httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jerenkra...@apache.org
Subject cvs commit: httpd-2.0 CHANGES
Date Wed, 19 Sep 2001 06:53:26 GMT
jerenkrantz    01/09/18 23:53:26

  Modified:    server   Makefile.in
               modules/loggers mod_log_config.c
               .        CHANGES
  Added:       include  util_time.h
               server   util_time.c
  Log:
  The call to apr_explode_localtime() in mod_log_config is one of the more
  expensive operations in the httpd.  This patch attempts to reduce the
  overhead by caching the result for 15 seconds.
  
  Submitted by:	Brian Pane <bpane@pacbell.net>
  Reviewed by:	Cliff Woolley, Ryan Bloom, Dean Gaudet, Justin Erenkrantz
  
  Revision  Changes    Path
  1.1                  httpd-2.0/include/util_time.h
  
  Index: util_time.h
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  #ifndef APACHE_UTIL_TIME_H
  #define APACHE_UTIL_TIME_H
  
  #include "apr.h"
  #include "apr_time.h"
  #include "httpd.h"
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /**
   * @package Apache date/time handling functions
   */
  
  /* Maximum delta from the current time, in seconds, for a past time
   * to qualify as "recent" for use in the ap_explode_recent_*() functions:
   */
  #define AP_TIME_RECENT_THRESHOLD 15
  
  /**
   * convert a recent time to its human readable components in local timezone
   * @param tm the exploded time
   * @param t the time to explode: MUST be within the last
   *          AP_TIME_RECENT_THRESHOLD seconds
   * @note This is a faster alternative to apr_explode_localtime that uses
   *       a cache of pre-exploded time structures.  It is useful for things
   *       that need to explode the current time multiple times per second,
   *       like loggers.
   * @return APR_SUCCESS iff successful
   * @deffunc apr_status_t ap_explode_recent_localtime(apr_exploded_time_t *tm, apr_time_t
t);
   */
  AP_DECLARE(apr_status_t) ap_explode_recent_localtime(apr_exploded_time_t *tm,
                                                       apr_time_t t);
  
  /**
   * convert a recent time to its human readable components in GMT timezone
   * @param tm the exploded time
   * @param t the time to explode: MUST be within the last
   *          AP_TIME_RECENT_THRESHOLD seconds
   * @note This is a faster alternative to apr_explode_gmt that uses
   *       a cache of pre-exploded time structures.  It is useful for things
   *       that need to explode the current time multiple times per second,
   *       like loggers.
   * @return APR_SUCCESS iff successful
   * @deffunc apr_status_t ap_explode_recent_gmt(apr_exploded_time_t *tm, apr_time_t t);
   */
  AP_DECLARE(apr_status_t) ap_explode_recent_gmt(apr_exploded_time_t *tm,
                                                 apr_time_t t);
  
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif  /* !APACHE_UTIL_TIME_H */
  
  
  
  1.67      +3 -3      httpd-2.0/server/Makefile.in
  
  Index: Makefile.in
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/Makefile.in,v
  retrieving revision 1.66
  retrieving revision 1.67
  diff -u -r1.66 -r1.67
  --- Makefile.in	2001/09/13 06:49:09	1.66
  +++ Makefile.in	2001/09/19 06:53:26	1.67
  @@ -11,10 +11,10 @@
   LTLIBRARY_SOURCES = \
       test_char.h \
   	config.c log.c main.c vhost.c util.c \
  -	util_script.c util_md5.c util_cfgtree.c util_ebcdic.c \
  +	util_script.c util_md5.c util_cfgtree.c util_ebcdic.c util_time.c \
   	rfc1413.c connection.c listen.c \
  -        mpm_common.c util_charset.c util_debug.c util_xml.c \
  -        util_filter.c exports.c buildmark.c scoreboard.c \
  +	mpm_common.c util_charset.c util_debug.c util_xml.c \
  +	util_filter.c exports.c buildmark.c scoreboard.c \
   	error_bucket.c protocol.c core.c request.c
   
   TARGETS = delete-exports $(LTLIBRARY_NAME) $(CORE_IMPLIB_FILE) export_vars.h httpd.exp
  
  
  
  1.1                  httpd-2.0/server/util_time.c
  
  Index: util_time.c
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  #include "util_time.h"
  
  /* Cache for exploded values of recent timestamps
   */
  
  struct exploded_time_cache_element {
      apr_int64_t t;
      apr_exploded_time_t xt;
      apr_int64_t t_validate; /* please see comments in cached_explode() */
  };
  
  /* the "+ 1" is for the current second: */
  #define TIME_CACHE_SIZE (AP_TIME_RECENT_THRESHOLD + 1)
  
  static struct exploded_time_cache_element exploded_cache_localtime[TIME_CACHE_SIZE];
  static struct exploded_time_cache_element exploded_cache_gmt[TIME_CACHE_SIZE];
  
  
  static apr_status_t cached_explode(apr_exploded_time_t *xt, apr_time_t t,
                                     struct exploded_time_cache_element *cache,
                                     int use_gmt)
  {
      apr_int64_t seconds = t / APR_USEC_PER_SEC;
      struct exploded_time_cache_element *cache_element =
          &(cache[seconds % TIME_CACHE_SIZE]);
      struct exploded_time_cache_element cache_element_snapshot;
  
      /* The cache is implemented as a ring buffer.  Each second,
       * it uses a different element in the buffer.  The timestamp
       * in the element indicates whether the element contains the
       * exploded time for the current second (vs the time
       * 'now - AP_TIME_RECENT_THRESHOLD' seconds ago).  If the
       * cached value is for the current time, we use it.  Otherwise,
       * we compute the apr_exploded_time_t and store it in this
       * cache element. Note that the timestamp in the cache
       * element is updated only after the exploded time.  Thus
       * if two threads hit this cache element simultaneously
       * at the start of a new second, they'll both explode the
       * time and store it.  I.e., the writers will collide, but
       * they'll be writing the same value.
       */
      if (cache_element->t >= seconds) {
          /* There is an intentional race condition in this design:
           * in a multithreaded app, one thread might be reading
           * from this cache_element to resolve a timestamp from
           * TIME_CACHE_SIZE seconds ago at the same time that
           * another thread is copying the exploded form of the
           * current time into the same cache_element.  (I.e., the
           * first thread might hit this element of the ring buffer
           * just as the element is being recycled.)  This can
           * also happen at the start of a new second, if a
           * reader accesses the cache_element after a writer
           * has updated cache_element.t but before the writer
           * has finished updating the whole cache_element.
           *
           * Rather than trying to prevent this race condition
           * with locks, we allow it to happen and then detect
           * and correct it.  The detection works like this:
           *   Step 1: Take a "snapshot" of the cache element by
           *           copying it into a temporary buffer.
           *   Step 2: Check whether the snapshot contains consistent
           *           data: the timestamps at the start and end of
           *           the cache_element should both match the 'seconds'
           *           value that we computed from the input time.
           *           If these three don't match, then the snapshot
           *           shows the cache_element in the middle of an
           *           update, and its contents are invalid.
           *   Step 3: If the snapshot is valid, use it.  Otherwise,
           *           just give up on the cache and explode the
           *           input time.
           */
          memcpy(&cache_element_snapshot, cache_element,
                 sizeof(struct exploded_time_cache_element));
          if ((seconds != cache_element_snapshot.t) ||
              (seconds != cache_element_snapshot.t_validate)) {
              /* Invalid snapshot */
              if (use_gmt) {
                  return apr_explode_gmt(xt, t);
              }
              else {
                  return apr_explode_localtime(xt, t);
              }
          }
          else {
              /* Valid snapshot */
              memcpy(xt, &(cache_element_snapshot.xt),
                     sizeof(apr_exploded_time_t));
          }
      }
      else {
          apr_status_t r;
          if (use_gmt) {
              r = apr_explode_gmt(xt, t);
          }
          else {
              r = apr_explode_localtime(xt, t);
          }
          if (!APR_STATUS_IS_SUCCESS(r)) {
              return r;
          }
          cache_element->t = seconds;
          memcpy(&(cache_element->xt), xt, sizeof(apr_exploded_time_t));
          cache_element->t_validate = seconds;
      }
      xt->tm_usec = t % APR_USEC_PER_SEC;
      return APR_SUCCESS;
  }
  
  
  AP_DECLARE(apr_status_t) ap_explode_recent_localtime(apr_exploded_time_t * tm,
                                                       apr_time_t t)
  {
      return cached_explode(tm, t, exploded_cache_localtime, 0);
  }
  
  AP_DECLARE(apr_status_t) ap_explode_recent_gmt(apr_exploded_time_t * tm,
                                                 apr_time_t t)
  {
      return cached_explode(tm, t, exploded_cache_gmt, 1);
  }
  
  
  
  1.69      +3 -2      httpd-2.0/modules/loggers/mod_log_config.c
  
  Index: mod_log_config.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/loggers/mod_log_config.c,v
  retrieving revision 1.68
  retrieving revision 1.69
  diff -u -r1.68 -r1.69
  --- mod_log_config.c	2001/08/27 20:50:01	1.68
  +++ mod_log_config.c	2001/09/19 06:53:26	1.69
  @@ -196,6 +196,7 @@
   #include "http_core.h"          /* For REMOTE_NAME */
   #include "http_log.h"
   #include "http_protocol.h"
  +#include "util_time.h"
   
   #if APR_HAVE_UNISTD_H
   #include <unistd.h>
  @@ -463,9 +464,9 @@
   	a problem with this, you can set the define.  -djg
       */
   #ifdef I_INSIST_ON_EXTRA_CYCLES_FOR_CLF_COMPLIANCE
  -    apr_explode_localtime(&xt, apr_time_now());
  +    ap_explode_recent_localtime(&xt, apr_time_now());
   #else
  -    apr_explode_localtime(&xt, r->request_time);
  +    ap_explode_recent_localtime(&xt, r->request_time);
   #endif
       if (a && *a) {              /* Custom format */
           apr_strftime(tstr, &retcode, MAX_STRING_LEN, a, &xt);
  
  
  
  1.367     +3 -0      httpd-2.0/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/CHANGES,v
  retrieving revision 1.366
  retrieving revision 1.367
  diff -u -r1.366 -r1.367
  --- CHANGES	2001/09/19 06:20:32	1.366
  +++ CHANGES	2001/09/19 06:53:26	1.367
  @@ -1,5 +1,8 @@
   Changes with Apache 2.0.26-dev
   
  +  *) Cache apr_explode_localtime() value for 15 seconds.
  +     [Brian Pane <bpane@pacbell.net>]
  +
     *) Fix mod_include to not return ETag or Last-Modified headers.
        [Ian Holsman <ianh@cnet.com>]
   
  
  
  

Mime
View raw message