v6-0007-gen_node_support.pl-Optimize-serialization-of-fie.patch
application/octet-stream
Filename: v6-0007-gen_node_support.pl-Optimize-serialization-of-fie.patch
Type: application/octet-stream
Part: 5
Patch
Format: format-patch
Series: patch v6-0007
Subject: gen_node_support.pl: Optimize serialization of fields with copied values
| File | + | − |
|---|---|---|
| src/backend/nodes/gen_node_support.pl | 62 | 32 |
| src/backend/nodes/outfuncs.c | 3 | 0 |
| src/backend/nodes/readfuncs.c | 3 | 0 |
| src/include/nodes/primnodes.h | 2 | 2 |
From 089305ddbc433177e68cc173a396fc7392e4c9ed Mon Sep 17 00:00:00 2001
From: Matthias van de Meent <boekewurm+postgres@gmail.com>
Date: Mon, 12 Feb 2024 17:12:02 +0100
Subject: [PATCH v6 7/8] gen_node_support.pl: Optimize serialization of fields
with copied values
The Var node's [syn] fields often contain the same data as their non-syn
counterparts. We invent a new pg_node_attr()ibute that represents this
relation, which allows us to omit these fields from serialization when they
are indeed copies of the original fields.
---
src/backend/nodes/gen_node_support.pl | 94 ++++++++++++++++++---------
src/backend/nodes/outfuncs.c | 3 +
src/backend/nodes/readfuncs.c | 3 +
src/include/nodes/primnodes.h | 4 +-
4 files changed, 70 insertions(+), 34 deletions(-)
diff --git a/src/backend/nodes/gen_node_support.pl b/src/backend/nodes/gen_node_support.pl
index fda8c3a494..66661a3881 100644
--- a/src/backend/nodes/gen_node_support.pl
+++ b/src/backend/nodes/gen_node_support.pl
@@ -363,6 +363,10 @@ foreach my $infile (@ARGV)
{
$manual_nodetag_number{$in_struct} = $1;
}
+ elsif ($attr =~ /^default_ref\(([\w\d."'-]+)\)$/)
+ {
+ # Unused at the node level
+ }
else
{
die
@@ -437,7 +441,7 @@ foreach my $infile (@ARGV)
}
# normal struct field
elsif ($line =~
- /^\s*(.+)\s*\b(\w+)(\[[\w\s+]+\])?\s*(?:pg_node_attr\(([\w(), ]*)\))?;/
+ /^\s*(.+)\s*\b(\w+)(\[[\w\s+]+\])?\s*(?:pg_node_attr\(([\w\d(), ."'-]*)\))?;/
)
{
if ($is_node_struct)
@@ -469,6 +473,7 @@ foreach my $infile (@ARGV)
if ( $attr !~ /^array_size\(\w+\)$/
&& $attr !~ /^copy_as\(\w+\)$/
&& $attr !~ /^read_as\(\w+\)$/
+ && $attr !~ /^default_ref\([\w\d."'-]+\)$/
&& !elem $attr,
qw(copy_as_scalar
equal_as_scalar
@@ -495,7 +500,7 @@ foreach my $infile (@ARGV)
}
# function pointer field
elsif ($line =~
- /^\s*([\w\s*]+)\s*\(\*(\w+)\)\s*\((.*)\)\s*(?:pg_node_attr\(([\w(), ]*)\))?;/
+ /^\s*([\w\s*]+)\s*\(\*(\w+)\)\s*\((.*)\)\s*(?:pg_node_attr\(([\w\d(), ."'-]*)\))?;/
)
{
if ($is_node_struct)
@@ -970,6 +975,15 @@ _read${n}(void)
my $array_size_field;
my $read_as_field;
my $read_write_ignore = 0;
+ # Type read/write macro suffix, "" for normal use, or "_DEFAULT" when
+ # value argument.
+ my $s = "";
+ # Default parameter to read/write macro. Includes comma separator so
+ # that MACRO_NAME$s($fieldname$defaultparam) is the full complete
+ # read/write expression for essentially all types.
+ # Note that this (currently) only works for scalar values.
+ my $d = "";
+
foreach my $a (@a)
{
if ($a =~ /^array_size\(([\w.]+)\)$/)
@@ -988,6 +1002,19 @@ _read${n}(void)
{
$read_write_ignore = 1;
}
+ elsif ($a =~ /^default_ref\(([\w\d+."'-]+)\)$/)
+ {
+ $s = "_DEFAULT";
+ $d = ", NODE_FIELD($1)";
+ }
+ }
+
+ if ($s eq "_DEFAULT")
+ {
+ die "custom defaults for non-scalar fields are not supported\n\tat $n.$f"
+ unless (elem $t, @scalar_types or elem $t, @enum_types);
+ die "custom defaults for Location fields are not supported\n\tat $n.$f"
+ if ($t eq "Location");
}
if ($read_write_ignore)
@@ -1008,8 +1035,8 @@ _read${n}(void)
# select instructions by field type
if ($t eq 'bool')
{
- print $off "\tWRITE_BOOL_FIELD($f);\n";
- print $rff "\tREAD_BOOL_FIELD($f);\n" unless $no_read;
+ print $off "\tWRITE_BOOL_FIELD$s($f$d);\n";
+ print $rff "\tREAD_BOOL_FIELD$s($f$d);\n" unless $no_read;
}
elsif ($t eq 'Location')
{
@@ -1018,8 +1045,11 @@ _read${n}(void)
}
elsif ($t eq 'TypMod')
{
- print $off "\tWRITE_INT_FIELD_DEFAULT($f, -1);\n";
- print $rff "\tREAD_INT_FIELD_DEFAULT($f, -1);\n" unless $no_read;
+ # The default value of a TypMod fields is -1, rather than 0
+ # for normal int fields.
+ $d = ", -1" if ($d eq "");
+ print $off "\tWRITE_INT_FIELD_DEFAULT($f$d);\n";
+ print $rff "\tREAD_INT_FIELD_DEFAULT($f$d);\n" unless $no_read;
}
elsif ($t eq 'int'
|| $t eq 'int16'
@@ -1027,8 +1057,8 @@ _read${n}(void)
|| $t eq 'AttrNumber'
|| $t eq 'StrategyNumber')
{
- print $off "\tWRITE_INT_FIELD($f);\n";
- print $rff "\tREAD_INT_FIELD($f);\n" unless $no_read;
+ print $off "\tWRITE_INT_FIELD$s($f$d);\n";
+ print $rff "\tREAD_INT_FIELD$s($f$d);\n" unless $no_read;
}
elsif ($t eq 'uint32'
|| $t eq 'bits32'
@@ -1036,56 +1066,56 @@ _read${n}(void)
|| $t eq 'Index'
|| $t eq 'SubTransactionId')
{
- print $off "\tWRITE_UINT_FIELD($f);\n";
- print $rff "\tREAD_UINT_FIELD($f);\n" unless $no_read;
+ print $off "\tWRITE_UINT_FIELD$s($f$d);\n";
+ print $rff "\tREAD_UINT_FIELD$s($f$d);\n" unless $no_read;
}
elsif ($t eq 'uint64'
|| $t eq 'AclMode')
{
- print $off "\tWRITE_UINT64_FIELD($f);\n";
- print $rff "\tREAD_UINT64_FIELD($f);\n" unless $no_read;
+ print $off "\tWRITE_UINT64_FIELD$s($f$d);\n";
+ print $rff "\tREAD_UINT64_FIELD$s($f$d);\n" unless $no_read;
}
elsif ($t eq 'Oid' || $t eq 'RelFileNumber')
{
- print $off "\tWRITE_OID_FIELD($f);\n";
- print $rff "\tREAD_OID_FIELD($f);\n" unless $no_read;
+ print $off "\tWRITE_OID_FIELD$s($f$d);\n";
+ print $rff "\tREAD_OID_FIELD$s($f$d);\n" unless $no_read;
}
elsif ($t eq 'long')
{
- print $off "\tWRITE_LONG_FIELD($f);\n";
- print $rff "\tREAD_LONG_FIELD($f);\n" unless $no_read;
+ print $off "\tWRITE_LONG_FIELD$s($f$d);\n";
+ print $rff "\tREAD_LONG_FIELD$s($f$d);\n" unless $no_read;
}
elsif ($t eq 'char')
{
- print $off "\tWRITE_CHAR_FIELD($f);\n";
- print $rff "\tREAD_CHAR_FIELD($f);\n" unless $no_read;
+ print $off "\tWRITE_CHAR_FIELD$s($f$d);\n";
+ print $rff "\tREAD_CHAR_FIELD$s($f$d);\n" unless $no_read;
}
elsif ($t eq 'double')
{
- print $off "\tWRITE_FLOAT_FIELD($f);\n";
- print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+ print $off "\tWRITE_FLOAT_FIELD$s($f$d);\n";
+ print $rff "\tREAD_FLOAT_FIELD$s($f$d);\n" unless $no_read;
}
elsif ($t eq 'Cardinality')
{
- print $off "\tWRITE_FLOAT_FIELD($f);\n";
- print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+ print $off "\tWRITE_FLOAT_FIELD$s($f$d);\n";
+ print $rff "\tREAD_FLOAT_FIELD$s($f$d);\n" unless $no_read;
}
elsif ($t eq 'Cost')
{
- print $off "\tWRITE_FLOAT_FIELD($f);\n";
- print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+ print $off "\tWRITE_FLOAT_FIELD$s($f$d);\n";
+ print $rff "\tREAD_FLOAT_FIELD$s($f$d);\n" unless $no_read;
}
elsif ($t eq 'QualCost')
{
- print $off "\tWRITE_FLOAT_FIELD($f.startup);\n";
- print $off "\tWRITE_FLOAT_FIELD($f.per_tuple);\n";
- print $rff "\tREAD_FLOAT_FIELD($f.startup);\n" unless $no_read;
- print $rff "\tREAD_FLOAT_FIELD($f.per_tuple);\n" unless $no_read;
+ print $off "\tWRITE_FLOAT_FIELD$s($f.startup$d);\n";
+ print $off "\tWRITE_FLOAT_FIELD$s($f.per_tuple$d);\n";
+ print $rff "\tREAD_FLOAT_FIELD$s($f.startup$d);\n" unless $no_read;
+ print $rff "\tREAD_FLOAT_FIELD$s($f.per_tuple$d);\n" unless $no_read;
}
elsif ($t eq 'Selectivity')
{
- print $off "\tWRITE_FLOAT_FIELD($f);\n";
- print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+ print $off "\tWRITE_FLOAT_FIELD$s($f$d);\n";
+ print $rff "\tREAD_FLOAT_FIELD$s($f$d);\n" unless $no_read;
}
elsif ($t eq 'char*')
{
@@ -1099,8 +1129,8 @@ _read${n}(void)
}
elsif (elem $t, @enum_types)
{
- print $off "\tWRITE_ENUM_FIELD($f, $t);\n";
- print $rff "\tREAD_ENUM_FIELD($f, $t);\n" unless $no_read;
+ print $off "\tWRITE_ENUM_FIELD$s($f, $t$d);\n";
+ print $rff "\tREAD_ENUM_FIELD$s($f, $t$d);\n" unless $no_read;
}
# arrays of scalar types
elsif ($t =~ /^(\w+)(\*|\[\w+\])$/ and elem $1, @scalar_types)
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index cfafdaa033..e64f3c5975 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -245,6 +245,9 @@ static void outDouble(StringInfo str, double d);
} \
} while (0)
+/* Accessing a node's field goes like this */
+#define NODE_FIELD(fldname) (node->fldname)
+
#define booltostr(x) ((x) ? "true" : "false")
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index d77dd30f34..5e082a2c37 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -269,6 +269,9 @@
local_node->fldname = NULL; \
} while (0)
+/* Accessing a node's field goes like this */
+#define NODE_FIELD(fldname) (local_node->fldname)
+
/* Routine exit */
#define READ_DONE() \
return local_node
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 94282497d7..9dd60ad5c5 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -274,9 +274,9 @@ typedef struct Var
* their varno/varattno match.
*/
/* syntactic relation index (0 if unknown) */
- Index varnosyn pg_node_attr(equal_ignore, query_jumble_ignore);
+ Index varnosyn pg_node_attr(equal_ignore, query_jumble_ignore, default_ref(varno));
/* syntactic attribute number */
- AttrNumber varattnosyn pg_node_attr(equal_ignore, query_jumble_ignore);
+ AttrNumber varattnosyn pg_node_attr(equal_ignore, query_jumble_ignore, default_ref(varattno));
/* token location, or -1 if unknown */
Location location;
--
2.40.1