httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Bill Stoddard" <b...@wstoddard.com>
Subject SGI Patch 10xpatch-2.0a6-2: Reduce time resolution to 1 sec
Date Fri, 23 Feb 2001 19:50:34 GMT
The essence of this patch is:

apr_now() calls st_time() rather than a native system call

st_time() returns time with one second resolution, which means it probably
caches the time and updates the cache once per second. If the server serves
1000 cps, this saves 999 calls to determine the system time per second.

The rest of the changes leverage the reduced resolution which makes possible
simpler conversion/formatting functions and caching (of the string to go into
the Date: header for instance) available to other time functions.

This patch would need to be reimplemented to not rely on the state thread
library and would need to be made portable to all platforms and MPMs.

FWIW, I did this exact same thing with the IBM AFPA cache on NT several years
back to handle Date: timestamps.  A timer thread pops once per second to
update the cached Date: string (among other things). I kept two copies of the
string, a 'live' string and an 'update' string and ping-ponged between the two
each timer pop which made locking during updates unnecessary. It was good for
a few % performance boost :-)

Bill


diff -Naur apache_2.0a6/10xpatchlevel-1 apache_2.0a6/10xpatchlevel
--- apache_2.0a6/10xpatchlevel-1 Thu Sep  7 21:06:35 2000
+++ apache_2.0a6/10xpatchlevel Thu Sep  7 22:03:36 2000
@@ -2,4 +2,4 @@
 available from
  http://oss.sgi.com/projects/apache/

-10xpatchlevel=2.0a6-1
+10xpatchlevel=2.0a6-2
diff -Naur apache_2.0a6/htdocs/manual/stm.html-1
apache_2.0a6/htdocs/manual/stm.html
--- apache_2.0a6/htdocs/manual/stm.html-1 Thu Sep  7 21:26:55 2000
+++ apache_2.0a6/htdocs/manual/stm.html Thu Sep  7 22:03:57 2000
@@ -368,6 +368,29 @@

  </TD>
     </TR>
+    <TR>
+ <TD WIDTH=25%>
+     <CODE>USE_ST_TIME</CODE>
+ </TD>
+ <TD>
+
+     Enables more efficient but less accurate time-of-day
+     queries.  Only the presence or absence of this token is
+     meaningful; the value is ignored.
+
+     <P>Apache/2.0 queries the current time of day with
+     one-microsecond resolution upon receipt of each request.
+     One-second resolution usually suffices and is more efficient
+     to query under heavy load (because it uses the state
+     threads library's <A
+
HREF="http://oss.sgi.com/projects/state-threads/docs/reference.html#time">time
+     cache</A>).  This option switches to one-second resolution.
+
+     <P>Default: <CODE>USE_ST_TIME</CODE> is not defined so
+     timekeeping is not accelerated.
+
+ </TD>
+    </TR>
 </TABLE>

 <H3><A NAME="directives">3.2. Configuration Directives</A></H3>
diff -Naur apache_2.0a6/src/lib/apr/time/unix/time.c-1
apache_2.0a6/src/lib/apr/time/unix/time.c
--- apache_2.0a6/src/lib/apr/time/unix/time.c-1 Sat Aug  5 23:07:32 2000
+++ apache_2.0a6/src/lib/apr/time/unix/time.c Thu Sep  7 22:04:50 2000
@@ -73,6 +73,9 @@
 #ifdef BEOS
 #include <sys/socket.h> /* for select */
 #endif
+#ifdef USE_ST_TIME
+#include <st.h>
+#endif
 /* End System Headers */


@@ -85,9 +88,13 @@

 apr_time_t apr_now(void)
 {
+#ifdef USE_ST_TIME
+    return st_time() * APR_USEC_PER_SEC;
+#else
     struct timeval tv;
     gettimeofday(&tv, NULL);
     return tv.tv_sec * APR_USEC_PER_SEC + tv.tv_usec;
+#endif
 }


@@ -166,14 +173,23 @@
 #else
     /* need to create tm_gmtoff... assume we are never more than 24 hours
away */
     {
+ static struct {
+     time_t time;
+     apr_int32_t gmtoff;
+ } last;   /* See apr_rfc822_date() */
  int days, hours, minutes;

- tmx = gmtime(&t);
- days = result->tm_yday - tmx->tm_yday;
- hours = ((days < -1 ? 24 : 1 < days ? -24 : days * 24)
-  + result->tm_hour - tmx->tm_hour);
- minutes = hours * 60 + result->tm_min - tmx->tm_min;
- result->tm_gmtoff = minutes * 60;
+ if (t == last.time)
+     result->tm_gmtoff = last.gmtoff;
+ else {
+     tmx = gmtime(&t);
+     days = result->tm_yday - tmx->tm_yday;
+     hours = ((days < -1 ? 24 : 1 < days ? -24 : days * 24)
+      + result->tm_hour - tmx->tm_hour);
+     minutes = hours * 60 + result->tm_min - tmx->tm_min;
+     last.time = t;
+     result->tm_gmtoff = last.gmtoff = minutes * 60;
+ }
     }
 #endif
 #endif
diff -Naur apache_2.0a6/src/lib/apr/time/unix/timestr.c-1
apache_2.0a6/src/lib/apr/time/unix/timestr.c
--- apache_2.0a6/src/lib/apr/time/unix/timestr.c-1 Sat Aug  5 23:07:33 2000
+++ apache_2.0a6/src/lib/apr/time/unix/timestr.c Thu Sep  7 22:05:00 2000
@@ -83,6 +83,28 @@
     const char *s;
     int real_year;

+#if !APR_HAS_THREADS
+    /*
+     * Assume we're called most often to convert the current time of
+     * day.  Since that changes at most once a second and this
+     * formatting function ignores the microseconds part, cache the
+     * result to avoid unnecessary formatting under very heavy load.
+     * Don't bother doing this in threaded servers because mutex locking
+     * the cached data probably would hurt more than caching would help.
+     */
+    static struct {
+ apr_time_t  time;
+ time_t     secs;
+ char     str[APR_RFC822_DATE_LEN];
+    } last;
+    time_t secs;
+
+    if (t == last.time || (secs = t / APR_USEC_PER_SEC) == last.secs) {
+ memcpy(date_str, last.str, APR_RFC822_DATE_LEN);
+ return APR_SUCCESS;
+    }
+#endif
+
     apr_explode_gmt(&xt, t);

     /* example: "Sat, 08 Jan 2000 18:31:41 GMT" */
@@ -122,6 +144,13 @@
     *date_str++ = 'M';
     *date_str++ = 'T';
     *date_str++ = 0;
+
+#if !APR_HAS_THREADS
+    last.time = t;
+    last.secs = secs;
+    memcpy(last.str, date_str - APR_RFC822_DATE_LEN, APR_RFC822_DATE_LEN);
+#endif
+
     return APR_SUCCESS;
 }

diff -Naur apache_2.0a6/src/main/http_main.c-1
apache_2.0a6/src/main/http_main.c
--- apache_2.0a6/src/main/http_main.c-1 Thu Sep  7 21:30:53 2000
+++ apache_2.0a6/src/main/http_main.c Thu Sep  7 22:05:08 2000
@@ -182,6 +182,9 @@
 #ifdef STM_VP_LIMIT
     printf(" -D STM_VP_LIMIT=%ld\n", (long) STM_VP_LIMIT);
 #endif
+#ifdef USE_ST_TIME
+    printf(" -D USE_ST_TIME\n");
+#endif

 /* This list displays the compiled in default paths: */
 #ifdef HTTPD_ROOT
diff -Naur apache_2.0a6/src/modules/experimental/mod_mmap_static.c-1
apache_2.0a6/src/modules/experimental/mod_mmap_static.c
--- apache_2.0a6/src/modules/experimental/mod_mmap_static.c-1 Sat Aug  5
23:07:38 2000
+++ apache_2.0a6/src/modules/experimental/mod_mmap_static.c Thu Sep  7
22:05:28 2000
@@ -128,6 +128,7 @@
 #include "http_request.h"
 #include "http_core.h"
 #include "apr_mmap.h"
+#include "apr_strings.h"

 module MODULE_VAR_EXPORT mmap_static_module;

@@ -135,6 +136,7 @@
     apr_mmap_t *mm;
     char *filename;
     apr_finfo_t finfo;
+    char mtimestr[APR_RFC822_DATE_LEN];
 } a_file;

 typedef struct {
@@ -199,6 +201,7 @@
     }
     apr_close(fd);
     tmp.filename = apr_pstrdup(cmd->pool, filename);
+    apr_rfc822_date(tmp.mtimestr, tmp.finfo.mtime);
     sconf = ap_get_module_config(cmd->server->module_config,
&mmap_static_module);
     new_file = apr_push_array(sconf->files);
     *new_file = tmp;
@@ -297,7 +300,26 @@
         return errstatus;

     ap_update_mtime(r, match->finfo.mtime);
-    ap_set_last_modified(r);
+
+    /*
+     * ap_set_last_modified() always converts the file mtime to a string
+     * which is slow.  Accelerate the common case.
+     * ap_set_last_modified(r);
+     */
+    {
+ apr_time_t mod_time;
+ char *datestr;
+
+ mod_time = ap_rationalize_mtime(r, r->mtime);
+ if (mod_time == match->finfo.mtime)
+     datestr = match->mtimestr;
+ else {
+     datestr = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
+     apr_rfc822_date(datestr, mod_time);
+ }
+ apr_table_setn(r->headers_out, "Last-Modified", datestr);
+    }
+
     ap_set_etag(r);
     if (((errstatus = ap_meets_conditions(r)) != OK)
  || (errstatus = ap_set_content_length (r, match->finfo.size))) {
diff -Naur apache_2.0a6/src/modules/standard/mod_log_config.c-1
apache_2.0a6/src/modules/standard/mod_log_config.c
--- apache_2.0a6/src/modules/standard/mod_log_config.c-1 Sat Aug  5 23:07:47
2000
+++ apache_2.0a6/src/modules/standard/mod_log_config.c Thu Sep  7 22:06:11
2000
@@ -386,9 +386,17 @@

 static const char *log_request_time(request_rec *r, char *a)
 {
+    apr_time_t t;
     apr_exploded_time_t xt;
     apr_size_t retcode;
     char tstr[MAX_STRING_LEN];
+#if !APR_HAS_THREADS
+    /* Cache the last converted time.  See apr_rfc822_date(). */
+    static struct {
+ apr_time_t  time;
+ char     str[32];
+    } last;
+#endif

     /*
  hi.  i think getting the time again at the end of the request
@@ -402,17 +410,26 @@
  a problem with this, you can set the define.  -djg
     */
 #ifdef I_INSIST_ON_EXTRA_CYCLES_FOR_CLF_COMPLIANCE
-    apr_explode_localtime(&xt, apr_now());
+    t = apr_now();
 #else
-    apr_explode_localtime(&xt, r->request_time);
+    t = r->request_time;
 #endif
+
     if (a && *a) {              /* Custom format */
+ apr_explode_localtime(&xt, t);
         apr_strftime(tstr, &retcode, MAX_STRING_LEN, a, &xt);
+ return apr_pstrdup(r->pool, tstr);
     }
     else {                      /* CLF format */
  char sign;
  int timz;

+#if !APR_HAS_THREADS
+ if (t == last.time)
+     return last.str;
+#endif
+
+ apr_explode_localtime(&xt, t);
  timz = xt.tm_gmtoff;
  if (timz < 0) {
      timz = -timz;
@@ -422,13 +439,24 @@
      sign = '+';
  }

-        apr_snprintf(tstr, sizeof(tstr), "[%02d/%s/%d:%02d:%02d:%02d
%c%.2d%.2d]",
+        apr_snprintf(
+#if APR_HAS_THREADS
+  tstr, sizeof(tstr),
+#else
+  last.str, sizeof(last.str),
+#endif
+  "[%02d/%s/%d:%02d:%02d:%02d %c%.2d%.2d]",
                 xt.tm_mday, apr_month_snames[xt.tm_mon], xt.tm_year+1900,
                 xt.tm_hour, xt.tm_min, xt.tm_sec,
                 sign, timz / (60*60), timz % (60*60));
-    }

-    return apr_pstrdup(r->pool, tstr);
+#if APR_HAS_THREADS
+ return apr_pstrdup(r->pool, tstr);
+#else
+ last.time = t;
+ return last.str;
+#endif
+    }
 }

 static const char *log_request_duration(request_rec *r, char *a)




Mime
View raw message