Re: Inlining of couple of functions in pl_exec.c improves performance - Mailing list pgsql-hackers

From Tom Lane
Subject Re: Inlining of couple of functions in pl_exec.c improves performance
Date
Msg-id 1046810.1593805777@sss.pgh.pa.us
Whole thread Raw
In response to Re: Inlining of couple of functions in pl_exec.c improves performance  (Amit Khandekar <amitdkhan.pg@gmail.com>)
Responses Re: Inlining of couple of functions in pl_exec.c improves performance
Re: Inlining of couple of functions in pl_exec.c improves performance
List pgsql-hackers
I did some performance testing on 0001+0002 here, and found that
for me, there's basically no change on x86_64 but a win of 2 to 3
percent on aarch64, using Pavel's pi_est_1() as a representative
case for simple plpgsql statements.  That squares with your original
results I believe.  It's not clear to me whether any of the later
tests in this thread measured these changes in isolation, or only
with 0003 added.

Anyway, that's good enough for me, so I pushed 0001+0002 after a
little bit of additional cosmetic tweaking.

I attach your original 0003 here (it still applies, with some line
offsets).  That's just so the cfbot doesn't get confused about what
it's supposed to test now.

            regards, tom lane

From 56aac7dff8243ff6dc9b8e72651cb1d9a018f1b3 Mon Sep 17 00:00:00 2001
From: Amit Khandekar <amitdkhan.pg@gmail.com>
Date: Sat, 23 May 2020 21:53:24 +0800
Subject: [PATCH 3/3] Inline exec_cast_value().

This function does not do the casting if not required. So move the
code that actually does the cast into a separate function, so as to
reduce the exec_cast_value() code and make it inline.

There are frequent calls of this function, so inlining it has shown to
improve performance by as much as 14%
---
 src/pl/plpgsql/src/pl_exec.c | 63 ++++++++++++++++++++++++------------
 1 file changed, 43 insertions(+), 20 deletions(-)

diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index d5377a6dad..4028a3f0f6 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -425,10 +425,14 @@ static void instantiate_empty_record_variable(PLpgSQL_execstate *estate,
                                               PLpgSQL_rec *rec);
 static char *convert_value_to_string(PLpgSQL_execstate *estate,
                                      Datum value, Oid valtype);
-static Datum exec_cast_value(PLpgSQL_execstate *estate,
+static inline Datum exec_cast_value(PLpgSQL_execstate *estate,
                              Datum value, bool *isnull,
                              Oid valtype, int32 valtypmod,
                              Oid reqtype, int32 reqtypmod);
+static Datum do_cast_value(PLpgSQL_execstate *estate,
+                Datum value, bool *isnull,
+                Oid valtype, int32 valtypmod,
+                Oid reqtype, int32 reqtypmod);
 static plpgsql_CastHashEntry *get_cast_hashentry(PLpgSQL_execstate *estate,
                                                  Oid srctype, int32 srctypmod,
                                                  Oid dsttype, int32 dsttypmod);
@@ -7764,9 +7768,11 @@ convert_value_to_string(PLpgSQL_execstate *estate, Datum value, Oid valtype)
  * also contain the result Datum if we have to do a conversion to a pass-
  * by-reference data type.  Be sure to do an exec_eval_cleanup() call when
  * done with the result.
+ * The actual code to cast is kept outside of this function, to keep it short
+ * since it is an inline function, being called frequently.
  * ----------
  */
-static Datum
+static inline Datum
 exec_cast_value(PLpgSQL_execstate *estate,
                 Datum value, bool *isnull,
                 Oid valtype, int32 valtypmod,
@@ -7777,31 +7783,48 @@ exec_cast_value(PLpgSQL_execstate *estate,
      */
     if (valtype != reqtype ||
         (valtypmod != reqtypmod && reqtypmod != -1))
-    {
-        plpgsql_CastHashEntry *cast_entry;
+        value = do_cast_value(estate, value, isnull, valtype, valtypmod,
+                              reqtype, reqtypmod);

-        cast_entry = get_cast_hashentry(estate,
-                                        valtype, valtypmod,
-                                        reqtype, reqtypmod);
-        if (cast_entry)
-        {
-            ExprContext *econtext = estate->eval_econtext;
-            MemoryContext oldcontext;
+    return value;
+}

-            oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
+/* ----------
+ * do_cast_value            cast the input value.
+ *
+ * Returns the cast value.
+ * Check comments in the wrapper function exec_cast_value().
+ * ----------
+ */
+static Datum
+do_cast_value(PLpgSQL_execstate *estate,
+                Datum value, bool *isnull,
+                Oid valtype, int32 valtypmod,
+                Oid reqtype, int32 reqtypmod)
+{
+    plpgsql_CastHashEntry *cast_entry;

-            econtext->caseValue_datum = value;
-            econtext->caseValue_isNull = *isnull;
+    cast_entry = get_cast_hashentry(estate,
+                                    valtype, valtypmod,
+                                    reqtype, reqtypmod);
+    if (cast_entry)
+    {
+        ExprContext *econtext = estate->eval_econtext;
+        MemoryContext oldcontext;

-            cast_entry->cast_in_use = true;
+        oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));

-            value = ExecEvalExpr(cast_entry->cast_exprstate, econtext,
-                                 isnull);
+        econtext->caseValue_datum = value;
+        econtext->caseValue_isNull = *isnull;

-            cast_entry->cast_in_use = false;
+        cast_entry->cast_in_use = true;

-            MemoryContextSwitchTo(oldcontext);
-        }
+        value = ExecEvalExpr(cast_entry->cast_exprstate, econtext,
+                             isnull);
+
+        cast_entry->cast_in_use = false;
+
+        MemoryContextSwitchTo(oldcontext);
     }

     return value;
--
2.17.1


pgsql-hackers by date:

Previous
From: Pavel Stehule
Date:
Subject: Re: pro pametniky -historie vzniku PL/SQL
Next
From: Alvaro Herrera
Date:
Subject: Re: Default setting for enable_hashagg_disk (hash_mem)