agora inbox for [email protected]  
help / color / mirror / Atom feed
[PATCH v3 05/17] meson: prereq: move snowball_create.sql creation into perl file.
10+ messages / 7 participants
[nested] [flat]

* [PATCH v3 05/17] meson: prereq: move snowball_create.sql creation into perl file.
@ 2021-03-08 22:59  Andres Freund <[email protected]>
  0 siblings, 0 replies; 10+ messages in thread

From: Andres Freund @ 2021-03-08 22:59 UTC (permalink / raw)

FIXME: deduplicate with Install.pm
---
 src/backend/snowball/Makefile           |  27 +-----
 src/backend/snowball/snowball_create.pl | 110 ++++++++++++++++++++++++
 2 files changed, 113 insertions(+), 24 deletions(-)
 create mode 100644 src/backend/snowball/snowball_create.pl

diff --git a/src/backend/snowball/Makefile b/src/backend/snowball/Makefile
index 50b9199910c..259104f8eb3 100644
--- a/src/backend/snowball/Makefile
+++ b/src/backend/snowball/Makefile
@@ -119,29 +119,8 @@ all: all-shared-lib $(SQLSCRIPT)
 
 include $(top_srcdir)/src/Makefile.shlib
 
-$(SQLSCRIPT): Makefile snowball_func.sql.in snowball.sql.in
-	echo '-- Language-specific snowball dictionaries' > $@
-	cat $(srcdir)/snowball_func.sql.in >> $@
-	@set -e; \
-	set $(LANGUAGES) ; \
-	while [ "$$#" -gt 0 ] ; \
-	do \
-		lang=$$1; shift; \
-		nonascdictname=$$lang; \
-		ascdictname=$$1; shift; \
-		if [ -s $(srcdir)/stopwords/$${lang}.stop ] ; then \
-			stop=", StopWords=$${lang}" ; \
-		else \
-			stop=""; \
-		fi; \
-		cat $(srcdir)/snowball.sql.in | \
-			sed -e "s#_LANGNAME_#$$lang#g" | \
-			sed -e "s#_DICTNAME_#$${lang}_stem#g" | \
-			sed -e "s#_CFGNAME_#$$lang#g" | \
-			sed -e "s#_ASCDICTNAME_#$${ascdictname}_stem#g" | \
-			sed -e "s#_NONASCDICTNAME_#$${nonascdictname}_stem#g" | \
-			sed -e "s#_STOPWORDS_#$$stop#g" ; \
-	done >> $@
+$(SQLSCRIPT): snowball_create.pl Makefile snowball_func.sql.in snowball.sql.in
+	$(PERL) $< --input ${srcdir} --output .
 
 install: all installdirs install-lib
 	$(INSTALL_DATA) $(SQLSCRIPT) '$(DESTDIR)$(datadir)'
@@ -171,4 +150,4 @@ uninstall: uninstall-lib
 	done
 
 clean distclean maintainer-clean: clean-lib
