Skip to content

Commit 67b2670

Browse files
committed
expression eval: Fix EEOP_JSON_CONSTRUCTOR and EEOP_JSONEXPR size.
The new expression step types increased the size of ExprEvalStep by ~4 for all types of expression steps, slowing down expression evaluation noticeably. Move them out of line. There's other issues with these expression steps, but addressing them is largely independent of this aspect. Author: Andres Freund <andres@anarazel.de> Reviewed-By: Andrew Dunstan <andrew@dunslane.net> Discussion: https://postgr.es/m/20220616233130.rparivafipt6doj3@alap3.anarazel.de Backpatch: 15-
1 parent 3f8148c commit 67b2670

File tree

4 files changed

+170
-140
lines changed

4 files changed

+170
-140
lines changed

src/backend/executor/execExpr.c

Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2470,32 +2470,38 @@ ExecInitExprRec(Expr *node, ExprState *state,
24702470
}
24712471
else
24722472
{
2473+
JsonConstructorExprState *jcstate;
2474+
2475+
jcstate = palloc0(sizeof(JsonConstructorExprState));
2476+
24732477
scratch.opcode = EEOP_JSON_CONSTRUCTOR;
2474-
scratch.d.json_constructor.constructor = ctor;
2475-
scratch.d.json_constructor.arg_values = palloc(sizeof(Datum) * nargs);
2476-
scratch.d.json_constructor.arg_nulls = palloc(sizeof(bool) * nargs);
2477-
scratch.d.json_constructor.arg_types = palloc(sizeof(Oid) * nargs);
2478-
scratch.d.json_constructor.nargs = nargs;
2478+
scratch.d.json_constructor.jcstate = jcstate;
2479+
2480+
jcstate->constructor = ctor;
2481+
jcstate->arg_values = palloc(sizeof(Datum) * nargs);
2482+
jcstate->arg_nulls = palloc(sizeof(bool) * nargs);
2483+
jcstate->arg_types = palloc(sizeof(Oid) * nargs);
2484+
jcstate->nargs = nargs;
24792485

24802486
foreach(lc, args)
24812487
{
24822488
Expr *arg = (Expr *) lfirst(lc);
24832489

2484-
scratch.d.json_constructor.arg_types[argno] = exprType((Node *) arg);
2490+
jcstate->arg_types[argno] = exprType((Node *) arg);
24852491

24862492
if (IsA(arg, Const))
24872493
{
24882494
/* Don't evaluate const arguments every round */
24892495
Const *con = (Const *) arg;
24902496

2491-
scratch.d.json_constructor.arg_values[argno] = con->constvalue;
2492-
scratch.d.json_constructor.arg_nulls[argno] = con->constisnull;
2497+
jcstate->arg_values[argno] = con->constvalue;
2498+
jcstate->arg_nulls[argno] = con->constisnull;
24932499
}
24942500
else
24952501
{
24962502
ExecInitExprRec(arg, state,
2497-
&scratch.d.json_constructor.arg_values[argno],
2498-
&scratch.d.json_constructor.arg_nulls[argno]);
2503+
&jcstate->arg_values[argno],
2504+
&jcstate->arg_nulls[argno]);
24992505
}
25002506
argno++;
25012507
}
@@ -2506,14 +2512,14 @@ ExecInitExprRec(Expr *node, ExprState *state,
25062512
bool is_jsonb =
25072513
ctor->returning->format->format_type == JS_FORMAT_JSONB;
25082514

2509-
scratch.d.json_constructor.arg_type_cache =
2510-
palloc(sizeof(*scratch.d.json_constructor.arg_type_cache) * nargs);
2515+
jcstate->arg_type_cache =
2516+
palloc(sizeof(*jcstate->arg_type_cache) * nargs);
25112517

25122518
for (int i = 0; i < nargs; i++)
25132519
{
25142520
int category;
25152521
Oid outfuncid;
2516-
Oid typid = scratch.d.json_constructor.arg_types[i];
2522+
Oid typid = jcstate->arg_types[i];
25172523

25182524
if (is_jsonb)
25192525
{
@@ -2532,8 +2538,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
25322538
category = (int) jscat;
25332539
}
25342540

2535-
scratch.d.json_constructor.arg_type_cache[i].outfuncid = outfuncid;
2536-
scratch.d.json_constructor.arg_type_cache[i].category = category;
2541+
jcstate->arg_type_cache[i].outfuncid = outfuncid;
2542+
jcstate->arg_type_cache[i].category = category;
25372543
}
25382544
}
25392545

@@ -2572,41 +2578,44 @@ ExecInitExprRec(Expr *node, ExprState *state,
25722578
case T_JsonExpr:
25732579
{
25742580
JsonExpr *jexpr = castNode(JsonExpr, node);
2581+
JsonExprState *jsestate = palloc0(sizeof(JsonExprState));
25752582
ListCell *argexprlc;
25762583
ListCell *argnamelc;
25772584

25782585
scratch.opcode = EEOP_JSONEXPR;
2579-
scratch.d.jsonexpr.jsexpr = jexpr;
2586+
scratch.d.jsonexpr.jsestate = jsestate;
2587+
2588+
jsestate->jsexpr = jexpr;
25802589

2581-
scratch.d.jsonexpr.formatted_expr =
2582-
palloc(sizeof(*scratch.d.jsonexpr.formatted_expr));
2590+
jsestate->formatted_expr =
2591+
palloc(sizeof(*jsestate->formatted_expr));
25832592

25842593
ExecInitExprRec((Expr *) jexpr->formatted_expr, state,
2585-
&scratch.d.jsonexpr.formatted_expr->value,
2586-
&scratch.d.jsonexpr.formatted_expr->isnull);
2594+
&jsestate->formatted_expr->value,
2595+
&jsestate->formatted_expr->isnull);
25872596

2588-
scratch.d.jsonexpr.pathspec =
2589-
palloc(sizeof(*scratch.d.jsonexpr.pathspec));
2597+
jsestate->pathspec =
2598+
palloc(sizeof(*jsestate->pathspec));
25902599

25912600
ExecInitExprRec((Expr *) jexpr->path_spec, state,
2592-
&scratch.d.jsonexpr.pathspec->value,
2593-
&scratch.d.jsonexpr.pathspec->isnull);
2601+
&jsestate->pathspec->value,
2602+
&jsestate->pathspec->isnull);
25942603

2595-
scratch.d.jsonexpr.res_expr =
2596-
palloc(sizeof(*scratch.d.jsonexpr.res_expr));
2604+
jsestate->res_expr =
2605+
palloc(sizeof(*jsestate->res_expr));
25972606

2598-
scratch.d.jsonexpr.result_expr = jexpr->result_coercion
2607+
jsestate->result_expr = jexpr->result_coercion
25992608
? ExecInitExprWithCaseValue((Expr *) jexpr->result_coercion->expr,
26002609
state->parent,
2601-
&scratch.d.jsonexpr.res_expr->value,
2602-
&scratch.d.jsonexpr.res_expr->isnull)
2610+
&jsestate->res_expr->value,
2611+
&jsestate->res_expr->isnull)
26032612
: NULL;
26042613

2605-
scratch.d.jsonexpr.default_on_empty = !jexpr->on_empty ? NULL :
2614+
jsestate->default_on_empty = !jexpr->on_empty ? NULL :
26062615
ExecInitExpr((Expr *) jexpr->on_empty->default_expr,
26072616
state->parent);
26082617

2609-
scratch.d.jsonexpr.default_on_error =
2618+
jsestate->default_on_error =
26102619
ExecInitExpr((Expr *) jexpr->on_error->default_expr,
26112620
state->parent);
26122621

@@ -2617,11 +2626,11 @@ ExecInitExprRec(Expr *node, ExprState *state,
26172626

26182627
/* lookup the result type's input function */
26192628
getTypeInputInfo(jexpr->returning->typid, &typinput,
2620-
&scratch.d.jsonexpr.input.typioparam);
2621-
fmgr_info(typinput, &scratch.d.jsonexpr.input.func);
2629+
&jsestate->input.typioparam);
2630+
fmgr_info(typinput, &jsestate->input.func);
26222631
}
26232632

2624-
scratch.d.jsonexpr.args = NIL;
2633+
jsestate->args = NIL;
26252634

26262635
forboth(argexprlc, jexpr->passing_values,
26272636
argnamelc, jexpr->passing_names)
@@ -2640,11 +2649,11 @@ ExecInitExprRec(Expr *node, ExprState *state,
26402649
var->value = (Datum) 0;
26412650
var->isnull = true;
26422651

2643-
scratch.d.jsonexpr.args =
2644-
lappend(scratch.d.jsonexpr.args, var);
2652+
jsestate->args =
2653+
lappend(jsestate->args, var);
26452654
}
26462655

2647-
scratch.d.jsonexpr.cache = NULL;
2656+
jsestate->cache = NULL;
26482657

26492658
if (jexpr->coercions)
26502659
{
@@ -2653,13 +2662,13 @@ ExecInitExprRec(Expr *node, ExprState *state,
26532662
Datum *caseval;
26542663
bool *casenull;
26552664

2656-
scratch.d.jsonexpr.coercion_expr =
2657-
palloc(sizeof(*scratch.d.jsonexpr.coercion_expr));
2665+
jsestate->coercion_expr =
2666+
palloc(sizeof(*jsestate->coercion_expr));
26582667

2659-
caseval = &scratch.d.jsonexpr.coercion_expr->value;
2660-
casenull = &scratch.d.jsonexpr.coercion_expr->isnull;
2668+
caseval = &jsestate->coercion_expr->value;
2669+
casenull = &jsestate->coercion_expr->isnull;
26612670

2662-
for (cstate = &scratch.d.jsonexpr.coercions.null,
2671+
for (cstate = &jsestate->coercions.null,
26632672
coercion = &jexpr->coercions->null;
26642673
coercion <= &jexpr->coercions->composite;
26652674
coercion++, cstate++)

0 commit comments

Comments
 (0)