From e96b48c0779233ebe66f6bc0b44caad067d15d36 Mon Sep 17 00:00:00 2001 From: Matthias van de Meent Date: Mon, 12 Feb 2024 17:12:02 +0100 Subject: [PATCH v7 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 4077699cab..4c33908b66 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -270,6 +270,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