-	rm -f $(OBJS) $(SQLSCRIPT)
+	rm -f $(OBJS) $(SQLSCRIPT) snowball_create.dep
diff --git a/src/backend/snowball/snowball_create.pl b/src/backend/snowball/snowball_create.pl
new file mode 100644
index 00000000000..d9d79f3668f
--- /dev/null
+++ b/src/backend/snowball/snowball_create.pl
@@ -0,0 +1,110 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Getopt::Long;
+
+my $output_path = '';
+my $makefile_path = '';
+my $input_path = '';
+
+GetOptions(
+	'output:s'   => \$output_path,
+	'input:s'    => \$input_path) || usage();
+
+# Make sure input_path ends in a slash if needed.
+if ($input_path ne '' && substr($input_path, -1) ne '/')
+{
+	$output_path .= '/';
+}
+
+# Make sure output_path ends in a slash if needed.
+if ($output_path ne '' && substr($output_path, -1) ne '/')
+{
+	$output_path .= '/';
+}
+
+GenerateTsearchFiles();
+
+sub usage
+{
+	die <<EOM;
+Usage: snowball_create.pl --input/-i <path> --input <path>
+    --output        Output directory (default '.')
+    --input         Input directory
+
+snowball_create.pl creates snowball.sql from snowball.sql.in
+EOM
+}
+
+sub GenerateTsearchFiles
+{
+	my $target = shift;
+	my $output_file = "$output_path/snowball_create.sql";
+
+	print "Generating tsearch script...";
+	my $F;
+	my $D;
+	my $tmpl = read_file("$input_path/snowball.sql.in");
+	my $mf   = read_file("$input_path/Makefile");
+
+	open($D, '>', "$output_path/snowball_create.dep")
+	  || die "Could not write snowball_create.dep";
+
+	print $D "$output_file: $input_path/Makefile\n";
+	print $D "$output_file: $input_path/snowball.sql.in\n";
+	print $D "$output_file: $input_path/snowball_func.sql.in\n";
+
+	$mf =~ s{\\\r?\n}{}g;
+	$mf =~ /^LANGUAGES\s*=\s*(.*)$/m
+	  || die "Could not find LANGUAGES line in snowball Makefile\n";
+	my @pieces = split /\s+/, $1;
+	open($F, '>', $output_file)
+	  || die "Could not write snowball_create.sql";
+
+	print $F "-- Language-specific snowball dictionaries\n";
+
+	print $F read_file("$input_path/snowball_func.sql.in");
+
+	while ($#pieces > 0)
+	{
+		my $lang    = shift @pieces || last;
+		my $asclang = shift @pieces || last;
+		my $txt     = $tmpl;
+		my $stop    = '';
+		my $stopword_path = "$input_path/stopwords/$lang.stop";
+
+		if (-s "$stopword_path")
+		{
+			$stop = ", StopWords=$lang";
+
+			print $D "$output_file: $stopword_path\n";
+		}
+
+		$txt =~ s#_LANGNAME_#${lang}#gs;
+		$txt =~ s#_DICTNAME_#${lang}_stem#gs;
+		$txt =~ s#_CFGNAME_#${lang}#gs;
+		$txt =~ s#_ASCDICTNAME_#${asclang}_stem#gs;
+		$txt =~ s#_NONASCDICTNAME_#${lang}_stem#gs;
+		$txt =~ s#_STOPWORDS_#$stop#gs;
+		print $F $txt;
+		print ".";
+	}
+	close($F);
+	close($D);
+	print "\n";
+	return;
+}
+
+
+sub read_file
+{
+	my $filename = shift;
+	my $F;
+	local $/ = undef;
+	open($F, '<', $filename) || die "Could not open file $filename\n";
+	my $txt = <$F>;
+	close($F);
+
+	return $txt;
+}
-- 
2.23.0.385.gbc12974a89


--qozqt6hocm2wibt2
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v3-0006-meson-prereq-add-output-path-arg-in-generate-lwlo.patch"



^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* [PATCH v5 05/16] meson: prereq: move snowball_create.sql creation into perl file.
@ 2021-03-08 22:59  Andres Freund <[email protected]>
  0 siblings, 0 replies; 10+ messages in thread

From: Andres Freund @ 2021-03-08 22:59 UTC (permalink / raw)

FIXME: deduplicate with Install.pm
---
 src/backend/snowball/Makefile           |  27 +-----
 src/backend/snowball/snowball_create.pl | 110 ++++++++++++++++++++++++
 2 files changed, 113 insertions(+), 24 deletions(-)
 create mode 100644 src/backend/snowball/snowball_create.pl

diff --git a/src/backend/snowball/Makefile b/src/backend/snowball/Makefile
index 50b9199910c..259104f8eb3 100644
--- a/src/backend/snowball/Makefile
+++ b/src/backend/snowball/Makefile
@@ -119,29 +119,8 @@ all: all-shared-lib $(SQLSCRIPT)
 
 include $(top_srcdir)/src/Makefile.shlib
 
-$(SQLSCRIPT): Makefile snowball_func.sql.in snowball.sql.in
-	echo '-- Language-specific snowball dictionaries' > $@
-	cat $(srcdir)/snowball_func.sql.in >> $@
-	@set -e; \
-	set $(LANGUAGES) ; \
-	while [ "$$#" -gt 0 ] ; \
-	do \
-		lang=$$1; shift; \
-		nonascdictname=$$lang; \
-		ascdictname=$$1; shift; \
-		if [ -s $(srcdir)/stopwords/$${lang}.stop ] ; then \
-			stop=", StopWords=$${lang}" ; \
-		else \
-			stop=""; \
-		fi; \
-		cat $(srcdir)/snowball.sql.in | \
-			sed -e "s#_LANGNAME_#$$lang#g" | \
-			sed -e "s#_DICTNAME_#$${lang}_stem#g" | \
-			sed -e "s#_CFGNAME_#$$lang#g" | \
-			sed -e "s#_ASCDICTNAME_#$${ascdictname}_stem#g" | \
-			sed -e "s#_NONASCDICTNAME_#$${nonascdictname}_stem#g" | \
-			sed -e "s#_STOPWORDS_#$$stop#g" ; \
-	done >> $@
+$(SQLSCRIPT): snowball_create.pl Makefile snowball_func.sql.in snowball.sql.in
+	$(PERL) $< --input ${srcdir} --output .
 
 install: all installdirs install-lib
 	$(INSTALL_DATA) $(SQLSCRIPT) '$(DESTDIR)$(datadir)'
@@ -171,4 +150,4 @@ uninstall: uninstall-lib
 	done
 
 clean distclean maintainer-clean: clean-lib
-	rm -f $(OBJS) $(SQLSCRIPT)
+	rm -f $(OBJS) $(SQLSCRIPT) snowball_create.dep
diff --git a/src/backend/snowball/snowball_create.pl b/src/backend/snowball/snowball_create.pl
new file mode 100644
index 00000000000..d9d79f3668f
--- /dev/null
+++ b/src/backend/snowball/snowball_create.pl
@@ -0,0 +1,110 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Getopt::Long;
+
+my $output_path = '';
+my $makefile_path = '';
+my $input_path = '';
+
+GetOptions(
+	'output:s'   => \$output_path,
+	'input:s'    => \$input_path) || usage();
+
+# Make sure input_path ends in a slash if needed.
+if ($input_path ne '' && substr($input_path, -1) ne '/')
+{
+	$output_path .= '/';
+}
+
+# Make sure output_path ends in a slash if needed.
+if ($output_path ne '' && substr($output_path, -1) ne '/')
+{
+	$output_path .= '/';
+}
+
+GenerateTsearchFiles();
+
+sub usage
+{
+	die <<EOM;
+Usage: snowball_create.pl --input/-i <path> --input <path>
+    --output        Output directory (default '.')
+    --input         Input directory
+
+snowball_create.pl creates snowball.sql from snowball.sql.in
+EOM
+}
+
+sub GenerateTsearchFiles
+{
+	my $target = shift;
+	my $output_file = "$output_path/snowball_create.sql";
+
+	print "Generating tsearch script...";
+	my $F;
+	my $D;
+	my $tmpl = read_file("$input_path/snowball.sql.in");
+	my $mf   = read_file("$input_path/Makefile");
+
+	open($D, '>', "$output_path/snowball_create.dep")
+	  || die "Could not write snowball_create.dep";
+
+	print $D "$output_file: $input_path/Makefile\n";
+	print $D "$output_file: $input_path/snowball.sql.in\n";
+	print $D "$output_file: $input_path/snowball_func.sql.in\n";
+
+	$mf =~ s{\\\r?\n}{}g;
+	$mf =~ /^LANGUAGES\s*=\s*(.*)$/m
+	  || die "Could not find LANGUAGES line in snowball Makefile\n";
+	my @pieces = split /\s+/, $1;
+	open($F, '>', $output_file)
+	  || die "Could not write snowball_create.sql";
+
+	print $F "-- Language-specific snowball dictionaries\n";
+
+	print $F read_file("$input_path/snowball_func.sql.in");
+
+	while ($#pieces > 0)
+	{
+		my $lang    = shift @pieces || last;
+		my $asclang = shift @pieces || last;
+		my $txt     = $tmpl;
+		my $stop    = '';
+		my $stopword_path = "$input_path/stopwords/$lang.stop";
+
+		if (-s "$stopword_path")
+		{
+			$stop = ", StopWords=$lang";
+
+			print $D "$output_file: $stopword_path\n";
+		}
+
+		$txt =~ s#_LANGNAME_#${lang}#gs;
+		$txt =~ s#_DICTNAME_#${lang}_stem#gs;
+		$txt =~ s#_CFGNAME_#${lang}#gs;
+		$txt =~ s#_ASCDICTNAME_#${asclang}_stem#gs;
+		$txt =~ s#_NONASCDICTNAME_#${lang}_stem#gs;
+		$txt =~ s#_STOPWORDS_#$stop#gs;
+		print $F $txt;
+		print ".";
+	}
+	close($F);
+	close($D);
+	print "\n";
+	return;
+}
+
+
+sub read_file
+{
+	my $filename = shift;
+	my $F;
+	local $/ = undef;
+	open($F, '<', $filename) || die "Could not open file $filename\n";
+	my $txt = <$F>;
+	close($F);
+
+	return $txt;
+}
-- 
2.23.0.385.gbc12974a89


--q7iu5jwpuq7sbl3z
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v5-0006-meson-prereq-add-output-path-arg-in-generate-lwlo.patch"



^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* [PATCH v10 04/16] meson: prereq: Move snowball_create.sql creation into perl file
@ 2022-01-20 07:36  Andres Freund <[email protected]>
  0 siblings, 0 replies; 10+ messages in thread

From: Andres Freund @ 2022-01-20 07:36 UTC (permalink / raw)

Author: Peter Eisentraut <[email protected]>
Author: Andres Freund <[email protected]>
---
 src/backend/snowball/Makefile           | 104 +++++------------
 src/backend/snowball/snowball_create.pl | 148 ++++++++++++++++++++++++
 src/tools/msvc/Install.pm               |  36 +-----
 3 files changed, 178 insertions(+), 110 deletions(-)
 create mode 100644 src/backend/snowball/snowball_create.pl

diff --git a/src/backend/snowball/Makefile b/src/backend/snowball/Makefile
index 50b9199910c..29076371db7 100644
--- a/src/backend/snowball/Makefile
+++ b/src/backend/snowball/Makefile
@@ -72,40 +72,22 @@ OBJS += \
 	stem_UTF_8_turkish.o \
 	stem_UTF_8_yiddish.o
 
-# first column is language name and also name of dictionary for not-all-ASCII
-# words, second is name of dictionary for all-ASCII words
-# Note order dependency: use of some other language as ASCII dictionary
-# must come after creation of that language
-LANGUAGES=  \
-	arabic		arabic		\
-	armenian	armenian	\
-	basque		basque		\
-	catalan		catalan		\
-	danish		danish		\
-	dutch		dutch		\
-	english		english		\
-	finnish		finnish		\
-	french		french		\
-	german		german		\
-	greek		greek		\
-	hindi		english		\
-	hungarian	hungarian	\
-	indonesian	indonesian	\
-	irish		irish		\
-	italian		italian		\
-	lithuanian	lithuanian	\
-	nepali		nepali		\
-	norwegian	norwegian	\
-	portuguese	portuguese	\
-	romanian	romanian	\
-	russian		english		\
-	serbian		serbian		\
-	spanish		spanish		\
-	swedish		swedish		\
-	tamil		tamil		\
-	turkish		turkish		\
-	yiddish		yiddish
-
+stop_files = \
+	danish.stop \
+	dutch.stop \
+	english.stop \
+	finnish.stop \
+	french.stop \
+	german.stop \
+	hungarian.stop \
+	italian.stop \
+	nepali.stop \
+	norwegian.stop \
+	portuguese.stop \
+	russian.stop \
+	spanish.stop \
+	swedish.stop \
+	turkish.stop
 
 SQLSCRIPT= snowball_create.sql
 DICTDIR=tsearch_data
@@ -119,56 +101,24 @@ all: all-shared-lib $(SQLSCRIPT)
 
 include $(top_srcdir)/src/Makefile.shlib
 
-$(SQLSCRIPT): Makefile snowball_func.sql.in snowball.sql.in
-	echo '-- Language-specific snowball dictionaries' > $@
-	cat $(srcdir)/snowball_func.sql.in >> $@
-	@set -e; \
-	set $(LANGUAGES) ; \
-	while [ "$$#" -gt 0 ] ; \
-	do \
-		lang=$$1; shift; \
-		nonascdictname=$$lang; \
-		ascdictname=$$1; shift; \
-		if [ -s $(srcdir)/stopwords/$${lang}.stop ] ; then \
-			stop=", StopWords=$${lang}" ; \
-		else \
-			stop=""; \
-		fi; \
-		cat $(srcdir)/snowball.sql.in | \
-			sed -e "s#_LANGNAME_#$$lang#g" | \
-			sed -e "s#_DICTNAME_#$${lang}_stem#g" | \
-			sed -e "s#_CFGNAME_#$$lang#g" | \
-			sed -e "s#_ASCDICTNAME_#$${ascdictname}_stem#g" | \
-			sed -e "s#_NONASCDICTNAME_#$${nonascdictname}_stem#g" | \
-			sed -e "s#_STOPWORDS_#$$stop#g" ; \
-	done >> $@
+$(SQLSCRIPT): snowball_create.pl snowball_func.sql.in snowball.sql.in
+	$(PERL) $< --input ${srcdir} --outdir .
+
+distprep: $(SQLSCRIPT)
 
 install: all installdirs install-lib
 	$(INSTALL_DATA) $(SQLSCRIPT) '$(DESTDIR)$(datadir)'
-	@set -e; \
-	set $(LANGUAGES) ; \
-	while [ "$$#" -gt 0 ] ; \
-	do \
-		lang=$$1; shift; shift; \
-		if [ -s $(srcdir)/stopwords/$${lang}.stop ] ; then \
-			$(INSTALL_DATA) $(srcdir)/stopwords/$${lang}.stop '$(DESTDIR)$(datadir)/$(DICTDIR)' ; \
-		fi \
-	done
+	$(INSTALL_DATA) $(addprefix $(srcdir)/stopwords/,$(stop_files)) '$(DESTDIR)$(datadir)/$(DICTDIR)'
 
 installdirs: installdirs-lib
 	$(MKDIR_P) '$(DESTDIR)$(datadir)' '$(DESTDIR)$(datadir)/$(DICTDIR)'
 
 uninstall: uninstall-lib
 	rm -f '$(DESTDIR)$(datadir)/$(SQLSCRIPT)'
-	@set -e; \
-	set $(LANGUAGES) ; \
-	while [ "$$#" -gt 0 ] ; \
-	do \
-		lang=$$1; shift; shift;  \
-		if [ -s $(srcdir)/stopwords/$${lang}.stop ] ; then \
-		    rm -f '$(DESTDIR)$(datadir)/$(DICTDIR)/'$${lang}.stop ; \
-		fi \
-	done
+	rm -f $(addprefix '$(DESTDIR)$(datadir)/$(DICTDIR)/',$(stop_files))
 
-clean distclean maintainer-clean: clean-lib
-	rm -f $(OBJS) $(SQLSCRIPT)
+clean distclean: clean-lib
+	rm -f $(OBJS)
+
+maintainer-clean: distclean
+	rm -f $(SQLSCRIPT)
diff --git a/src/backend/snowball/snowball_create.pl b/src/backend/snowball/snowball_create.pl
new file mode 100644
index 00000000000..f4b58ada1cb
--- /dev/null
+++ b/src/backend/snowball/snowball_create.pl
@@ -0,0 +1,148 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Getopt::Long;
+
+my $outdir_path = '';
+my $makefile_path = '';
+my $input_path = '';
+my $depfile;
+
+our @languages = qw(
+	arabic
+	armenian
+	basque
+	catalan
+	danish
+	dutch
+	english
+	finnish
+	french
+	german
+	greek
+	hindi
+	hungarian
+	indonesian
+	irish
+	italian
+	lithuanian
+	nepali
+	norwegian
+	portuguese
+	romanian
+	russian
+	serbian
+	spanish
+	swedish
+	tamil
+	turkish
+	yiddish
+);
+
+# Names of alternative dictionaries for all-ASCII words.  If not
+# listed, the language itself is used.  Note order dependency: Use of
+# some other language as ASCII dictionary must come after creation of
+# that language, so the "backup" language must be listed earlier in
+# @languages.
+
+our %ascii_languages = (
+	'hindi' => 'english',
+	'russian' => 'english',
+);
+
+GetOptions(
+	'depfile'    => \$depfile,
+	'outdir:s'   => \$outdir_path,
+	'input:s'    => \$input_path) || usage();
+
+# Make sure input_path ends in a slash if needed.
+if ($input_path ne '' && substr($input_path, -1) ne '/')
+{
+	$outdir_path .= '/';
+}
+
+# Make sure outdir_path ends in a slash if needed.
+if ($outdir_path ne '' && substr($outdir_path, -1) ne '/')
+{
+	$outdir_path .= '/';
+}
+
+GenerateTsearchFiles();
+
+sub usage
+{
+	die <<EOM;
+Usage: snowball_create.pl --input/-i <path> --outdir/-o <path>
+    --depfile       Write dependency file
+    --outdir        Output directory (default '.')
+    --input         Input directory
+
+snowball_create.pl creates snowball.sql from snowball.sql.in
+EOM
+}
+
+sub GenerateTsearchFiles
+{
+	my $target = shift;
+	my $outdir_file = "$outdir_path/snowball_create.sql";
+
+	my $F;
+	my $D;
+	my $tmpl = read_file("$input_path/snowball.sql.in");
+
+	if ($depfile)
+	{
+		open($D, '>', "$outdir_path/snowball_create.dep")
+		  || die "Could not write snowball_create.dep";
+	}
+
+	print $D "$outdir_file: $input_path/snowball.sql.in\n" if $depfile;
+	print $D "$outdir_file: $input_path/snowball_func.sql.in\n" if $depfile;
+
+	open($F, '>', $outdir_file)
+	  || die "Could not write snowball_create.sql";
+
+	print $F "-- Language-specific snowball dictionaries\n";
+
+	print $F read_file("$input_path/snowball_func.sql.in");
+
+	foreach my $lang (@languages)
+	{
+		my $asclang = $ascii_languages{$lang} || $lang;
+		my $txt     = $tmpl;
+		my $stop    = '';
+		my $stopword_path = "$input_path/stopwords/$lang.stop";
+
+		if (-s "$stopword_path")
+		{
+			$stop = ", StopWords=$lang";
+
+			print $D "$outdir_file: $stopword_path\n" if $depfile;
+		}
+
+		$txt =~ s#_LANGNAME_#${lang}#gs;
+		$txt =~ s#_DICTNAME_#${lang}_stem#gs;
+		$txt =~ s#_CFGNAME_#${lang}#gs;
+		$txt =~ s#_ASCDICTNAME_#${asclang}_stem#gs;
+		$txt =~ s#_NONASCDICTNAME_#${lang}_stem#gs;
+		$txt =~ s#_STOPWORDS_#$stop#gs;
+		print $F $txt;
+	}
+	close($F);
+	close($D) if $depfile;
+	return;
+}
+
+
+sub read_file
+{
+	my $filename = shift;
+	my $F;
+	local $/ = undef;
+	open($F, '<', $filename) || die "Could not open file $filename\n";
+	my $txt = <$F>;
+	close($F);
+
+	return $txt;
+}
diff --git a/src/tools/msvc/Install.pm b/src/tools/msvc/Install.pm
index 8de79c618cb..5da299476eb 100644
--- a/src/tools/msvc/Install.pm
+++ b/src/tools/msvc/Install.pm
@@ -389,39 +389,9 @@ sub GenerateTsearchFiles
 	my $target = shift;
 
 	print "Generating tsearch script...";
-	my $F;
-	my $tmpl = read_file('src/backend/snowball/snowball.sql.in');
-	my $mf   = read_file('src/backend/snowball/Makefile');
-	$mf =~ s{\\\r?\n}{}g;
-	$mf =~ /^LANGUAGES\s*=\s*(.*)$/m
-	  || die "Could not find LANGUAGES line in snowball Makefile\n";
-	my @pieces = split /\s+/, $1;
-	open($F, '>', "$target/share/snowball_create.sql")
-	  || die "Could not write snowball_create.sql";
-	print $F read_file('src/backend/snowball/snowball_func.sql.in');
-
-	while ($#pieces > 0)
-	{
-		my $lang    = shift @pieces || last;
-		my $asclang = shift @pieces || last;
-		my $txt     = $tmpl;
-		my $stop    = '';
-
-		if (-s "src/backend/snowball/stopwords/$lang.stop")
-		{
-			$stop = ", StopWords=$lang";
-		}
-
-		$txt =~ s#_LANGNAME_#${lang}#gs;
-		$txt =~ s#_DICTNAME_#${lang}_stem#gs;
-		$txt =~ s#_CFGNAME_#${lang}#gs;
-		$txt =~ s#_ASCDICTNAME_#${asclang}_stem#gs;
-		$txt =~ s#_NONASCDICTNAME_#${lang}_stem#gs;
-		$txt =~ s#_STOPWORDS_#$stop#gs;
-		print $F $txt;
-		print ".";
-	}
-	close($F);
+	system('perl', 'src/backend/snowball/snowball_create.pl',
+		'--input', 'src/backend/snowball/',
+		'--outdir', "$target/share/");
 	print "\n";
 	return;
 }
-- 
2.37.0.3.g30cc8d0f14


--mqd6wwweo5bfrq2e
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v10-0005-meson-prereq-Add-output-path-arg-in-generate-lwl.patch"



^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Primary and standby setting cross-checks
@ 2024-08-29 18:52  Heikki Linnakangas <[email protected]>
  0 siblings, 2 replies; 10+ messages in thread

From: Heikki Linnakangas @ 2024-08-29 18:52 UTC (permalink / raw)
  To: pgsql-hackers

Currently, if you configure a hot standby server with a smaller 
max_connections setting than the primary, the server refuses to start up:

LOG:  entering standby mode
FATAL:  recovery aborted because of insufficient parameter settings
DETAIL:  max_connections = 10 is a lower setting than on the primary 
server, where its value was 100.
HINT:  You can restart the server after making the necessary 
configuration changes.

Or if you change the setting in the primary while the standby is 
running, replay pauses:

WARNING:  hot standby is not possible because of insufficient parameter 
settings
DETAIL:  max_connections = 100 is a lower setting than on the primary 
server, where its value was 200.
CONTEXT:  WAL redo at 2/E10000D8 for XLOG/PARAMETER_CHANGE: 
max_connections=200 max_worker_processes=8 max_wal_senders=10 
max_prepared_xacts=0 max_locks_per_xact=64 wal_level=logical 
wal_log_hints=off track_commit_timestamp=off
LOG:  recovery has paused
DETAIL:  If recovery is unpaused, the server will shut down.
HINT:  You can then restart the server after making the necessary 
configuration changes.
CONTEXT:  WAL redo at 2/E10000D8 for XLOG/PARAMETER_CHANGE: 
max_connections=200 max_worker_processes=8 max_wal_senders=10 
max_prepared_xacts=0 max_locks_per_xact=64 wal_level=logical 
wal_log_hints=off track_commit_timestamp=off

Both of these are rather unpleasant behavior.

I thought I could get rid of that limitation with my CSN snapshot patch 
[1], because it gets rid of the fixed-size known-assigned XIDs array, 
but there's a second reason for these limitations. It's also used to 
ensure that the standby has enough space in the lock manager to hold 
possible AccessExclusiveLocks taken by transactions in the primary.

So firstly, I think that's a bad tradeoff. In vast majority of cases, 
you would not run out of lock space anyway, if you just started up the 
system. Secondly, that cross-check of settings doesn't fully prevent the 
problem. It ensures that the lock tables are large enough to accommodate 
all the locks you could possibly hold in the primary, but that doesn't 
take into account any additional locks held by read-only queries in the 
hot standby. So if you have queries running in the standby that take a 
lot of locks, this can happen anyway:

2024-08-29 21:44:32.634 EEST [668327] FATAL:  out of shared memory
2024-08-29 21:44:32.634 EEST [668327] HINT:  You might need to increase 
"max_locks_per_transaction".
2024-08-29 21:44:32.634 EEST [668327] CONTEXT:  WAL redo at 2/FD40FCC8 
for Standby/LOCK: xid 996 db 5 rel 154045
2024-08-29 21:44:32.634 EEST [668327] WARNING:  you don't own a lock of 
type AccessExclusiveLock
2024-08-29 21:44:32.634 EEST [668327] LOG:  RecoveryLockHash contains 
entry for lock no longer recorded by lock manager: xid 996 database 5 
relation 154045
TRAP: failed Assert("false"), File: 
"../src/backend/storage/ipc/standby.c", Line: 1053, PID: 668327
postgres: startup recovering 
0000000100000002000000FD(ExceptionalCondition+0x6e)[0x556a4588396e]
postgres: startup recovering 
0000000100000002000000FD(+0x44156e)[0x556a4571356e]
postgres: startup recovering 
0000000100000002000000FD(StandbyReleaseAllLocks+0x78)[0x556a45712738]
postgres: startup recovering 
0000000100000002000000FD(ShutdownRecoveryTransactionEnvironment+0x15)[0x556a45712685]
postgres: startup recovering 
0000000100000002000000FD(shmem_exit+0x111)[0x556a457062e1]
postgres: startup recovering 
0000000100000002000000FD(+0x434132)[0x556a45706132]
postgres: startup recovering 
0000000100000002000000FD(proc_exit+0x59)[0x556a45706079]
postgres: startup recovering 
0000000100000002000000FD(errfinish+0x278)[0x556a45884708]
postgres: startup recovering 
0000000100000002000000FD(LockAcquireExtended+0xa46)[0x556a45719386]
postgres: startup recovering 
0000000100000002000000FD(StandbyAcquireAccessExclusiveLock+0x11d)[0x556a4571330d]
postgres: startup recovering 
0000000100000002000000FD(standby_redo+0x70)[0x556a45713690]
postgres: startup recovering 
0000000100000002000000FD(PerformWalRecovery+0x7b3)[0x556a4547d313]
postgres: startup recovering 
0000000100000002000000FD(StartupXLOG+0xac3)[0x556a4546dae3]
postgres: startup recovering 
0000000100000002000000FD(StartupProcessMain+0xe8)[0x556a45693558]
postgres: startup recovering 
0000000100000002000000FD(+0x3ba95d)[0x556a4568c95d]
postgres: startup recovering 
0000000100000002000000FD(+0x3bce41)[0x556a4568ee41]
postgres: startup recovering 
0000000100000002000000FD(PostmasterMain+0x116e)[0x556a4568eaae]
postgres: startup recovering 
0000000100000002000000FD(+0x2f960e)[0x556a455cb60e]
/lib/x86_64-linux-gnu/libc.so.6(+0x27c8a)[0x7f10ef042c8a]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x85)[0x7f10ef042d45]
postgres: startup recovering 
0000000100000002000000FD(_start+0x21)[0x556a453af011]
2024-08-29 21:44:32.641 EEST [668324] LOG:  startup process (PID 668327) 
was terminated by signal 6: Aborted
2024-08-29 21:44:32.641 EEST [668324] LOG:  terminating any other active 
server processes
2024-08-29 21:44:32.654 EEST [668324] LOG:  shutting down due to startup 
process failure
2024-08-29 21:44:32.729 EEST [668324] LOG:  database system is shut down

Granted, if you restart the server, it will probably succeed because 
restarting the server will kill all the other queries that were holding 
locks. But yuck. With assertions disabled, it looks a little less scary, 
but not nice anyway.

So how to improve this? I see a few options:

a) Downgrade the error at startup to a warning, and allow starting the 
standby with smaller settings in standby. At least with a smaller 
max_locks_per_transactions. The other settings also affect the size of 
known-assigned XIDs array, but if the CSN snapshots get committed, that 
will get fixed. In most cases there is enough lock memory anyway, and it 
will be fine. Just fix the assertion failure so that the error message 
is a little nicer.

b) If you run out of lock space, kill running queries, and prevent new 
ones from starting. Track the locks in startup process' private memory 
until there is enough space in the lock manager, and then re-open for 
queries. In essence, go from hot standby mode to warm standby, until 
it's possible to go back to hot standby mode again.

Thoughts, better ideas?

[1] https://commitfest.postgresql.org/49/4912/

-- 
Heikki Linnakangas
Neon (https://neon.tech)





^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: Primary and standby setting cross-checks
@ 2024-09-25 03:03  Noah Misch <[email protected]>
  parent: Heikki Linnakangas <[email protected]>
  1 sibling, 0 replies; 10+ messages in thread

From: Noah Misch @ 2024-09-25 03:03 UTC (permalink / raw)
  To: Heikki Linnakangas <[email protected]>; +Cc: pgsql-hackers

On Thu, Aug 29, 2024 at 09:52:06PM +0300, Heikki Linnakangas wrote:
> Currently, if you configure a hot standby server with a smaller
> max_connections setting than the primary, the server refuses to start up:
> 
> LOG:  entering standby mode
> FATAL:  recovery aborted because of insufficient parameter settings
> DETAIL:  max_connections = 10 is a lower setting than on the primary server,
> where its value was 100.

> happen anyway:
> 
> 2024-08-29 21:44:32.634 EEST [668327] FATAL:  out of shared memory
> 2024-08-29 21:44:32.634 EEST [668327] HINT:  You might need to increase
> "max_locks_per_transaction".
> 2024-08-29 21:44:32.634 EEST [668327] CONTEXT:  WAL redo at 2/FD40FCC8 for
> Standby/LOCK: xid 996 db 5 rel 154045
> 2024-08-29 21:44:32.634 EEST [668327] WARNING:  you don't own a lock of type
> AccessExclusiveLock
> 2024-08-29 21:44:32.634 EEST [668327] LOG:  RecoveryLockHash contains entry
> for lock no longer recorded by lock manager: xid 996 database 5 relation
> 154045
> TRAP: failed Assert("false"), File: "../src/backend/storage/ipc/standby.c",

> Granted, if you restart the server, it will probably succeed because
> restarting the server will kill all the other queries that were holding
> locks. But yuck.

Agreed.

> So how to improve this? I see a few options:
> 
> a) Downgrade the error at startup to a warning, and allow starting the
> standby with smaller settings in standby. At least with a smaller
> max_locks_per_transactions. The other settings also affect the size of
> known-assigned XIDs array, but if the CSN snapshots get committed, that will
> get fixed. In most cases there is enough lock memory anyway, and it will be
> fine. Just fix the assertion failure so that the error message is a little
> nicer.
> 
> b) If you run out of lock space, kill running queries, and prevent new ones
> from starting. Track the locks in startup process' private memory until
> there is enough space in the lock manager, and then re-open for queries. In
> essence, go from hot standby mode to warm standby, until it's possible to go
> back to hot standby mode again.

