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

Lines changed: 66 additions & 13 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 12 additions & 17 deletions
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

Lines changed: 9 additions & 2 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy