joes        2003/04/28 20:35:56

  Modified:    src      apreq_tables.c apreq_tables.h
  Log:
  Speed hacks: apreq_table lookups are now faster than apr_table.
  
  Revision  Changes    Path
  1.24      +86 -39    httpd-apreq-2/src/apreq_tables.c
  
  Index: apreq_tables.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_tables.c,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- apreq_tables.c    28 Apr 2003 14:05:01 -0000      1.23
  +++ apreq_tables.c    29 Apr 2003 03:35:55 -0000      1.24
  @@ -68,6 +68,7 @@
   #endif
   #include "apr_signal.h"
   
  +#include <assert.h>
   /********************* table_entry structure ********************/
   
   /* private struct */
  @@ -75,7 +76,7 @@
   typedef struct apreq_table_entry_t {
       const apreq_value_t *val;
       const char          *key;   /* = val->name : saves a ptr deref */
  -
  +    apr_uint32_t         checksum;
       enum { RED, BLACK }  color;
       int                  tree[4];  /* LEFT RIGHT UP NEXT */
   } apreq_table_entry_t;
  @@ -90,13 +91,36 @@
   
   /********************* table structure ********************/
   
  +#if APR_CHARSET_EBCDIC
  +#define CASE_MASK 0xbfbfbfbf
  +#else
  +#define CASE_MASK 0xdfdfdfdf
  +#endif
   
   #define TABLE_HASH_SIZE 16
   #define TABLE_INDEX_MASK 0x0f
  -
  -/* TABLE_HASH must be compatible with table comparator t->cmp */
  -/* this one is strcasecmp compatible */
  -#define TABLE_HASH(key)  (TABLE_INDEX_MASK & *(unsigned char *)(key))
  +#define TABLE_HASH(c)  (TABLE_INDEX_MASK & (unsigned char)(c))
  +#define COMPUTE_KEY_CHECKSUM(k, checksum)    \
  +{                                            \
  +    apr_uint32_t c = (apr_uint32_t)*(k);     \
  +    (checksum) = c;                          \
  +    (checksum) <<= 8;                        \
  +    if (c) {                                 \
  +        c = (apr_uint32_t)*++(k);            \
  +        checksum |= c;                       \
  +    }                                        \
  +    (checksum) <<= 8;                        \
  +    if (c) {                                 \
  +        c = (apr_uint32_t)*++(k);            \
  +        checksum |= c;                       \
  +    }                                        \
  +    (checksum) <<= 8;                        \
  +    if (c) {                                 \
  +        c = (apr_uint32_t)*++(k);            \
  +        checksum |= c;                       \
  +    }                                        \
  +    checksum &= CASE_MASK;                   \
  +}
   
   
   /* XXX: apreq_tables need to be signal( thread? )safe; currently
  @@ -129,11 +153,12 @@
   #define KILL(t,idx)    do { (idx)[o].key = NULL; \
                               (t)->ghosts++; } while (0)
   #define RESURRECT(t,idx) do { (idx)[o].key = (idx)[o].val->name; \
  -                              (t)->ghosts--; } while (0)
  +           COMPUTE_KEY_CHECKSUM((idx[o].key),(idx)[o].checksum); \
  +                                               (t)->ghosts--; } while (0)
   
   /* NEVER KILL AN ENTRY THAT'S STILL WITHIN THE FOREST */
   #define IN_FOREST(t,idx) ( !DEAD(idx) && ( (idx)[o].tree[UP] >= 0 || \
  -                           (idx) == t->root[TABLE_HASH((idx)[o].key)] ) )
  +                           (idx) == 
t->root[TABLE_HASH((idx)[o].checksum>>24)] ) )
   
   /* MUST ensure n's parent exists (>=0) before using LR(n) */
   #define LR(n) (  ( (n)[o].tree[UP][o].tree[LEFT] == (n) ) ? LEFT : RIGHT  )
  @@ -198,11 +223,15 @@
                                const char *key) 
   {
       int idx = *elt;
  +    apr_uint32_t checksum;
       if ( idx < 0)
           return 0;
   
  +    COMPUTE_KEY_CHECKSUM(key, checksum);
  +
       while (1) {
  -        int direction = strcasecmp(key,idx[o].key);
  +        int direction = (checksum == idx[o].checksum) ? 
  +            strcasecmp(key,idx[o].key) : checksum - idx[o].checksum;
   
           if (direction < 0 && idx[o].tree[LEFT] >= 0)
               idx = idx[o].tree[LEFT];
  @@ -233,6 +262,7 @@
       if (parent >= 0 && parent[o].color == RED) {        \
           int parent_direction = LR(parent);              \
           int grandparent = parent[o].tree[UP];           \
  +        assert(parent >=0 && grandparent >= 0);         \
           if (parent_direction != LR(x)) {                \
               rotate(o, root, parent, parent_direction);  \
               parent = x;                                 \
  @@ -249,11 +279,13 @@
            * corrects potential red-red violations prior to insertion:
            *      http://www.cs.uiowa.edu/~hzhang/c44/lec14.PDF
            */
  +
           while (1) {
               int left = x[o].tree[LEFT];
               int right = x[o].tree[RIGHT];
   
  -            s = strcasecmp(elt->key,x[o].key);
  +            s = (elt->checksum == x[o].checksum) ? 
  +                strcasecmp(elt->key,x[o].key) : elt->checksum - 
x[o].checksum;
   
               if (s < 0 && left >= 0) {
                   if (left[o].color == RED && right >= 0 
  @@ -278,7 +310,7 @@
           }
       }
       else
  -        s = search(o, &x, elt->key);
  +        s = search(o, &x, elt->val->name);
   
       if (s == 0) { /* found */
           int parent = x;
  @@ -310,9 +342,9 @@
       elt->tree[UP]    =  x;
       elt->tree[RIGHT] = -1;
       elt->tree[LEFT]  = -1;
  -    elt->color = RED;
   
       if (flags & TF_BALANCE) {
  +        elt->color = RED;
           x = idx;
           REBALANCE;
       }
  @@ -320,7 +352,6 @@
       return -1;
   }
   
  -
   static void delete(apreq_table_entry_t *o, 
                      int *root,  const int idx, unsigned flags)
   {
  @@ -374,8 +405,10 @@
               y[o].color = idx[o].color;
               return;
           }
  -        else
  +        else {
               y[o].color = idx[o].color;
  +            x = y;
  +        }
       }
   
   
  @@ -392,7 +425,8 @@
           int parent = x[o].tree[UP];
           register const int direction = LR(x);
           int sibling = parent[o].tree[!direction];
  -
  +        assert(parent >= 0);
  +        assert(sibling >= 0);
           if (sibling[o].color == RED) {
               sibling[o].color = BLACK;
               parent[o].color  = RED;
  @@ -549,7 +583,7 @@
       memcpy(new->root, t->root, TABLE_HASH_SIZE * sizeof(int));
       new->merge = t->merge;
       new->copy = t->copy;
  -    new->flags=t->flags;
  +    new->flags = t->flags;
       return new;
   }
   
  @@ -559,7 +593,7 @@
   {
       int idx;
       apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  -    apr_table_t *s = apr_table_make(p, t->a.nelts);
  +    apr_table_t *s = apr_table_make(p, t->a.nalloc);
   
       for (idx = 0; idx < t->a.nelts; ++idx) {
           if (! DEAD(idx)) {
  @@ -650,9 +684,9 @@
   
           memset(t->root,-1,TABLE_HASH_SIZE * sizeof(int));
           for (idx = 0; idx < t->a.nelts; ++idx)
  -            if (IN_FOREST(t,idx))
  -                insert(o, &t->root[TABLE_HASH(idx[o].key)], 
  -                       -1, &idx[o], TF_BALANCE);
  +            if (!DEAD(idx))
  +                insert(o, &t->root[TABLE_HASH(idx[o].checksum>>24)], 
  +                       t->root[TABLE_HASH(idx[o].checksum>>24)], idx+o, 
TF_BALANCE);
   
           t->flags |= TF_BALANCE;
       }
  @@ -697,14 +731,18 @@
                       RESURRECT(t,j);
               }
               else {
  -                idx[o].key = idx[o].val->name;
                   idx[o].val = v;
                   idx[o].tree[NEXT] = -1;
               }
           }
       }
  -    return status;
   
  +    while (DEAD(t->a.nelts-1)) {
  +        t->ghosts--;
  +        t->a.nelts--;
  +    }
  +
  +    return status;
   }
   
   static int bury_table_entries(apreq_table_t *t, apr_array_header_t *q)
  @@ -776,7 +814,7 @@
   APREQ_DECLARE(const char *) apreq_table_get(const apreq_table_t *t,
                                                const char *key)
   {
  -    int idx = t->root[TABLE_HASH(key)];
  +    int idx = t->root[TABLE_HASH(*key)];
       apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
   
       if ( idx < 0 || search(o,&idx,key) )
  @@ -788,7 +826,7 @@
   APREQ_DECLARE(const char *) apreq_table_cache(apreq_table_t *t,
                                                 const char *key)
   {
  -    int *root = &t->root[TABLE_HASH(key)];
  +    int *root = &t->root[TABLE_HASH(*key)];
       int idx = *root;
       apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
   
  @@ -813,7 +851,7 @@
   
       for (idx = 0; idx < t->a.nelts; ++idx)
           if (IN_FOREST(t,idx))
  -            *(const char **)apr_array_push(keys) = idx[o].key;
  +            *(const char **)apr_array_push(keys) = idx[o].val->name;
   
       return APR_SUCCESS;
   
  @@ -835,7 +873,7 @@
                   *(const apreq_value_t **)apr_array_push(values) = idx[o].val;
       }
       else {
  -        idx = t->root[TABLE_HASH(key)];
  +        idx = t->root[TABLE_HASH(*key)];
           if ( idx>=0 && search(o,&idx,key) == 0 )
              for ( ; idx>=0; idx = idx[o].tree[NEXT] )
                   *(const apreq_value_t **)apr_array_push(values) = idx[o].val;
  @@ -851,15 +889,16 @@
                                       const apreq_value_t *val)
   {
       const char *key = val->name;
  -    int idx = t->root[TABLE_HASH(key)];
  +    int idx;
       apreq_table_entry_t *e = table_push(t);
       apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
   
       e->key = key;
       e->val = val;
       e->tree[NEXT] = -1;
  -
  -    idx = insert(o,&t->root[TABLE_HASH(key)], idx ,e,t->flags);
  +    COMPUTE_KEY_CHECKSUM(e->key,e->checksum);
  +    idx = insert(o,&t->root[TABLE_HASH(*key)], 
  +                 t->root[TABLE_HASH(*key)] ,e,t->flags);
   
       if (idx >= 0) {
           int n;
  @@ -879,12 +918,12 @@
   
   APREQ_DECLARE(void) apreq_table_unset(apreq_table_t *t, const char *key)
   {
  -    int idx = t->root[TABLE_HASH(key)];
  +    int idx = t->root[TABLE_HASH(*key)];
       apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
   
       if (idx >= 0 && search(o,&idx,key) == 0) {
           int n;
  -        delete(o,&t->root[TABLE_HASH(key)],idx, t->flags);
  +        delete(o,&t->root[TABLE_HASH(*key)],idx, t->flags);
           for ( n=idx; n>=0; n=n[o].tree[NEXT] )
               KILL(t,n);
       }
  @@ -895,15 +934,15 @@
                                         const apreq_value_t *val)
   {
       const char *key = val->name;
  -    int idx = t->root[TABLE_HASH(key)];
  +    int idx = t->root[TABLE_HASH(*key)];
       apreq_table_entry_t *e = table_push(t);
       apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
   
  -    e->key = val->name;
  +    e->key = key;
       e->val = val;
       e->tree[NEXT] = -1;
  -
  -    idx = insert(o,&t->root[TABLE_HASH(key)],idx,e,t->flags);
  +    COMPUTE_KEY_CHECKSUM(key,e->checksum);
  +    idx = insert(o,&t->root[TABLE_HASH(*key)],idx,e,t->flags);
   
       if (idx >= 0) {
           int n;
  @@ -956,12 +995,13 @@
       {
           const char *key = val->name;
           apreq_table_entry_t *elt = table_push(t);
  -        int *root = &t->root[TABLE_HASH(key)];
  +        int *root = &t->root[TABLE_HASH(*key)];
           apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
   
  -        elt->key = val->name;
  +        elt->key = key;
           elt->val = val;
           elt->tree[NEXT] = -1;
  +        COMPUTE_KEY_CHECKSUM(elt->key,elt->checksum);
           insert(o, root, *root, elt, t->flags);
           return APR_SUCCESS;
       }
  @@ -985,6 +1025,12 @@
       const int n = t->a.nelts;
       int idx;
       apreq_table_entry_t *o;
  +    if (t->ghosts == n) {
  +        t->a.nelts == 0;
  +        t->ghosts = s->ghosts;
  +        apr_array_cat(&t->a,&s->a);
  +        return;
  +    }
   
       apr_array_cat(&t->a, &s->a);
       o = (apreq_table_entry_t *)t->a.elts;
  @@ -992,7 +1038,7 @@
   
       if (t->flags & TF_BALANCE) {
           for (idx = n; idx < t->a.nelts; ++idx) {
  -            const unsigned char hash = TABLE_HASH(idx[o].key);
  +            const unsigned char hash = TABLE_HASH(idx[o].checksum>>24);
   
               if (DEAD(idx))
                   continue;
  @@ -1194,7 +1240,8 @@
    * Sigh.  --JCW, 06/28/02
    */
   APREQ_DECLARE(int) apreq_table_vdo(apr_table_do_callback_fn_t *comp,
  -                                 void *rec, const apreq_table_t *t, va_list 
vp)
  +                                   void *rec, const apreq_table_t *t, 
  +                                   va_list vp)
   {
       char *argp;
       apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  @@ -1204,7 +1251,7 @@
       do {
           int rv = 1, idx;
           if (argp) {     /* Scan for entries that match the next key */
  -            idx = t->root[TABLE_HASH(argp)];
  +            idx = t->root[TABLE_HASH(*argp)];
               if ( search(o,&idx,argp) == 0 )
                   while (idx >= 0) {
                       rv = (*comp) (rec, idx[o].key, v2c(idx[o].val));
  
  
  
  1.15      +2 -2      httpd-apreq-2/src/apreq_tables.h
  
  Index: apreq_tables.h
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_tables.h,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- apreq_tables.h    26 Apr 2003 20:55:34 -0000      1.14
  +++ apreq_tables.h    29 Apr 2003 03:35:55 -0000      1.15
  @@ -433,8 +433,8 @@
    * @see apreq_table_do_callback_fn_t
    */
   APREQ_DECLARE(int) apreq_table_vdo(apreq_table_do_callback_fn_t *comp,
  -                                   void *ctx,
  -                                   const apreq_table_t *t, va_list);
  +                                   void *ctx, const apreq_table_t *t, 
  +                                   va_list vp);
   
   
   
  
  
  

Reply via email to