1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-24 00:23:06 +03:00

Replace binary search in fmgr_isbuiltin with a lookup array.

Turns out we have enough functions that the binary search is quite
noticeable in profiles.

Thus have Gen_fmgrtab.pl build a new mapping from a builtin function's
oid to an index in the existing fmgr_builtins array. That keeps the
additional memory usage at a reasonable amount.

Author: Andres Freund, with input from Tom Lane
Discussion: https://postgr.es/m/20170914065128.a5sk7z4xde5uy3ei@alap3.anarazel.de
This commit is contained in:
Andres Freund
2017-10-04 00:22:38 -07:00
parent 18f791ab2b
commit 212e6f34d5
4 changed files with 87 additions and 32 deletions

View File

@@ -21,6 +21,8 @@ use warnings;
# Collect arguments
my $infile; # pg_proc.h
my $output_path = '';
my @include_path;
while (@ARGV)
{
my $arg = shift @ARGV;
@@ -32,6 +34,10 @@ while (@ARGV)
{
$output_path = length($arg) > 2 ? substr($arg, 2) : shift @ARGV;
}
elsif ($arg =~ /^-I/)
{
push @include_path, length($arg) > 2 ? substr($arg, 2) : shift @ARGV;
}
else
{
usage();
@@ -44,6 +50,13 @@ if ($output_path ne '' && substr($output_path, -1) ne '/')
$output_path .= '/';
}
# Sanity check arguments.
die "No input files.\n" if !$infile;
die "No include path; you must specify -I at least once.\n" if !@include_path;
my $FirstBootstrapObjectId =
Catalog::FindDefinedSymbol('access/transam.h', \@include_path, 'FirstBootstrapObjectId');
# Read all the data from the include/catalog files.
my $catalogs = Catalog::Catalogs($infile);
@@ -176,6 +189,7 @@ qq|/*-------------------------------------------------------------------------
#include "postgres.h"
#include "access/transam.h"
#include "utils/fmgrtab.h"
#include "utils/fmgrprotos.h"
@@ -191,32 +205,71 @@ foreach my $s (sort { $a->{oid} <=> $b->{oid} } @fmgr)
print $pfh "extern Datum $s->{prosrc}(PG_FUNCTION_ARGS);\n";
}
# Create the fmgr_builtins table
# Create the fmgr_builtins table, collect data for fmgr_builtin_oid_index
print $tfh "\nconst FmgrBuiltin fmgr_builtins[] = {\n";
my %bmap;
$bmap{'t'} = 'true';
$bmap{'f'} = 'false';
my @fmgr_builtin_oid_index;
my $fmgr_count = 0;
foreach my $s (sort { $a->{oid} <=> $b->{oid} } @fmgr)
{
print $tfh
" { $s->{oid}, \"$s->{prosrc}\", $s->{nargs}, $bmap{$s->{strict}}, $bmap{$s->{retset}}, $s->{prosrc} },\n";
" { $s->{oid}, \"$s->{prosrc}\", $s->{nargs}, $bmap{$s->{strict}}, $bmap{$s->{retset}}, $s->{prosrc} }";
$fmgr_builtin_oid_index[$s->{oid}] = $fmgr_count++;
if ($fmgr_count <= $#fmgr)
{
print $tfh ",\n";
}
else
{
print $tfh "\n";
}
}
print $tfh "};\n";
print $tfh qq|
const int fmgr_nbuiltins = (sizeof(fmgr_builtins) / sizeof(FmgrBuiltin));
|;
# Create fmgr_builtins_oid_index table.
#
# Note that the array has to be filled up to FirstBootstrapObjectId,
# as we can't rely on zero initialization as 0 is a valid mapping.
print $tfh qq|
const uint16 fmgr_builtin_oid_index[FirstBootstrapObjectId] = {
|;
for (my $i = 0; $i < $FirstBootstrapObjectId; $i++)
{
my $oid = $fmgr_builtin_oid_index[$i];
# fmgr_builtin_oid_index is sparse, map nonexistant functions to
# InvalidOidBuiltinMapping
if (not defined $oid)
{
$oid = 'InvalidOidBuiltinMapping';
}
if ($i + 1 == $FirstBootstrapObjectId)
{
print $tfh " $oid\n";
}
else
{
print $tfh " $oid,\n";
}
}
print $tfh "};\n";
# And add the file footers.
print $ofh "\n#endif /* FMGROIDS_H */\n";
print $pfh "\n#endif /* FMGRPROTOS_H */\n";
print $tfh
qq| /* dummy entry is easier than getting rid of comma after last real one */
/* (not that there has ever been anything wrong with *having* a
comma after the last field in an array initializer) */
{ 0, NULL, 0, false, false, NULL }
};
/* Note fmgr_nbuiltins excludes the dummy entry */
const int fmgr_nbuiltins = (sizeof(fmgr_builtins) / sizeof(FmgrBuiltin)) - 1;
|;
close($ofh);
close($pfh);
close($tfh);