Either seems fine.  Having never encountered actual lock exhaustion from this,
I'd lean toward (a) for simplicity.

> Thoughts, better ideas?

I worry about future code assuming a MaxBackends-sized array suffices for
something.  That could work almost all the time, breaking only when a standby
replays WAL from a server having a larger array.  What could we do now to
catch that future mistake promptly?  As a start, 027_stream_regress.pl could
use low settings on its standby.





^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: Primary and standby setting cross-checks
@ 2025-03-12 18:09  Kirill Reshke <[email protected]>
  parent: Heikki Linnakangas <[email protected]>
  1 sibling, 1 reply; 10+ messages in thread

From: Kirill Reshke @ 2025-03-12 18:09 UTC (permalink / raw)
  To: Heikki Linnakangas <[email protected]>; +Cc: pgsql-hackers

On Thu, 29 Aug 2024 at 23:52, Heikki Linnakangas <[email protected]> wrote:
>
> Currently, if you configure a hot standby server with a smaller
> max_connections setting than the primary, the server refuses to start up:
>
> LOG:  entering standby mode
> FATAL:  recovery aborted because of insufficient parameter settings
> DETAIL:  max_connections = 10 is a lower setting than on the primary
> server, where its value was 100.
> HINT:  You can restart the server after making the necessary
> configuration changes.
>
> Or if you change the setting in the primary while the standby is
> running, replay pauses:
>
> WARNING:  hot standby is not possible because of insufficient parameter
> settings
> DETAIL:  max_connections = 100 is a lower setting than on the primary
> server, where its value was 200.
> CONTEXT:  WAL redo at 2/E10000D8 for XLOG/PARAMETER_CHANGE:
> max_connections=200 max_worker_processes=8 max_wal_senders=10
> max_prepared_xacts=0 max_locks_per_xact=64 wal_level=logical
> wal_log_hints=off track_commit_timestamp=off
> LOG:  recovery has paused
> DETAIL:  If recovery is unpaused, the server will shut down.
> HINT:  You can then restart the server after making the necessary
> configuration changes.
> CONTEXT:  WAL redo at 2/E10000D8 for XLOG/PARAMETER_CHANGE:
> max_connections=200 max_worker_processes=8 max_wal_senders=10
> max_prepared_xacts=0 max_locks_per_xact=64 wal_level=logical
> wal_log_hints=off track_commit_timestamp=off
>
> Both of these are rather unpleasant behavior.
>
> I thought I could get rid of that limitation with my CSN snapshot patch
> [1], because it gets rid of the fixed-size known-assigned XIDs array,
> but there's a second reason for these limitations. It's also used to
> ensure that the standby has enough space in the lock manager to hold
> possible AccessExclusiveLocks taken by transactions in the primary.
>
> So firstly, I think that's a bad tradeoff. In vast majority of cases,
> you would not run out of lock space anyway, if you just started up the
> system. Secondly, that cross-check of settings doesn't fully prevent the
> problem. It ensures that the lock tables are large enough to accommodate
> all the locks you could possibly hold in the primary, but that doesn't
> take into account any additional locks held by read-only queries in the
> hot standby. So if you have queries running in the standby that take a
> lot of locks, this can happen anyway:
>
> 2024-08-29 21:44:32.634 EEST [668327] FATAL:  out of shared memory
> 2024-08-29 21:44:32.634 EEST [668327] HINT:  You might need to increase
> "max_locks_per_transaction".
> 2024-08-29 21:44:32.634 EEST [668327] CONTEXT:  WAL redo at 2/FD40FCC8
> for Standby/LOCK: xid 996 db 5 rel 154045
> 2024-08-29 21:44:32.634 EEST [668327] WARNING:  you don't own a lock of
> type AccessExclusiveLock
> 2024-08-29 21:44:32.634 EEST [668327] LOG:  RecoveryLockHash contains
> entry for lock no longer recorded by lock manager: xid 996 database 5
> relation 154045
> TRAP: failed Assert("false"), File:
> "../src/backend/storage/ipc/standby.c", Line: 1053, PID: 668327
> postgres: startup recovering
> 0000000100000002000000FD(ExceptionalCondition+0x6e)[0x556a4588396e]
> postgres: startup recovering
> 0000000100000002000000FD(+0x44156e)[0x556a4571356e]
> postgres: startup recovering
> 0000000100000002000000FD(StandbyReleaseAllLocks+0x78)[0x556a45712738]
> postgres: startup recovering
> 0000000100000002000000FD(ShutdownRecoveryTransactionEnvironment+0x15)[0x556a45712685]
> postgres: startup recovering
> 0000000100000002000000FD(shmem_exit+0x111)[0x556a457062e1]
> postgres: startup recovering
> 0000000100000002000000FD(+0x434132)[0x556a45706132]
> postgres: startup recovering
> 0000000100000002000000FD(proc_exit+0x59)[0x556a45706079]
> postgres: startup recovering
> 0000000100000002000000FD(errfinish+0x278)[0x556a45884708]
> postgres: startup recovering
> 0000000100000002000000FD(LockAcquireExtended+0xa46)[0x556a45719386]
> postgres: startup recovering
> 0000000100000002000000FD(StandbyAcquireAccessExclusiveLock+0x11d)[0x556a4571330d]
> postgres: startup recovering
> 0000000100000002000000FD(standby_redo+0x70)[0x556a45713690]
> postgres: startup recovering
> 0000000100000002000000FD(PerformWalRecovery+0x7b3)[0x556a4547d313]
> postgres: startup recovering
> 0000000100000002000000FD(StartupXLOG+0xac3)[0x556a4546dae3]
> postgres: startup recovering
> 0000000100000002000000FD(StartupProcessMain+0xe8)[0x556a45693558]
> postgres: startup recovering
> 0000000100000002000000FD(+0x3ba95d)[0x556a4568c95d]
> postgres: startup recovering
> 0000000100000002000000FD(+0x3bce41)[0x556a4568ee41]
> postgres: startup recovering
> 0000000100000002000000FD(PostmasterMain+0x116e)[0x556a4568eaae]
> postgres: startup recovering
> 0000000100000002000000FD(+0x2f960e)[0x556a455cb60e]
> /lib/x86_64-linux-gnu/libc.so.6(+0x27c8a)[0x7f10ef042c8a]
> /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x85)[0x7f10ef042d45]
> postgres: startup recovering
> 0000000100000002000000FD(_start+0x21)[0x556a453af011]
> 2024-08-29 21:44:32.641 EEST [668324] LOG:  startup process (PID 668327)
> was terminated by signal 6: Aborted
> 2024-08-29 21:44:32.641 EEST [668324] LOG:  terminating any other active
> server processes
> 2024-08-29 21:44:32.654 EEST [668324] LOG:  shutting down due to startup
> process failure
> 2024-08-29 21:44:32.729 EEST [668324] LOG:  database system is shut down
>
> Granted, if you restart the server, it will probably succeed because
> restarting the server will kill all the other queries that were holding
> locks. But yuck. With assertions disabled, it looks a little less scary,
> but not nice anyway.
>
> So how to improve this? I see a few options:
>
> a) Downgrade the error at startup to a warning, and allow starting the
> standby with smaller settings in standby. At least with a smaller
> max_locks_per_transactions. The other settings also affect the size of
> known-assigned XIDs array, but if the CSN snapshots get committed, that
> will get fixed. In most cases there is enough lock memory anyway, and it
> will be fine. Just fix the assertion failure so that the error message
> is a little nicer.
>
> b) If you run out of lock space, kill running queries, and prevent new
> ones from starting. Track the locks in startup process' private memory
> until there is enough space in the lock manager, and then re-open for
> queries. In essence, go from hot standby mode to warm standby, until
> it's possible to go back to hot standby mode again.
>
> Thoughts, better ideas?
>
> [1] https://commitfest.postgresql.org/49/4912/
>
> --
> Heikki Linnakangas
> Neon (https://neon.tech)
>
>

Hello! Do you intend to pursue this further?

-- 
Best regards,
Kirill Reshke





^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* [PATCH] Avoid unnecessary code execution in Instrument.c when TIMING is FALSE
@ 2025-07-25 15:26  Hironobu SUZUKI <[email protected]>
  0 siblings, 1 reply; 10+ messages in thread

From: Hironobu SUZUKI @ 2025-07-25 15:26 UTC (permalink / raw)
  To: pgsql-hackers

Hi,

Even when using EXPLAIN ANALYZE with TIMING=FALSE, the functions 
InstrStopNode(), InstrEndLoop(), and InstrAggNode() in Instrument.c 
still execute code related to the "starttime", "counter", "firsttuple", 
"startup",  and "total" fields within the Instrumentation structure.
These operations are unnecessary when timing is disabled, and since 
these functions are called very frequently, I have created a patch to 
address this.

As far as I can tell, this change has no side effects and clarifies the 
intent of each line, but please let me know if you notice any issues.

Best regards,
H.S.
diff --git a/src/backend/executor/instrument.c b/src/backend/executor/instrument.c
index 56e635f4700..e4274a28525 100644
--- a/src/backend/executor/instrument.c
+++ b/src/backend/executor/instrument.c
@@ -114,7 +114,8 @@ InstrStopNode(Instrumentation *instr, double nTuples)
 	if (!instr->running)
 	{
 		instr->running = true;
-		instr->firsttuple = INSTR_TIME_GET_DOUBLE(instr->counter);
+		if (instr->need_timer)
+			instr->firsttuple = INSTR_TIME_GET_DOUBLE(instr->counter);
 	}
 	else
 	{
@@ -122,7 +123,7 @@ InstrStopNode(Instrumentation *instr, double nTuples)
 		 * In async mode, if the plan node hadn't emitted any tuples before,
 		 * this might be the first tuple
 		 */
-		if (instr->async_mode && save_tuplecount < 1.0)
+		if (instr->need_timer && instr->async_mode && save_tuplecount < 1.0)
 			instr->firsttuple = INSTR_TIME_GET_DOUBLE(instr->counter);
 	}
 }
@@ -149,18 +150,24 @@ InstrEndLoop(Instrumentation *instr)
 		elog(ERROR, "InstrEndLoop called on running node");
 
 	/* Accumulate per-cycle statistics into totals */
-	totaltime = INSTR_TIME_GET_DOUBLE(instr->counter);
+	if (instr->need_timer)
+	{
+		totaltime = INSTR_TIME_GET_DOUBLE(instr->counter);
 
-	instr->startup += instr->firsttuple;
-	instr->total += totaltime;
+		instr->startup += instr->firsttuple;
+		instr->total += totaltime;
+	}
 	instr->ntuples += instr->tuplecount;
 	instr->nloops += 1;
 
 	/* Reset for next cycle (if any) */
 	instr->running = false;
-	INSTR_TIME_SET_ZERO(instr->starttime);
-	INSTR_TIME_SET_ZERO(instr->counter);
-	instr->firsttuple = 0;
+	if (instr->need_timer)
+	{
+		INSTR_TIME_SET_ZERO(instr->starttime);
+		INSTR_TIME_SET_ZERO(instr->counter);
+		instr->firsttuple = 0;
+	}
 	instr->tuplecount = 0;
 }
 
@@ -171,16 +178,21 @@ InstrAggNode(Instrumentation *dst, Instrumentation *add)
 	if (!dst->running && add->running)
 	{
 		dst->running = true;
-		dst->firsttuple = add->firsttuple;
+		if (dst->need_timer && add->need_timer)
+			dst->firsttuple = add->firsttuple;
 	}
