Cache typlens of a SQL function's input arguments.
authorTom Lane <[email protected]>
Thu, 17 Apr 2025 16:56:40 +0000 (12:56 -0400)
committerTom Lane <[email protected]>
Thu, 17 Apr 2025 16:56:40 +0000 (12:56 -0400)
This gets rid of repetitive get_typlen calls in postquel_sub_params,
which show up as costing a few percent of the runtime in simple test
cases (more with more parameters).

In combination with the preceding es, this gets us most of the
way back down to the amount of per-call overhead that functions.c
had before commit 0dca5d68d.  There are some more things that could
be done, but this seems like an okay place to stop for v18.

src/backend/executor/functions.c

index 135fddda3fc4f278fa04a35c2e71a840d4822603..e0bca7cb81cab8500f179d7884f0e462432357a9 100644 (file)
@@ -116,6 +116,7 @@ typedef struct SQLFunctionHashEntry
    char       *src;            /* function body text (for error msgs) */
 
    SQLFunctionParseInfoPtr pinfo;  /* data for parser callback hooks */
+   int16      *argtyplen;      /* lengths of the input argument types */
 
    Oid         rettype;        /* actual return type */
    int16       typlen;         /* length of the return type */
@@ -1100,6 +1101,15 @@ sql_compile_callback(FunctionCallInfo fcinfo,
                                            PG_GET_COLLATION());
    MemoryContextSwitchTo(oldcontext);
 
+   /*
+    * Now that we have the resolved argument types, collect their typlens for
+    * use in postquel_sub_params.
+    */
+   func->argtyplen = (int16 *)
+       MemoryContextAlloc(hcontext, func->pinfo->nargs * sizeof(int16));
+   for (int i = 0; i < func->pinfo->nargs; i++)
+       func->argtyplen[i] = get_typlen(func->pinfo->argtypes[i]);
+
    /*
     * And of course we need the function body text.
     */
@@ -1427,6 +1437,7 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
    {
        ParamListInfo paramLI;
        Oid        *argtypes = fcache->func->pinfo->argtypes;
+       int16      *argtyplen = fcache->func->argtyplen;
 
        if (fcache->paramLI == NULL)
        {
@@ -1463,7 +1474,7 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
            prm->isnull = fcinfo->args[i].isnull;
            prm->value = MakeExpandedObjectReadOnly(fcinfo->args[i].value,
                                                    prm->isnull,
-                                                   get_typlen(argtypes[i]));
+                                                   argtyplen[i]);
            /* Allow the value to be substituted into custom plans */
            prm->pflags = PARAM_FLAG_CONST;
            prm->ptype = argtypes[i];