mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	> I can see a couple possible downsides: (a) the library might have some
> weird behavior across fork boundaries; (b) the additional memory space > that has to be duplicated into child processes will cost something per > child launch, even if the child never uses it. But these are only > arguments that it might not *always* be a prudent thing to do, not that > we shouldn't give the DBA the tool to do it if he wants. So fire away. Here is a patch for the above, including a documentation update. It creates a new GUC variable "preload_libraries", that accepts a list in the form: preload_libraries = '$libdir/mylib1:initfunc,$libdir/mylib2' If ":initfunc" is omitted or not found, no initialization function is executed, but the library is still preloaded. If "$libdir/mylib" isn't found, the postmaster refuses to start. In my testing with PL/R, it reduces the first call to a PL/R function (after connecting) from almost 2 seconds, down to about 8 ms. Joe Conway
This commit is contained in:
		@@ -1,5 +1,5 @@
 | 
				
			|||||||
<!--
 | 
					<!--
 | 
				
			||||||
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.171 2003/03/20 03:34:55 momjian Exp $
 | 
					$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.172 2003/03/20 04:51:44 momjian Exp $
 | 
				
			||||||
-->
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<Chapter Id="runtime">
 | 
					<Chapter Id="runtime">
 | 
				
			||||||
@@ -1799,6 +1799,35 @@ dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir'
 | 
				
			|||||||
      </listitem>
 | 
					      </listitem>
 | 
				
			||||||
     </varlistentry>
 | 
					     </varlistentry>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     <varlistentry>
 | 
				
			||||||
 | 
					      <term><varname>PRELOAD_LIBRARIES</varname> (<type>string</type>)</term>
 | 
				
			||||||
 | 
					      <indexterm><primary>preload_libraries</></>
 | 
				
			||||||
 | 
					      <listitem>
 | 
				
			||||||
 | 
					       <para>
 | 
				
			||||||
 | 
					        This variable specifies one or more shared libraries that are to be
 | 
				
			||||||
 | 
						preloaded at Postmaster start. An initialization function can also be
 | 
				
			||||||
 | 
						optionally specified by adding a colon followed by the name of the
 | 
				
			||||||
 | 
						initialization function after the library name. For example
 | 
				
			||||||
 | 
						<literal>'$libdir/mylib:init_mylib'</literal> would cause <literal>mylib</>
 | 
				
			||||||
 | 
					    to be preloaded and <literal>init_mylib</> to be executed. If more than
 | 
				
			||||||
 | 
						one library is to be loaded, they must be delimited with a comma.
 | 
				
			||||||
 | 
					       </para>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       <para>
 | 
				
			||||||
 | 
					        If <literal>mylib</> is not found, the postmaster will fail to start.
 | 
				
			||||||
 | 
						However, if <literal>init_mylib</> is not found, <literal>mylib</> will
 | 
				
			||||||
 | 
						still be preloaded without executing the initialization function.
 | 
				
			||||||
 | 
					       </para>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       <para>
 | 
				
			||||||
 | 
					        By preloading a shared library (and initializing it if applicable),
 | 
				
			||||||
 | 
						the library startup time is avoided when the library is used later in a
 | 
				
			||||||
 | 
						specific backend. However there is a cost in terms of memory duplication
 | 
				
			||||||
 | 
						as every backend is forked, whether or not the library is used.
 | 
				
			||||||
 | 
					       </para>
 | 
				
			||||||
 | 
					      </listitem>
 | 
				
			||||||
 | 
					     </varlistentry>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     <varlistentry>
 | 
					     <varlistentry>
 | 
				
			||||||
      <term><varname>REGEX_FLAVOR</varname> (<type>string</type>)</term>
 | 
					      <term><varname>REGEX_FLAVOR</varname> (<type>string</type>)</term>
 | 
				
			||||||
      <indexterm><primary>regular expressions</></>
 | 
					      <indexterm><primary>regular expressions</></>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,7 +37,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.307 2003/02/23 04:48:19 tgl Exp $
 | 
					 *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.308 2003/03/20 04:51:44 momjian Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * NOTES
 | 
					 * NOTES
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -205,6 +205,8 @@ bool		LogSourcePort;
 | 
				
			|||||||
bool		Log_connections = false;
 | 
					bool		Log_connections = false;
 | 
				
			||||||
bool		Db_user_namespace = false;
 | 
					bool		Db_user_namespace = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* list of library:init-function to be preloaded */
 | 
				
			||||||
 | 
					char       *preload_libraries_string = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Startup/shutdown state */
 | 
					/* Startup/shutdown state */
 | 
				
			||||||
static pid_t StartupPID = 0,
 | 
					static pid_t StartupPID = 0,
 | 
				
			||||||
@@ -645,6 +647,13 @@ PostmasterMain(int argc, char *argv[])
 | 
				
			|||||||
		secure_initialize();
 | 
							secure_initialize();
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * process any libraries that should be preloaded and
 | 
				
			||||||
 | 
						 * optionally pre-initialized
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (preload_libraries_string)
 | 
				
			||||||
 | 
							process_preload_libraries(preload_libraries_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Fork away from controlling terminal, if -S specified.
 | 
						 * Fork away from controlling terminal, if -S specified.
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.100 2003/01/27 00:51:06 tgl Exp $
 | 
					 *	  $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.101 2003/03/20 04:51:44 momjian Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -1044,3 +1044,92 @@ ValidatePgVersion(const char *path)
 | 
				
			|||||||
			 "which is not compatible with this version %s.",
 | 
								 "which is not compatible with this version %s.",
 | 
				
			||||||
			 file_major, file_minor, version_string);
 | 
								 file_major, file_minor, version_string);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*-------------------------------------------------------------------------
 | 
				
			||||||
 | 
					 *				Library preload support
 | 
				
			||||||
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__mc68000__) && defined(__ELF__)
 | 
				
			||||||
 | 
					typedef int32 ((*func_ptr) ());
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					typedef char *((*func_ptr) ());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * process any libraries that should be preloaded and
 | 
				
			||||||
 | 
					 * optionally pre-initialized
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					process_preload_libraries(char *preload_libraries_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char	   *rawstring;
 | 
				
			||||||
 | 
						List	   *elemlist;
 | 
				
			||||||
 | 
						List	   *l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (preload_libraries_string == NULL)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Need a modifiable copy of string */
 | 
				
			||||||
 | 
						rawstring = pstrdup(preload_libraries_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Parse string into list of identifiers */
 | 
				
			||||||
 | 
						if (!SplitIdentifierString(rawstring, ',', &elemlist))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* syntax error in list */
 | 
				
			||||||
 | 
							pfree(rawstring);
 | 
				
			||||||
 | 
							freeList(elemlist);
 | 
				
			||||||
 | 
							elog(LOG, "invalid list syntax for preload_libraries configuration option");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						foreach(l, elemlist)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							char	   *tok = (char *) lfirst(l);
 | 
				
			||||||
 | 
							char	   *sep = strstr(tok, ":");
 | 
				
			||||||
 | 
							char	   *filename = NULL;
 | 
				
			||||||
 | 
							char	   *funcname = NULL;
 | 
				
			||||||
 | 
							func_ptr	initfunc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (sep)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * a colon separator implies there is an initialization function
 | 
				
			||||||
 | 
								 * that we need to run in addition to loading the library
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								size_t		filename_len = sep - tok;
 | 
				
			||||||
 | 
								size_t		funcname_len = strlen(tok) - filename_len - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								filename = (char *) palloc(filename_len + 1);
 | 
				
			||||||
 | 
								memset(filename, '\0', filename_len + 1);
 | 
				
			||||||
 | 
								snprintf(filename, filename_len + 1, "%s", tok);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								funcname = (char *) palloc(funcname_len + 1);
 | 
				
			||||||
 | 
								memset(funcname, '\0', funcname_len + 1);
 | 
				
			||||||
 | 
								snprintf(funcname, funcname_len + 1, "%s", sep + 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * no separator -- just load the library
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								filename = pstrdup(tok);
 | 
				
			||||||
 | 
								funcname = NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							initfunc = (func_ptr) load_external_function(filename, funcname, false, NULL);
 | 
				
			||||||
 | 
							if (initfunc)
 | 
				
			||||||
 | 
								(*initfunc)();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							elog(LOG, "preloaded library %s with initialization function %s", filename, funcname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (filename != NULL)
 | 
				
			||||||
 | 
								pfree(filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (funcname != NULL)
 | 
				
			||||||
 | 
								pfree(funcname);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pfree(rawstring);
 | 
				
			||||||
 | 
						freeList(elemlist);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@
 | 
				
			|||||||
 * command, configuration file, and command line options.
 | 
					 * command, configuration file, and command line options.
 | 
				
			||||||
 * See src/backend/utils/misc/README for more information.
 | 
					 * See src/backend/utils/misc/README for more information.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.116 2003/03/04 21:51:21 tgl Exp $
 | 
					 * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.117 2003/03/20 04:51:44 momjian Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Copyright 2000 by PostgreSQL Global Development Group
 | 
					 * Copyright 2000 by PostgreSQL Global Development Group
 | 
				
			||||||
 * Written by Peter Eisentraut <peter_e@gmx.net>.
 | 
					 * Written by Peter Eisentraut <peter_e@gmx.net>.
 | 
				
			||||||
@@ -60,6 +60,7 @@ extern int	CheckPointTimeout;
 | 
				
			|||||||
extern bool autocommit;
 | 
					extern bool autocommit;
 | 
				
			||||||
extern int	CommitDelay;
 | 
					extern int	CommitDelay;
 | 
				
			||||||
extern int	CommitSiblings;
 | 
					extern int	CommitSiblings;
 | 
				
			||||||
 | 
					extern char *preload_libraries_string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_SYSLOG
 | 
					#ifdef HAVE_SYSLOG
 | 
				
			||||||
extern char *Syslog_facility;
 | 
					extern char *Syslog_facility;
 | 
				
			||||||
@@ -814,6 +815,12 @@ static struct config_string
 | 
				
			|||||||
		"C", locale_time_assign, NULL
 | 
							"C", locale_time_assign, NULL
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							{"preload_libraries", PGC_POSTMASTER, GUC_LIST_INPUT | GUC_LIST_QUOTE},
 | 
				
			||||||
 | 
							&preload_libraries_string,
 | 
				
			||||||
 | 
							"", NULL, NULL
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		{"regex_flavor", PGC_USERSET}, ®ex_flavor_string,
 | 
							{"regex_flavor", PGC_USERSET}, ®ex_flavor_string,
 | 
				
			||||||
		"advanced", assign_regex_flavor, NULL
 | 
							"advanced", assign_regex_flavor, NULL
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -214,4 +214,5 @@
 | 
				
			|||||||
#transform_null_equals = false
 | 
					#transform_null_equals = false
 | 
				
			||||||
#statement_timeout = 0		# 0 is disabled, in milliseconds
 | 
					#statement_timeout = 0		# 0 is disabled, in milliseconds
 | 
				
			||||||
#db_user_namespace = false
 | 
					#db_user_namespace = false
 | 
				
			||||||
 | 
					#preload_libraries = ''
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@
 | 
				
			|||||||
 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
 | 
					 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
 | 
				
			||||||
 * Portions Copyright (c) 1994, Regents of the University of California
 | 
					 * Portions Copyright (c) 1994, Regents of the University of California
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * $Id: miscadmin.h,v 1.116 2003/02/22 05:57:45 tgl Exp $
 | 
					 * $Id: miscadmin.h,v 1.117 2003/03/20 04:51:44 momjian Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * NOTES
 | 
					 * NOTES
 | 
				
			||||||
 *	  some of the information in this file should be moved to
 | 
					 *	  some of the information in this file should be moved to
 | 
				
			||||||
@@ -288,6 +288,7 @@ extern void RecordSharedMemoryInLockFile(unsigned long id1,
 | 
				
			|||||||
							 unsigned long id2);
 | 
												 unsigned long id2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void ValidatePgVersion(const char *path);
 | 
					extern void ValidatePgVersion(const char *path);
 | 
				
			||||||
 | 
					extern void process_preload_libraries(char *preload_libraries_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* these externs do not belong here... */
 | 
					/* these externs do not belong here... */
 | 
				
			||||||
extern void IgnoreSystemIndexes(bool mode);
 | 
					extern void IgnoreSystemIndexes(bool mode);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user