Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5c625a9

Browse files
committed
Add a hash table to cache lookups of 'C'-language functions (that is,
dynamically loaded C functions). Some limited testing suggests thatthis puts the lookup speed for external functions just about on parwith built-in functions. Per discussion with Eric Ridge.
1 parent90d1465 commit5c625a9

File tree

3 files changed

+165
-30
lines changed

3 files changed

+165
-30
lines changed

‎src/backend/utils/fmgr/dfmgr.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.68 2004/01/07 18:56:29 neilc Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.69 2004/01/19 02:06:41 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -213,6 +213,7 @@ load_file(char *filename)
213213
prv->next=nxt;
214214
else
215215
file_list=nxt;
216+
clear_external_function_hash(file_scanner->handle);
216217
pg_dlclose(file_scanner->handle);
217218
free((char*)file_scanner);
218219
/* prv does not change */

‎src/backend/utils/fmgr/fmgr.c

Lines changed: 161 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.79 2004/01/07 18:56:29 neilc Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.80 2004/01/19 02:06:41 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -57,11 +57,29 @@ typedef struct
5757
* toastable datatype? */
5858
}Oldstyle_fnextra;
5959

60+
/*
61+
* Hashtable for fast lookup of external C functions
62+
*/
63+
typedefstruct
64+
{
65+
/* fn_oid is the hash key and so must be first! */
66+
Oidfn_oid;/* OID of an external C function */
67+
TransactionIdfn_xmin;/* for checking up-to-dateness */
68+
CommandIdfn_cmin;
69+
PGFunctionuser_fn;/* the function's address */
70+
Pg_finfo_record*inforec;/* address of its info record */
71+
}CFuncHashTabEntry;
72+
73+
staticHTAB*CFuncHash=NULL;
74+
6075

6176
staticvoidfmgr_info_cxt_security(OidfunctionId,FmgrInfo*finfo,MemoryContextmcxt,
6277
boolignore_security);
6378
staticvoidfmgr_info_C_lang(OidfunctionId,FmgrInfo*finfo,HeapTupleprocedureTuple);
6479
staticvoidfmgr_info_other_lang(OidfunctionId,FmgrInfo*finfo,HeapTupleprocedureTuple);
80+
staticCFuncHashTabEntry*lookup_C_func(HeapTupleprocedureTuple);
81+
staticvoidrecord_C_func(HeapTupleprocedureTuple,
82+
PGFunctionuser_fn,Pg_finfo_record*inforec);
6583
staticDatumfmgr_oldstyle(PG_FUNCTION_ARGS);
6684
staticDatumfmgr_security_definer(PG_FUNCTION_ARGS);
6785

@@ -258,36 +276,58 @@ static void
258276
fmgr_info_C_lang(OidfunctionId,FmgrInfo*finfo,HeapTupleprocedureTuple)
259277
{
260278
Form_pg_procprocedureStruct= (Form_pg_proc)GETSTRUCT(procedureTuple);
261-
Datumprosrcattr,
262-
probinattr;
263-
char*prosrcstring,
264-
*probinstring;
265-
void*libraryhandle;
279+
CFuncHashTabEntry*hashentry;
266280
PGFunctionuser_fn;
267281
Pg_finfo_record*inforec;
268282
Oldstyle_fnextra*fnextra;
269283
boolisnull;
270284
inti;
271285

272-
/* Get prosrc and probin strings (link symbol and library filename) */
273-
prosrcattr=SysCacheGetAttr(PROCOID,procedureTuple,
274-
Anum_pg_proc_prosrc,&isnull);
275-
if (isnull)
276-
elog(ERROR,"null prosrc for function %u",functionId);
277-
prosrcstring=DatumGetCString(DirectFunctionCall1(textout,prosrcattr));
278-
279-
probinattr=SysCacheGetAttr(PROCOID,procedureTuple,
280-
Anum_pg_proc_probin,&isnull);
281-
if (isnull)
282-
elog(ERROR,"null probin for function %u",functionId);
283-
probinstring=DatumGetCString(DirectFunctionCall1(textout,probinattr));
284-
285-
/* Look up the function itself */
286-
user_fn=load_external_function(probinstring,prosrcstring, true,
287-
&libraryhandle);
288-
289-
/* Get the function information record (real or default) */
290-
inforec=fetch_finfo_record(libraryhandle,prosrcstring);
286+
/*
287+
* See if we have the function address cached already
288+
*/
289+
hashentry=lookup_C_func(procedureTuple);
290+
if (hashentry)
291+
{
292+
user_fn=hashentry->user_fn;
293+
inforec=hashentry->inforec;
294+
}
295+
else
296+
{
297+
Datumprosrcattr,
298+
probinattr;
299+
char*prosrcstring,
300+
*probinstring;
301+
void*libraryhandle;
302+
303+
/* Get prosrc and probin strings (link symbol and library filename) */
304+
prosrcattr=SysCacheGetAttr(PROCOID,procedureTuple,
305+
Anum_pg_proc_prosrc,&isnull);
306+
if (isnull)
307+
elog(ERROR,"null prosrc for function %u",functionId);
308+
prosrcstring=DatumGetCString(DirectFunctionCall1(textout,
309+
prosrcattr));
310+
311+
probinattr=SysCacheGetAttr(PROCOID,procedureTuple,
312+
Anum_pg_proc_probin,&isnull);
313+
if (isnull)
314+
elog(ERROR,"null probin for function %u",functionId);
315+
probinstring=DatumGetCString(DirectFunctionCall1(textout,
316+
probinattr));
317+
318+
/* Look up the function itself */
319+
user_fn=load_external_function(probinstring,prosrcstring, true,
320+
&libraryhandle);
321+
322+
/* Get the function information record (real or default) */
323+
inforec=fetch_finfo_record(libraryhandle,prosrcstring);
324+
325+
/* Cache the addresses for later calls */
326+
record_C_func(procedureTuple,user_fn,inforec);
327+
328+
pfree(prosrcstring);
329+
pfree(probinstring);
330+
}
291331

292332
switch (inforec->api_version)
293333
{
@@ -315,9 +355,6 @@ fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
315355
inforec->api_version);
316356
break;
317357
}
318-
319-
pfree(prosrcstring);
320-
pfree(probinstring);
321358
}
322359

323360
/*
@@ -416,6 +453,102 @@ fetch_finfo_record(void *filehandle, char *funcname)
416453
}
417454

418455

456+
/*-------------------------------------------------------------------------
457+
*Routines for caching lookup information for external C functions.
458+
*
459+
* The routines in dfmgr.c are relatively slow, so we try to avoid running
460+
* them more than once per external function per session. We use a hash table
461+
* with the function OID as the lookup key.
462+
*-------------------------------------------------------------------------
463+
*/
464+
465+
/*
466+
* lookup_C_func: try to find a C function in the hash table
467+
*
468+
* If an entry exists and is up to date, return it; else return NULL
469+
*/
470+
staticCFuncHashTabEntry*
471+
lookup_C_func(HeapTupleprocedureTuple)
472+
{
473+
Oidfn_oid=HeapTupleGetOid(procedureTuple);
474+
CFuncHashTabEntry*entry;
475+
476+
if (CFuncHash==NULL)
477+
returnNULL;/* no table yet */
478+
entry= (CFuncHashTabEntry*)
479+
hash_search(CFuncHash,
480+
&fn_oid,
481+
HASH_FIND,
482+
NULL);
483+
if (entry==NULL)
484+
returnNULL;/* no such entry */
485+
if (entry->fn_xmin==HeapTupleHeaderGetXmin(procedureTuple->t_data)&&
486+
entry->fn_cmin==HeapTupleHeaderGetCmin(procedureTuple->t_data))
487+
returnentry;/* OK */
488+
returnNULL;/* entry is out of date */
489+
}
490+
491+
/*
492+
* record_C_func: enter (or update) info about a C function in the hash table
493+
*/
494+
staticvoid
495+
record_C_func(HeapTupleprocedureTuple,
496+
PGFunctionuser_fn,Pg_finfo_record*inforec)
497+
{
498+
Oidfn_oid=HeapTupleGetOid(procedureTuple);
499+
CFuncHashTabEntry*entry;
500+
boolfound;
501+
502+
/* Create the hash table if it doesn't exist yet */
503+
if (CFuncHash==NULL)
504+
{
505+
HASHCTLhash_ctl;
506+
507+
MemSet(&hash_ctl,0,sizeof(hash_ctl));
508+
hash_ctl.keysize=sizeof(Oid);
509+
hash_ctl.entrysize=sizeof(CFuncHashTabEntry);
510+
hash_ctl.hash=tag_hash;
511+
CFuncHash=hash_create("CFuncHash",
512+
100,
513+
&hash_ctl,
514+
HASH_ELEM |HASH_FUNCTION);
515+
if (CFuncHash==NULL)
516+
ereport(ERROR,
517+
(errcode(ERRCODE_OUT_OF_MEMORY),
518+
errmsg("out of memory")));
519+
}
520+
521+
entry= (CFuncHashTabEntry*)
522+
hash_search(CFuncHash,
523+
&fn_oid,
524+
HASH_ENTER,
525+
&found);
526+
if (entry==NULL)
527+
ereport(ERROR,
528+
(errcode(ERRCODE_OUT_OF_MEMORY),
529+
errmsg("out of memory")));
530+
/* OID is already filled in */
531+
entry->fn_xmin=HeapTupleHeaderGetXmin(procedureTuple->t_data);
532+
entry->fn_cmin=HeapTupleHeaderGetCmin(procedureTuple->t_data);
533+
entry->user_fn=user_fn;
534+
entry->inforec=inforec;
535+
}
536+
537+
/*
538+
* clear_external_function_hash: remove entries for a library being closed
539+
*
540+
* Presently we just zap the entire hash table, but later it might be worth
541+
* the effort to remove only the entries associated with the given handle.
542+
*/
543+
void
544+
clear_external_function_hash(void*filehandle)
545+
{
546+
if (CFuncHash)
547+
hash_destroy(CFuncHash);
548+
CFuncHash=NULL;
549+
}
550+
551+
419552
/*
420553
* Copy an FmgrInfo struct
421554
*

‎src/include/fmgr.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
1212
* Portions Copyright (c) 1994, Regents of the University of California
1313
*
14-
* $PostgreSQL: pgsql/src/include/fmgr.h,v 1.32 2003/11/29 22:40:53 pgsql Exp $
14+
* $PostgreSQL: pgsql/src/include/fmgr.h,v 1.33 2004/01/19 02:06:42 tgl Exp $
1515
*
1616
*-------------------------------------------------------------------------
1717
*/
@@ -377,6 +377,7 @@ extern Datum OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2,
377377
* Routines in fmgr.c
378378
*/
379379
externPg_finfo_record*fetch_finfo_record(void*filehandle,char*funcname);
380+
externvoidclear_external_function_hash(void*filehandle);
380381
externOidfmgr_internal_function(constchar*proname);
381382
externOidget_fn_expr_rettype(FmgrInfo*flinfo);
382383
externOidget_fn_expr_argtype(FmgrInfo*flinfo,intargnum);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp