]> granicus.if.org Git - postgresql/commitdiff
> I can see a couple possible downsides: (a) the library might have some
authorBruce Momjian <bruce@momjian.us>
Thu, 20 Mar 2003 04:51:44 +0000 (04:51 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 20 Mar 2003 04:51:44 +0000 (04:51 +0000)
> 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

doc/src/sgml/runtime.sgml
src/backend/postmaster/postmaster.c
src/backend/utils/init/miscinit.c
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/include/miscadmin.h

index 408c81e2ee5a444453f1366bb0936c077153ab76..0f53895fdcde3a7e446d699b0481263eeeae3d88 100644 (file)
@@ -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">
@@ -1799,6 +1799,35 @@ dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir'
       </listitem>
      </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>
       <term><varname>REGEX_FLAVOR</varname> (<type>string</type>)</term>
       <indexterm><primary>regular expressions</></>
index 3ce63e05d63a8b8b948d55c2f02e9a782b09a412..13cc86e98c76e79a6d29c501e58550c111cc3218 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * 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
  *
@@ -205,6 +205,8 @@ bool                LogSourcePort;
 bool           Log_connections = false;
 bool           Db_user_namespace = false;
 
+/* list of library:init-function to be preloaded */
+char       *preload_libraries_string = NULL;
 
 /* Startup/shutdown state */
 static pid_t StartupPID = 0,
@@ -645,6 +647,13 @@ PostmasterMain(int argc, char *argv[])
                secure_initialize();
 #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.
         *
index 12154396193a0fb6a1b076426ec663c6db19a414..8b49ca2e5849af958dbefffc0f50eeb26ce3274c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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.",
                         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);
+}
+
index 37e1192b6d0c8e2a65d44bb7144c01a6a5d80f9e..7c5d6d1884964f50bec140d773f58468b60937ea 100644 (file)
@@ -5,7 +5,7 @@
  * command, configuration file, and command line options.
  * 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
  * Written by Peter Eisentraut <peter_e@gmx.net>.
@@ -60,6 +60,7 @@ extern int    CheckPointTimeout;
 extern bool autocommit;
 extern int     CommitDelay;
 extern int     CommitSiblings;
+extern char *preload_libraries_string;
 
 #ifdef HAVE_SYSLOG
 extern char *Syslog_facility;
@@ -814,6 +815,12 @@ static struct config_string
                "C", locale_time_assign, NULL
        },
 
+       {
+               {"preload_libraries", PGC_POSTMASTER, GUC_LIST_INPUT | GUC_LIST_QUOTE},
+               &preload_libraries_string,
+               "", NULL, NULL
+       },
+
        {
                {"regex_flavor", PGC_USERSET}, &regex_flavor_string,
                "advanced", assign_regex_flavor, NULL
index 40b143c7cab553f915c8f34e06b778d76c0bc8d6..c290df19d9943695468eb1fffa768af91859e5bb 100644 (file)
 #transform_null_equals = false
 #statement_timeout = 0         # 0 is disabled, in milliseconds
 #db_user_namespace = false
+#preload_libraries = ''
  
index f8321325f6c3b1a44d20bbaa475a8cd03ef5b465..e44d0fbad30740fd792d31ee2aead041473aca1f 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * 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
  *       some of the information in this file should be moved to
@@ -288,6 +288,7 @@ extern void RecordSharedMemoryInLockFile(unsigned long id1,
                                                         unsigned long id2);
 
 extern void ValidatePgVersion(const char *path);
+extern void process_preload_libraries(char *preload_libraries_string);
 
 /* these externs do not belong here... */
 extern void IgnoreSystemIndexes(bool mode);