Skip to content

Commit f5970a5

Browse files
author
Nikita Glukhov
committed
Optimize expanded object flattening: add context
1 parent d42f3a0 commit f5970a5

File tree

10 files changed

+63
-44
lines changed

10 files changed

+63
-44
lines changed

src/backend/access/common/detoast.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,12 @@ detoast_external_attr(struct varlena *attr)
8383
*/
8484
ExpandedObjectHeader *eoh;
8585
Size resultsize;
86+
void *context;
8687

8788
eoh = DatumGetEOHP(PointerGetDatum(attr));
88-
resultsize = EOH_get_flat_size(eoh);
89+
resultsize = EOH_get_flat_size(eoh, &context);
8990
result = (struct varlena *) palloc(resultsize);
90-
EOH_flatten_into(eoh, (void *) result, resultsize);
91+
EOH_flatten_into(eoh, (void *) result, resultsize, &context);
9192
}
9293
else
9394
{
@@ -525,7 +526,7 @@ toast_raw_datum_size(Datum value)
525526
}
526527
else if (VARATT_IS_EXTERNAL_EXPANDED(attr))
527528
{
528-
result = EOH_get_flat_size(DatumGetEOHP(value));
529+
result = EOH_get_flat_size(DatumGetEOHP(value), NULL);
529530
}
530531
else if (VARATT_IS_COMPRESSED(attr))
531532
{
@@ -585,7 +586,7 @@ toast_datum_size(Datum value)
585586
}
586587
else if (VARATT_IS_EXTERNAL_EXPANDED(attr))
587588
{
588-
result = EOH_get_flat_size(DatumGetEOHP(value));
589+
result = EOH_get_flat_size(DatumGetEOHP(value), NULL);
589590
}
590591
else if (VARATT_IS_SHORT(attr))
591592
{

src/backend/access/common/heaptuple.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ heap_compute_data_size(TupleDesc tupleDesc,
152152
* tuple doesn't depend on it
153153
*/
154154
data_length = att_align_nominal(data_length, atti->attalign);
155-
data_length += EOH_get_flat_size(DatumGetEOHP(val));
155+
data_length += EOH_get_flat_size(DatumGetEOHP(val), NULL);
156156
}
157157
else
158158
{
@@ -233,11 +233,12 @@ fill_val(Form_pg_attribute att,
233233
* constructed tuple doesn't depend on it
234234
*/
235235
ExpandedObjectHeader *eoh = DatumGetEOHP(datum);
236+
void *context;
236237

237238
data = (char *) att_align_nominal(data,
238239
att->attalign);
239-
data_length = EOH_get_flat_size(eoh);
240-
EOH_flatten_into(eoh, data, data_length);
240+
data_length = EOH_get_flat_size(eoh, &context);
241+
EOH_flatten_into(eoh, data, data_length, &context);
241242
}
242243
else
243244
{

src/backend/executor/execTuples.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ tts_virtual_materialize(TupleTableSlot *slot)
178178
* slot doesn't depend on it.
179179
*/
180180
sz = att_align_nominal(sz, att->attalign);
181-
sz += EOH_get_flat_size(DatumGetEOHP(val));
181+
sz += EOH_get_flat_size(DatumGetEOHP(val), NULL);
182182
}
183183
else
184184
{
@@ -216,11 +216,12 @@ tts_virtual_materialize(TupleTableSlot *slot)
216216
* slot doesn't depend on it.
217217
*/
218218
ExpandedObjectHeader *eoh = DatumGetEOHP(val);
219+
void *context;
219220

220221
data = (char *) att_align_nominal(data,
221222
att->attalign);
222-
data_length = EOH_get_flat_size(eoh);
223-
EOH_flatten_into(eoh, data, data_length);
223+
data_length = EOH_get_flat_size(eoh, &context);
224+
EOH_flatten_into(eoh, data, data_length, &context);
224225

225226
slot->tts_values[natt] = PointerGetDatum(data);
226227
data += data_length;

src/backend/utils/adt/array_expanded.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121

2222

2323
/* "Methods" required for an expanded object */
24-
static Size EA_get_flat_size(ExpandedObjectHeader *eohptr);
24+
static Size EA_get_flat_size(ExpandedObjectHeader *eohptr, void **context);
2525
static void EA_flatten_into(ExpandedObjectHeader *eohptr,
26-
void *result, Size allocated_size);
26+
void *result, Size allocated_size, void **context);
2727

2828
static const ExpandedObjectMethods EA_methods =
2929
{
@@ -230,7 +230,7 @@ copy_byval_expanded_array(ExpandedArrayHeader *eah,
230230
* get_flat_size method for expanded arrays
231231
*/
232232
static Size
233-
EA_get_flat_size(ExpandedObjectHeader *eohptr)
233+
EA_get_flat_size(ExpandedObjectHeader *eohptr, void **context)
234234
{
235235
ExpandedArrayHeader *eah = (ExpandedArrayHeader *) eohptr;
236236
int nelems;
@@ -291,7 +291,7 @@ EA_get_flat_size(ExpandedObjectHeader *eohptr)
291291
*/
292292
static void
293293
EA_flatten_into(ExpandedObjectHeader *eohptr,
294-
void *result, Size allocated_size)
294+
void *result, Size allocated_size, void **context)
295295
{
296296
ExpandedArrayHeader *eah = (ExpandedArrayHeader *) eohptr;
297297
ArrayType *aresult = (ArrayType *) result;

src/backend/utils/adt/datum.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,11 @@ datumCopy(Datum value, bool typByVal, int typLen)
145145
ExpandedObjectHeader *eoh = DatumGetEOHP(value);
146146
Size resultsize;
147147
char *resultptr;
148+
void *context;
148149

149-
resultsize = EOH_get_flat_size(eoh);
150+
resultsize = EOH_get_flat_size(eoh, &context);
150151
resultptr = (char *) palloc(resultsize);
151-
EOH_flatten_into(eoh, (void *) resultptr, resultsize);
152+
EOH_flatten_into(eoh, (void *) resultptr, resultsize, &context);
152153
res = PointerGetDatum(resultptr);
153154
}
154155
else
@@ -370,7 +371,9 @@ datumEstimateSpace(Datum value, bool isnull, bool typByVal, int typLen)
370371
VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(value)))
371372
{
372373
/* Expanded objects need to be flattened, see comment below */
373-
sz += EOH_get_flat_size(DatumGetEOHP(value));
374+
ExpandedObjectHeader *eoh = DatumGetEOHP(value);
375+
376+
sz += EOH_get_flat_size(eoh, NULL);
374377
}
375378
else
376379
sz += datumGetSize(value, typByVal, typLen);
@@ -408,6 +411,7 @@ datumSerialize(Datum value, bool isnull, bool typByVal, int typLen,
408411
char **start_address)
409412
{
410413
ExpandedObjectHeader *eoh = NULL;
414+
void *context;
411415
int header;
412416

413417
/* Write header word. */
@@ -419,7 +423,7 @@ datumSerialize(Datum value, bool isnull, bool typByVal, int typLen,
419423
VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(value)))
420424
{
421425
eoh = DatumGetEOHP(value);
422-
header = EOH_get_flat_size(eoh);
426+
header = EOH_get_flat_size(eoh, &context);
423427
}
424428
else
425429
header = datumGetSize(value, typByVal, typLen);
@@ -443,7 +447,7 @@ datumSerialize(Datum value, bool isnull, bool typByVal, int typLen,
443447
* so we can't store directly to *start_address.
444448
*/
445449
tmp = (char *) palloc(header);
446-
EOH_flatten_into(eoh, (void *) tmp, header);
450+
EOH_flatten_into(eoh, (void *) tmp, header, &context);
447451
memcpy(*start_address, tmp, header);
448452
*start_address += header;
449453

src/backend/utils/adt/expandeddatum.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,16 @@ EOH_init_header(ExpandedObjectHeader *eohptr,
7373
*/
7474

7575
Size
76-
EOH_get_flat_size(ExpandedObjectHeader *eohptr)
76+
EOH_get_flat_size(ExpandedObjectHeader *eohptr, void **context)
7777
{
78-
return eohptr->eoh_methods->get_flat_size(eohptr);
78+
return eohptr->eoh_methods->get_flat_size(eohptr, context);
7979
}
8080

8181
void
8282
EOH_flatten_into(ExpandedObjectHeader *eohptr,
83-
void *result, Size allocated_size)
83+
void *result, Size allocated_size, void **context)
8484
{
85-
eohptr->eoh_methods->flatten_into(eohptr, result, allocated_size);
85+
eohptr->eoh_methods->flatten_into(eohptr, result, allocated_size, context);
8686
}
8787

8888
/*

src/backend/utils/adt/expandedrecord.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131

3232

3333
/* "Methods" required for an expanded object */
34-
static Size ER_get_flat_size(ExpandedObjectHeader *eohptr);
34+
static Size ER_get_flat_size(ExpandedObjectHeader *eohptr, void **context);
3535
static void ER_flatten_into(ExpandedObjectHeader *eohptr,
36-
void *result, Size allocated_size);
36+
void *result, Size allocated_size, void **context);
3737

3838
static const ExpandedObjectMethods ER_methods =
3939
{
@@ -649,7 +649,7 @@ make_expanded_record_from_datum(Datum recorddatum, MemoryContext parentcontext)
649649
* memory leaks from activities such as detoasting.
650650
*/
651651
static Size
652-
ER_get_flat_size(ExpandedObjectHeader *eohptr)
652+
ER_get_flat_size(ExpandedObjectHeader *eohptr, void **context)
653653
{
654654
ExpandedRecordHeader *erh = (ExpandedRecordHeader *) eohptr;
655655
TupleDesc tupdesc;
@@ -762,7 +762,7 @@ ER_get_flat_size(ExpandedObjectHeader *eohptr)
762762
*/
763763
static void
764764
ER_flatten_into(ExpandedObjectHeader *eohptr,
765-
void *result, Size allocated_size)
765+
void *result, Size allocated_size, void **context)
766766
{
767767
ExpandedRecordHeader *erh = (ExpandedRecordHeader *) eohptr;
768768
HeapTupleHeader tuphdr = (HeapTupleHeader) result;

src/backend/utils/adt/json_generic.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ JsonInit(Json *json)
678678
}
679679

680680
static Size
681-
jsonGetFlatSize2(Json *json)
681+
jsonGetFlatSize2(Json *json, void **context)
682682
{
683683
Size size;
684684

@@ -693,7 +693,10 @@ jsonGetFlatSize2(Json *json)
693693
{
694694
char *str = JsonToCString(&json->root);
695695
size = VARHDRSZ + strlen(str);
696-
pfree(str);
696+
if (context)
697+
*context = str;
698+
else
699+
pfree(str);
697700
}
698701
}
699702
#endif
@@ -709,7 +712,10 @@ jsonGetFlatSize2(Json *json)
709712
JsonValue val;
710713
void *js = JsonValueToJsonb(JsonToJsonValue(json, &val));
711714
size = VARSIZE(js);
712-
pfree(js);
715+
if (context)
716+
*context = js;
717+
else
718+
pfree(js);
713719
}
714720
}
715721
#endif
@@ -718,7 +724,7 @@ jsonGetFlatSize2(Json *json)
718724
}
719725

720726
static void *
721-
jsonFlatten(Json *json)
727+
jsonFlatten(Json *json, void **context)
722728
{
723729
#ifdef JSON_FLATTEN_INTO_TARGET
724730
if (json->is_json)
@@ -729,7 +735,7 @@ jsonFlatten(Json *json)
729735
return cstring_to_text_with_len(json->root.data, json->root.len);
730736
else
731737
{
732-
char *str = JsonToCString(JsonRoot(json));
738+
char *str = context ? (char *) *context : JsonToCString(JsonRoot(json));
733739
text *text = cstring_to_text(str);
734740
pfree(str);
735741
return text;
@@ -748,6 +754,8 @@ jsonFlatten(Json *json)
748754
memcpy(VARDATA(res), json->root.data, json->root.len);
749755
return res;
750756
}
757+
else if (context)
758+
return *context;
751759
else
752760
{
753761
JsonValue val;
@@ -758,7 +766,7 @@ jsonFlatten(Json *json)
758766
}
759767

760768
static Size
761-
jsonGetFlatSize(ExpandedObjectHeader *eoh)
769+
jsonGetFlatSize(ExpandedObjectHeader *eoh, void **context)
762770
{
763771
Json *json = (Json *) eoh;
764772

@@ -773,19 +781,20 @@ jsonGetFlatSize(ExpandedObjectHeader *eoh)
773781
{
774782
tmp.data = NULL;
775783
tmp.ops = flatContainerOps;
776-
tmp.len = jsonGetFlatSize2(json) - VARHDRSZ;
784+
tmp.len = jsonGetFlatSize2(json, context) - VARHDRSZ;
777785
flat = &tmp;
778786
}
779787

780788
return jsonGetExtendedSize(flat);
781789
}
782790
#else
783-
return jsonGetFlatSize2(json);
791+
return jsonGetFlatSize2(json, context);
784792
#endif
785793
}
786794

787795
static void
788-
jsonFlattenInto(ExpandedObjectHeader *eoh, void *result, Size allocated_size)
796+
jsonFlattenInto(ExpandedObjectHeader *eoh, void *result, Size allocated_size,
797+
void **context)
789798
{
790799
Json *json = (Json *) eoh;
791800

@@ -799,7 +808,7 @@ jsonFlattenInto(ExpandedObjectHeader *eoh, void *result, Size allocated_size)
799808

800809
if (flat->ops == &jsonvContainerOps)
801810
{
802-
tmpData = jsonFlatten(json);
811+
tmpData = jsonFlatten(json, context);
803812

804813
tmp.ops = flatContainerOps;
805814
tmp.data = VARDATA(tmpData);
@@ -815,7 +824,7 @@ jsonFlattenInto(ExpandedObjectHeader *eoh, void *result, Size allocated_size)
815824
}
816825
#else
817826
{
818-
void *data = jsonFlatten(json);
827+
void *data = jsonFlatten(json, context);
819828
memcpy(result, data, allocated_size);
820829
pfree(data);
821830
}

src/include/utils/expandeddatum.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,11 @@
6464
* get_flat_size twice, so it's worthwhile to make sure that that doesn't
6565
* incur too much overhead.
6666
*/
67-
typedef Size (*EOM_get_flat_size_method) (ExpandedObjectHeader *eohptr);
67+
typedef Size (*EOM_get_flat_size_method) (ExpandedObjectHeader *eohptr,
68+
void **context);
6869
typedef void (*EOM_flatten_into_method) (ExpandedObjectHeader *eohptr,
69-
void *result, Size allocated_size);
70+
void *result, Size allocated_size,
71+
void **context);
7072

7173
/* Struct of function pointers for an expanded object's methods */
7274
typedef struct ExpandedObjectMethods
@@ -149,9 +151,9 @@ extern ExpandedObjectHeader *DatumGetEOHP(Datum d);
149151
extern void EOH_init_header(ExpandedObjectHeader *eohptr,
150152
const ExpandedObjectMethods *methods,
151153
MemoryContext obj_context);
152-
extern Size EOH_get_flat_size(ExpandedObjectHeader *eohptr);
154+
extern Size EOH_get_flat_size(ExpandedObjectHeader *eohptr, void **context);
153155
extern void EOH_flatten_into(ExpandedObjectHeader *eohptr,
154-
void *result, Size allocated_size);
156+
void *result, Size allocated_size, void **context);
155157
extern Datum MakeExpandedObjectReadOnlyInternal(Datum d);
156158
extern Datum TransferExpandedObject(Datum d, MemoryContext new_parent);
157159
extern void DeleteExpandedObject(Datum d);

src/pl/plpgsql/src/pl_exec.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -842,10 +842,11 @@ coerce_function_result_tuple(PLpgSQL_execstate *estate, TupleDesc tupdesc)
842842
*/
843843
Size resultsize;
844844
HeapTupleHeader tuphdr;
845+
void *context;
845846

846-
resultsize = EOH_get_flat_size(&erh->hdr);
847+
resultsize = EOH_get_flat_size(&erh->hdr, &context);
847848
tuphdr = (HeapTupleHeader) SPI_palloc(resultsize);
848-
EOH_flatten_into(&erh->hdr, (void *) tuphdr, resultsize);
849+
EOH_flatten_into(&erh->hdr, (void *) tuphdr, resultsize, &context);
849850
HeapTupleHeaderSetTypeId(tuphdr, tupdesc->tdtypeid);
850851
HeapTupleHeaderSetTypMod(tuphdr, tupdesc->tdtypmod);
851852
estate->retval = PointerGetDatum(tuphdr);

0 commit comments

Comments
 (0)