Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 212e6f3

Browse files
committed
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
1 parent 18f791a commit 212e6f3

File tree

4 files changed

+88
-33
lines changed

4 files changed

+88
-33
lines changed

src/backend/utils/Gen_fmgrtab.pl

+66-13
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
# Collect arguments
2222
my $infile; # pg_proc.h
2323
my $output_path = '';
24+
my @include_path;
25+
2426
while (@ARGV)
2527
{
2628
my $arg = shift @ARGV;
@@ -32,6 +34,10 @@
3234
{
3335
$output_path = length($arg) > 2 ? substr($arg, 2) : shift @ARGV;
3436
}
37+
elsif ($arg =~ /^-I/)
38+
{
39+
push @include_path, length($arg) > 2 ? substr($arg, 2) : shift @ARGV;
40+
}
3541
else
3642
{
3743
usage();
@@ -44,6 +50,13 @@
4450
$output_path .= '/';
4551
}
4652

53+
# Sanity check arguments.
54+
die "No input files.\n" if !$infile;
55+
die "No include path; you must specify -I at least once.\n" if !@include_path;
56+
57+
my $FirstBootstrapObjectId =
58+
Catalog::FindDefinedSymbol('access/transam.h', \@include_path, 'FirstBootstrapObjectId');
59+
4760
# Read all the data from the include/catalog files.
4861
my $catalogs = Catalog::Catalogs($infile);
4962

@@ -176,6 +189,7 @@
176189
177190
#include "postgres.h"
178191
192+
#include "access/transam.h"
179193
#include "utils/fmgrtab.h"
180194
#include "utils/fmgrprotos.h"
181195
@@ -191,32 +205,71 @@
191205
print $pfh "extern Datum $s->{prosrc}(PG_FUNCTION_ARGS);\n";
192206
}
193207

194-
# Create the fmgr_builtins table
208+
# Create the fmgr_builtins table, collect data for fmgr_builtin_oid_index
195209
print $tfh "\nconst FmgrBuiltin fmgr_builtins[] = {\n";
196210
my %bmap;
197211
$bmap{'t'} = 'true';
198212
$bmap{'f'} = 'false';
213+
my @fmgr_builtin_oid_index;
214+
my $fmgr_count = 0;
199215
foreach my $s (sort { $a->{oid} <=> $b->{oid} } @fmgr)
200216
{
201217
print $tfh
202-
" { $s->{oid}, \"$s->{prosrc}\", $s->{nargs}, $bmap{$s->{strict}}, $bmap{$s->{retset}}, $s->{prosrc} },\n";
218+
" { $s->{oid}, \"$s->{prosrc}\", $s->{nargs}, $bmap{$s->{strict}}, $bmap{$s->{retset}}, $s->{prosrc} }";
219+
220+
$fmgr_builtin_oid_index[$s->{oid}] = $fmgr_count++;
221+
222+
if ($fmgr_count <= $#fmgr)
223+
{
224+
print $tfh ",\n";
225+
}
226+
else
227+
{
228+
print $tfh "\n";
229+
}
230+
}
231+
print $tfh "};\n";
232+
233+
print $tfh qq|
234+
const int fmgr_nbuiltins = (sizeof(fmgr_builtins) / sizeof(FmgrBuiltin));
235+
|;
236+
237+
238+
# Create fmgr_builtins_oid_index table.
239+
#
240+
# Note that the array has to be filled up to FirstBootstrapObjectId,
241+
# as we can't rely on zero initialization as 0 is a valid mapping.
242+
print $tfh qq|
243+
const uint16 fmgr_builtin_oid_index[FirstBootstrapObjectId] = {
244+
|;
245+
246+
for (my $i = 0; $i < $FirstBootstrapObjectId; $i++)
247+
{
248+
my $oid = $fmgr_builtin_oid_index[$i];
249+
250+
# fmgr_builtin_oid_index is sparse, map nonexistant functions to
251+
# InvalidOidBuiltinMapping
252+
if (not defined $oid)
253+
{
254+
$oid = 'InvalidOidBuiltinMapping';
255+
}
256+
257+
if ($i + 1 == $FirstBootstrapObjectId)
258+
{
259+
print $tfh " $oid\n";
260+
}
261+
else
262+
{
263+
print $tfh " $oid,\n";
264+
}
203265
}
266+
print $tfh "};\n";
267+
204268

205269
# And add the file footers.
206270
print $ofh "\n#endif /* FMGROIDS_H */\n";
207271
print $pfh "\n#endif /* FMGRPROTOS_H */\n";
208272

209-
print $tfh
210-
qq| /* dummy entry is easier than getting rid of comma after last real one */
211-
/* (not that there has ever been anything wrong with *having* a
212-
comma after the last field in an array initializer) */
213-
{ 0, NULL, 0, false, false, NULL }
214-
};
215-
216-
/* Note fmgr_nbuiltins excludes the dummy entry */
217-
const int fmgr_nbuiltins = (sizeof(fmgr_builtins) / sizeof(FmgrBuiltin)) - 1;
218-
|;
219-
220273
close($ofh);
221274
close($pfh);
222275
close($tfh);

src/backend/utils/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ fmgrprotos.h: fmgroids.h ;
2525
fmgroids.h: fmgrtab.c ;
2626

2727
fmgrtab.c: Gen_fmgrtab.pl $(catalogdir)/Catalog.pm $(top_srcdir)/src/include/catalog/pg_proc.h
28-
$(PERL) -I $(catalogdir) $< $(top_srcdir)/src/include/catalog/pg_proc.h
28+
$(PERL) -I $(catalogdir) $< -I $(top_srcdir)/src/include/ $(top_srcdir)/src/include/catalog/pg_proc.h
2929

3030
errcodes.h: $(top_srcdir)/src/backend/utils/errcodes.txt generate-errcodes.pl
3131
$(PERL) $(srcdir)/generate-errcodes.pl $< > $@

src/backend/utils/fmgr/fmgr.c

+12-17
Original file line numberDiff line numberDiff line change
@@ -70,26 +70,21 @@ static Datum fmgr_security_definer(PG_FUNCTION_ARGS);
7070
static const FmgrBuiltin *
7171
fmgr_isbuiltin(Oid id)
7272
{
73-
int low = 0;
74-
int high = fmgr_nbuiltins - 1;
73+
uint16 index;
74+
75+
/* fast lookup only possible if original oid still assigned */
76+
if (id >= FirstBootstrapObjectId)
77+
return NULL;
7578

7679
/*
77-
* Loop invariant: low is the first index that could contain target entry,
78-
* and high is the last index that could contain it.
80+
* Lookup function data. If there's a miss in that range it's likely a
81+
* nonexistant function, returning NULL here will trigger an ERROR later.
7982
*/
80-
while (low <= high)
81-
{
82-
int i = (high + low) / 2;
83-
const FmgrBuiltin *ptr = &fmgr_builtins[i];
84-
85-
if (id == ptr->foid)
86-
return ptr;
87-
else if (id > ptr->foid)
88-
low = i + 1;
89-
else
90-
high = i - 1;
91-
}
92-
return NULL;
83+
index = fmgr_builtin_oid_index[id];
84+
if (index == InvalidOidBuiltinMapping)
85+
return NULL;
86+
87+
return &fmgr_builtins[index];
9388
}
9489

9590
/*

src/include/utils/fmgrtab.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313
#ifndef FMGRTAB_H
1414
#define FMGRTAB_H
1515

16+
#include "access/transam.h"
1617
#include "fmgr.h"
1718

1819

1920
/*
2021
* This table stores info about all the built-in functions (ie, functions
21-
* that are compiled into the Postgres executable). The table entries are
22-
* required to appear in Oid order, so that binary search can be used.
22+
* that are compiled into the Postgres executable).
2323
*/
2424

2525
typedef struct
@@ -36,4 +36,11 @@ extern const FmgrBuiltin fmgr_builtins[];
3636

3737
extern const int fmgr_nbuiltins; /* number of entries in table */
3838

39+
/*
40+
* Mapping from a builtin function's oid to the index in the fmgr_builtins
41+
* array.
42+
*/
43+
#define InvalidOidBuiltinMapping UINT16_MAX
44+
extern const uint16 fmgr_builtin_oid_index[FirstBootstrapObjectId];
45+
3946
#endif /* FMGRTAB_H */

0 commit comments

Comments
 (0)