-	else if (dst->running && add->running && dst->firsttuple > add->firsttuple)
+	else if (dst->need_timer && add->need_timer && dst->running && add->running
+			 && dst->firsttuple > add->firsttuple)
 		dst->firsttuple = add->firsttuple;
 
-	INSTR_TIME_ADD(dst->counter, add->counter);
+	if (dst->need_timer && add->need_timer)
+	{
+		INSTR_TIME_ADD(dst->counter, add->counter);
 
+		dst->startup += add->startup;
+		dst->total += add->total;
+	}
 	dst->tuplecount += add->tuplecount;
-	dst->startup += add->startup;
-	dst->total += add->total;
 	dst->ntuples += add->ntuples;
 	dst->ntuples2 += add->ntuples2;
 	dst->nloops += add->nloops;


Attachments:

  [text/plain] v1_avoid_unnecessary_code_execution_in_instrumentation.patch (2.6K, ../../[email protected]/2-v1_avoid_unnecessary_code_execution_in_instrumentation.patch)
  download | inline diff:
diff --git a/src/backend/executor/instrument.c b/src/backend/executor/instrument.c
index 56e635f4700..e4274a28525 100644
--- a/src/backend/executor/instrument.c
+++ b/src/backend/executor/instrument.c
@@ -114,7 +114,8 @@ InstrStopNode(Instrumentation *instr, double nTuples)
 	if (!instr->running)
 	{
 		instr->running = true;
-		instr->firsttuple = INSTR_TIME_GET_DOUBLE(instr->counter);
+		if (instr->need_timer)
+			instr->firsttuple = INSTR_TIME_GET_DOUBLE(instr->counter);
 	}
 	else
 	{
@@ -122,7 +123,7 @@ InstrStopNode(Instrumentation *instr, double nTuples)
 		 * In async mode, if the plan node hadn't emitted any tuples before,
 		 * this might be the first tuple
 		 */
-		if (instr->async_mode && save_tuplecount < 1.0)
+		if (instr->need_timer && instr->async_mode && save_tuplecount < 1.0)
 			instr->firsttuple = INSTR_TIME_GET_DOUBLE(instr->counter);
 	}
 }
@@ -149,18 +150,24 @@ InstrEndLoop(Instrumentation *instr)
 		elog(ERROR, "InstrEndLoop called on running node");
 
 	/* Accumulate per-cycle statistics into totals */
-	totaltime = INSTR_TIME_GET_DOUBLE(instr->counter);
+	if (instr->need_timer)
+	{
+		totaltime = INSTR_TIME_GET_DOUBLE(instr->counter);
 
-	instr->startup += instr->firsttuple;
-	instr->total += totaltime;
+		instr->startup += instr->firsttuple;
+		instr->total += totaltime;
+	}
 	instr->ntuples += instr->tuplecount;
 	instr->nloops += 1;
 
 	/* Reset for next cycle (if any) */
 	instr->running = false;
-	INSTR_TIME_SET_ZERO(instr->starttime);
-	INSTR_TIME_SET_ZERO(instr->counter);
-	instr->firsttuple = 0;
+	if (instr->need_timer)
+	{
+		INSTR_TIME_SET_ZERO(instr->starttime);
+		INSTR_TIME_SET_ZERO(instr->counter);
+		instr->firsttuple = 0;
+	}
 	instr->tuplecount = 0;
 }
 
@@ -171,16 +178,21 @@ InstrAggNode(Instrumentation *dst, Instrumentation *add)
 	if (!dst->running && add->running)
 	{
 		dst->running = true;
-		dst->firsttuple = add->firsttuple;
+		if (dst->need_timer && add->need_timer)
+			dst->firsttuple = add->firsttuple;
 	}
-	else if (dst->running && add->running && dst->firsttuple > add->firsttuple)
+	else if (dst->need_timer && add->need_timer && dst->running && add->running
+			 && dst->firsttuple > add->firsttuple)
 		dst->firsttuple = add->firsttuple;
 
-	INSTR_TIME_ADD(dst->counter, add->counter);
+	if (dst->need_timer && add->need_timer)
+	{
+		INSTR_TIME_ADD(dst->counter, add->counter);
 
+		dst->startup += add->startup;
+		dst->total += add->total;
+	}
 	dst->tuplecount += add->tuplecount;
-	dst->startup += add->startup;
-	dst->total += add->total;
 	dst->ntuples += add->ntuples;
 	dst->ntuples2 += add->ntuples2;
 	dst->nloops += add->nloops;


^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: [PATCH] Avoid unnecessary code execution in Instrument.c when TIMING is FALSE
@ 2025-07-26 00:29  Michael Paquier <[email protected]>
  parent: Hironobu SUZUKI <[email protected]>
  0 siblings, 1 reply; 10+ messages in thread

From: Michael Paquier @ 2025-07-26 00:29 UTC (permalink / raw)
  To: Hironobu SUZUKI <[email protected]>; +Cc: pgsql-hackers

On Sat, Jul 26, 2025 at 12:26:21AM +0900, Hironobu SUZUKI wrote:
> Even when using EXPLAIN ANALYZE with TIMING=FALSE, the functions
> InstrStopNode(), InstrEndLoop(), and InstrAggNode() in Instrument.c still
> execute code related to the "starttime", "counter", "firsttuple", "startup",
> and "total" fields within the Instrumentation structure.
> These operations are unnecessary when timing is disabled, and since these
> functions are called very frequently, I have created a patch to address
> this.
> 
> As far as I can tell, this change has no side effects and clarifies the
> intent of each line, but please let me know if you notice any issues.

Spoiler: this has been discussed during a meetup attended by most of
the PostgreSQL hackers based in Tokyo and surroundings on the 18th of
July, where Suzuki-san has noticed that the work done by the backend
was pointless when using the instrumentation while hacking on an
extension that relied at least on the explain hook.  One of the
remarks was that this seemed worth a submission to upstream when
timers are disabled.  The performance really took a hit when the timer
was disabled, making the extension do a lot of unnecessary work for
nothing.
--
Michael


Attachments:

  [application/pgp-signature] signature.asc (833B, ../../[email protected]/2-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: [PATCH] Avoid unnecessary code execution in Instrument.c when TIMING is FALSE
@ 2025-07-26 08:16  Hironobu SUZUKI <[email protected]>
  parent: Michael Paquier <[email protected]>
  0 siblings, 0 replies; 10+ messages in thread

From: Hironobu SUZUKI @ 2025-07-26 08:16 UTC (permalink / raw)
  To: Michael Paquier <[email protected]>; +Cc: pgsql-hackers

On 2025/07/26 9:29, Michael Paquier wrote:
> On Sat, Jul 26, 2025 at 12:26:21AM +0900, Hironobu SUZUKI wrote:
>> Even when using EXPLAIN ANALYZE with TIMING=FALSE, the functions
>> InstrStopNode(), InstrEndLoop(), and InstrAggNode() in Instrument.c still
>> execute code related to the "starttime", "counter", "firsttuple", "startup",
>> and "total" fields within the Instrumentation structure.
>> These operations are unnecessary when timing is disabled, and since these
>> functions are called very frequently, I have created a patch to address
>> this.
>>
>> As far as I can tell, this change has no side effects and clarifies the
>> intent of each line, but please let me know if you notice any issues.
> 
> Spoiler: this has been discussed during a meetup attended by most of
> the PostgreSQL hackers based in Tokyo and surroundings on the 18th of
> July, where Suzuki-san has noticed that the work done by the backend
> was pointless when using the instrumentation while hacking on an
> extension that relied at least on the explain hook.  One of the
> remarks was that this seemed worth a submission to upstream when
> timers are disabled.  The performance really took a hit when the timer
> was disabled, making the extension do a lot of unnecessary work for
> nothing.
> --
> Michael


Thanks for the spoilers!

Actually, I was confused while reading the Instrument module’s source
code since some sections ran even when timing was disabled, unlike
other parts guarded by if statements.

This patch mainly clarifies the coding intent, so I intentionally avoided
adding comments.

(The essential improvement proposals for internal monitoring will be
presented on another occasion.)

Best,






^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: Primary and standby setting cross-checks
@ 2026-02-28 08:26  James Pang <[email protected]>
  parent: Kirill Reshke <[email protected]>
  0 siblings, 0 replies; 10+ messages in thread

From: James Pang @ 2026-02-28 08:26 UTC (permalink / raw)
  To: Kirill Reshke <[email protected]>; +Cc: Heikki Linnakangas <[email protected]>; pgsql-hackers

May I know the progress?  sometimes, standby only offload some query and
with lower cpu and ram.  warning is flexible instead of fatal ?  We
 track_commit_timestamp =on and max_worker_process, wal_level=logical
change and restart primary, it lead to standby failed and recovery from
last restart point   that lead to another issue, because old transaction
before turn on track_commit_timestamp, and failed in get that transaction
commit_ts.
FATAL:  recovery aborted because of insufficient parameter settings
DETAIL:  max_worker_processes = 10 is a lower setting than on the primary
server, where its value was 30.
HINT:  You can restart the server after making the necessary configuration
changes.
CONTEXT:  WAL redo at 1F4F/xxxxxxxx for XLOG/PARAMETER_CHANGE:
max_connections=xxx max_worker_processes=30 max_wal_sen
LOG:  startup process (PID xxx) exited with exit code 1
LOG:  terminating any other active server processes
LOG:  shutting down due to startup process failure
LOG:  database system is shut down
LOG:  starting PostgreSQL 14.18 on aarch64-unknown-linux-gnu, compiled by
gcc (GCC) 7.3.1 20180712

Thanks,

James

Kirill Reshke <[email protected]> 於 2025年3月13日週四 上午2:09寫道:

> On Thu, 29 Aug 2024 at 23:52, Heikki Linnakangas <[email protected]> wrote:
> >
> > Currently, if you configure a hot standby server with a smaller
> > max_connections setting than the primary, the server refuses to start up:
> >
> > LOG:  entering standby mode
> > FATAL:  recovery aborted because of insufficient parameter settings
> > DETAIL:  max_connections = 10 is a lower setting than on the primary
> > server, where its value was 100.
> > HINT:  You can restart the server after making the necessary
> > configuration changes.
> >
> > Or if you change the setting in the primary while the standby is
> > running, replay pauses:
> >
> > WARNING:  hot standby is not possible because of insufficient parameter
> > settings
> > DETAIL:  max_connections = 100 is a lower setting than on the primary
> > server, where its value was 200.
> > CONTEXT:  WAL redo at 2/E10000D8 for XLOG/PARAMETER_CHANGE:
> > max_connections=200 max_worker_processes=8 max_wal_senders=10
> > max_prepared_xacts=0 max_locks_per_xact=64 wal_level=logical
> > wal_log_hints=off track_commit_timestamp=off
> > LOG:  recovery has paused
> > DETAIL:  If recovery is unpaused, the server will shut down.
> > HINT:  You can then restart the server after making the necessary
> > configuration changes.
> > CONTEXT:  WAL redo at 2/E10000D8 for XLOG/PARAMETER_CHANGE:
> > max_connections=200 max_worker_processes=8 max_wal_senders=10
> > max_prepared_xacts=0 max_locks_per_xact=64 wal_level=logical
> > wal_log_hints=off track_commit_timestamp=off
> >
> > Both of these are rather unpleasant behavior.
> >
> > I thought I could get rid of that limitation with my CSN snapshot patch
> > [1], because it gets rid of the fixed-size known-assigned XIDs array,
> > but there's a second reason for these limitations. It's also used to
> > ensure that the standby has enough space in the lock manager to hold
> > possible AccessExclusiveLocks taken by transactions in the primary.
> >
> > So firstly, I think that's a bad tradeoff. In vast majority of cases,
> > you would not run out of lock space anyway, if you just started up the
> > system. Secondly, that cross-check of settings doesn't fully prevent the
> > problem. It ensures that the lock tables are large enough to accommodate
> > all the locks you could possibly hold in the primary, but that doesn't
> > take into account any additional locks held by read-only queries in the
> > hot standby. So if you have queries running in the standby that take a
> > lot of locks, this can happen anyway:
> >
> > 2024-08-29 21:44:32.634 EEST [668327] FATAL:  out of shared memory
> > 2024-08-29 21:44:32.634 EEST [668327] HINT:  You might need to increase
> > "max_locks_per_transaction".
> > 2024-08-29 21:44:32.634 EEST [668327] CONTEXT:  WAL redo at 2/FD40FCC8
> > for Standby/LOCK: xid 996 db 5 rel 154045
> > 2024-08-29 21:44:32.634 EEST [668327] WARNING:  you don't own a lock of
> > type AccessExclusiveLock
> > 2024-08-29 21:44:32.634 EEST [668327] LOG:  RecoveryLockHash contains
> > entry for lock no longer recorded by lock manager: xid 996 database 5
> > relation 154045
> > TRAP: failed Assert("false"), File:
> > "../src/backend/storage/ipc/standby.c", Line: 1053, PID: 668327
> > postgres: startup recovering
> > 0000000100000002000000FD(ExceptionalCondition+0x6e)[0x556a4588396e]
> > postgres: startup recovering
> > 0000000100000002000000FD(+0x44156e)[0x556a4571356e]
> > postgres: startup recovering
> > 0000000100000002000000FD(StandbyReleaseAllLocks+0x78)[0x556a45712738]
> > postgres: startup recovering
> >
> 0000000100000002000000FD(ShutdownRecoveryTransactionEnvironment+0x15)[0x556a45712685]
> > postgres: startup recovering
> > 0000000100000002000000FD(shmem_exit+0x111)[0x556a457062e1]
> > postgres: startup recovering
> > 0000000100000002000000FD(+0x434132)[0x556a45706132]
> > postgres: startup recovering
> > 0000000100000002000000FD(proc_exit+0x59)[0x556a45706079]
> > postgres: startup recovering
> > 0000000100000002000000FD(errfinish+0x278)[0x556a45884708]
> > postgres: startup recovering
> > 0000000100000002000000FD(LockAcquireExtended+0xa46)[0x556a45719386]
> > postgres: startup recovering
> >
> 0000000100000002000000FD(StandbyAcquireAccessExclusiveLock+0x11d)[0x556a4571330d]
> > postgres: startup recovering
> > 0000000100000002000000FD(standby_redo+0x70)[0x556a45713690]
> > postgres: startup recovering
> > 0000000100000002000000FD(PerformWalRecovery+0x7b3)[0x556a4547d313]
> > postgres: startup recovering
> > 0000000100000002000000FD(StartupXLOG+0xac3)[0x556a4546dae3]
> > postgres: startup recovering
> > 0000000100000002000000FD(StartupProcessMain+0xe8)[0x556a45693558]
> > postgres: startup recovering
> > 0000000100000002000000FD(+0x3ba95d)[0x556a4568c95d]
> > postgres: startup recovering
> > 0000000100000002000000FD(+0x3bce41)[0x556a4568ee41]
> > postgres: startup recovering
> > 0000000100000002000000FD(PostmasterMain+0x116e)[0x556a4568eaae]
> > postgres: startup recovering
> > 0000000100000002000000FD(+0x2f960e)[0x556a455cb60e]
> > /lib/x86_64-linux-gnu/libc.so.6(+0x27c8a)[0x7f10ef042c8a]
> > /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x85)[0x7f10ef042d45]
> > postgres: startup recovering
> > 0000000100000002000000FD(_start+0x21)[0x556a453af011]
> > 2024-08-29 21:44:32.641 EEST [668324] LOG:  startup process (PID 668327)
> > was terminated by signal 6: Aborted
> > 2024-08-29 21:44:32.641 EEST [668324] LOG:  terminating any other active
> > server processes
> > 2024-08-29 21:44:32.654 EEST [668324] LOG:  shutting down due to startup
> > process failure
> > 2024-08-29 21:44:32.729 EEST [668324] LOG:  database system is shut down
> >
> > Granted, if you restart the server, it will probably succeed because
> > restarting the server will kill all the other queries that were holding
> > locks. But yuck. With assertions disabled, it looks a little less scary,
> > but not nice anyway.
> >
> > So how to improve this? I see a few options:
> >
> > a) Downgrade the error at startup to a warning, and allow starting the
> > standby with smaller settings in standby. At least with a smaller
> > max_locks_per_transactions. The other settings also affect the size of
> > known-assigned XIDs array, but if the CSN snapshots get committed, that
> > will get fixed. In most cases there is enough lock memory anyway, and it
> > will be fine. Just fix the assertion failure so that the error message
> > is a little nicer.
> >
> > b) If you run out of lock space, kill running queries, and prevent new
> > ones from starting. Track the locks in startup process' private memory
> > until there is enough space in the lock manager, and then re-open for
> > queries. In essence, go from hot standby mode to warm standby, until
> > it's possible to go back to hot standby mode again.
> >
> > Thoughts, better ideas?
> >
> > [1] https://commitfest.postgresql.org/49/4912/
> >
> > --
> > Heikki Linnakangas
> > Neon (https://neon.tech)
> >
> >
>
> Hello! Do you intend to pursue this further?
>
> --
> Best regards,
> Kirill Reshke
>
>
>


^ permalink  raw  reply  [nested|flat] 10+ messages in thread


end of thread, other threads:[~2026-02-28 08:26 UTC | newest]

Thread overview: 10+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2021-03-08 22:59 [PATCH v3 05/17] meson: prereq: move snowball_create.sql creation into perl file. Andres Freund <[email protected]>
2021-03-08 22:59 [PATCH v5 05/16] meson: prereq: move snowball_create.sql creation into perl file. Andres Freund <[email protected]>
2022-01-20 07:36 [PATCH v10 04/16] meson: prereq: Move snowball_create.sql creation into perl file Andres Freund <[email protected]>
2024-08-29 18:52 Primary and standby setting cross-checks Heikki Linnakangas <[email protected]>
2024-09-25 03:03 ` Re: Primary and standby setting cross-checks Noah Misch <[email protected]>
2025-03-12 18:09 ` Re: Primary and standby setting cross-checks Kirill Reshke <[email protected]>
2026-02-28 08:26   ` Re: Primary and standby setting cross-checks James Pang <[email protected]>
2025-07-25 15:26 [PATCH] Avoid unnecessary code execution in Instrument.c when TIMING is FALSE Hironobu SUZUKI <[email protected]>
2025-07-26 00:29 ` Re: [PATCH] Avoid unnecessary code execution in Instrument.c when TIMING is FALSE Michael Paquier <[email protected]>
2025-07-26 08:16   ` Re: [PATCH] Avoid unnecessary code execution in Instrument.c when TIMING is FALSE Hironobu SUZUKI <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox