Author: rhuijben
Date: Sun Nov 29 11:43:45 2015
New Revision: 1717039

URL: http://svn.apache.org/viewvc?rev=1717039&view=rev
Log:
With the Subversion test suite now completely running over HTTP/2, improve
the final step of hpack (header) encoding: dynamic table compression.

* buckets/hpack_buckets.c
  (serf_hpack_table_t): Remove unused nr of item variables.
  (serialize_ensure_buffer): New function.
  (serialize): Improve buffer usage by calling serialize_ensure_buffer
    in a few places instead of allocating to much up front. Store indexable
    entries in the table's local to remote list after writing.

Modified:
    serf/trunk/buckets/hpack_buckets.c

Modified: serf/trunk/buckets/hpack_buckets.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/buckets/hpack_buckets.c?rev=1717039&r1=1717038&r2=1717039&view=diff
==============================================================================
--- serf/trunk/buckets/hpack_buckets.c (original)
+++ serf/trunk/buckets/hpack_buckets.c Sun Nov 29 11:43:45 2015
@@ -290,13 +290,11 @@ struct serf_hpack_table_t
 
     /* The local -> remote 'encoder' list */
     serf_hpack_entry_t *lr_first, *lr_last;
-    unsigned int lr_count; /* Number of items */
     apr_size_t lr_size; /* 'Bytes' in list, calculated by HPACK_ENTRY_SIZE() */
     apr_size_t lr_max_table_size;
     apr_size_t lr_sys_table_size;
 
     serf_hpack_entry_t *rl_first, *rl_last;
-    unsigned int rl_count; /* Number of items */
     apr_size_t rl_size; /* 'Bytes' in list, calculated by HPACK_ENTRY_SIZE() */
     apr_size_t rl_max_table_size;
     apr_size_t rl_sys_table_size;
@@ -810,6 +808,28 @@ static void hpack_int(unsigned char flag
     *used = u;
 }
 
+static void
+serialize_ensure_buffer(serf_bucket_t *bucket, apr_size_t ensure,
+                        char **buffer, apr_size_t *offset)
+{
+    const apr_size_t chunksize = 1024;
+
+    if (*buffer && ((*offset + ensure) < chunksize))
+        return;
+
+    if (*buffer) {
+        serf_bucket_aggregate_append(
+            bucket,
+            serf_bucket_simple_own_create(*buffer, *offset, 
bucket->allocator));
+
+        *buffer = NULL;
+    }
+    *offset = 0;
+
+    *buffer = serf_bucket_mem_alloc(bucket->allocator, chunksize);
+    *offset = 0;
+}
+
 static apr_status_t
 serialize(serf_bucket_t *bucket)
 {
@@ -822,7 +842,6 @@ serialize(serf_bucket_t *bucket)
 
     char *buffer = NULL;
     apr_size_t offset = 0;
-    const apr_size_t chunksize = 2048; /* Wild guess */
 
     /* Put on our aggregate bucket cloak */
     serf_bucket_aggregate_become(bucket);
@@ -832,7 +851,7 @@ serialize(serf_bucket_t *bucket)
     {
         apr_size_t len;
 
-        buffer = serf_bucket_mem_alloc(alloc, chunksize);
+        serialize_ensure_buffer(bucket, 8, &buffer, &offset);
 
         hpack_int(0x20, 5, tbl->lr_max_table_size, buffer + offset, &len);
         offset += len;
@@ -850,23 +869,7 @@ serialize(serf_bucket_t *bucket)
 
         next = entry->next;
 
-        /* Make 100% sure the next entry will fit.
-           ### Using the actual size later on is far more memory efficient
-         */
-        if (!buffer || (HPACK_ENTRY_SIZE(entry) > chunksize - offset))
-        {
-            if (offset)
-            {
-                serf_bucket_aggregate_append(
-                    bucket,
-                    serf_bucket_simple_own_create(buffer, offset, alloc));
-            }
-
-            buffer = serf_bucket_mem_alloc(alloc,
-                                           MAX(chunksize,
-                                               HPACK_ENTRY_SIZE(entry)));
-            offset = 0;
-        }
+        serialize_ensure_buffer(bucket, 16, &buffer, &offset);
 
         for (i = 0; i < hpack_static_table_count; i++) {
             e = &hpack_static_table[i];
@@ -938,6 +941,8 @@ serialize(serf_bucket_t *bucket)
                 apr_size_t int_len;
 
                 /* It is more efficient to huffman encode */
+                serialize_ensure_buffer(bucket, 8 + len, &buffer, &offset);
+
                 hpack_int(0x80, 7, len, buffer + offset, &int_len);
                 offset += int_len;
 
@@ -952,7 +957,10 @@ serialize(serf_bucket_t *bucket)
             }
             else
             {
-              /* It is more efficient not to encode */
+                /* It is more efficient not to encode */
+                serialize_ensure_buffer(bucket, 8 + entry->key_len,
+                                        &buffer, &offset);
+
                 hpack_int(0x00, 7, entry->key_len, buffer + offset, &len);
                 offset += len;
 
@@ -970,6 +978,7 @@ serialize(serf_bucket_t *bucket)
                 apr_size_t int_len;
 
                 /* It is more efficient to huffman encode */
+                serialize_ensure_buffer(bucket, 8 + len, &buffer, &offset);
                 hpack_int(0x80, 7, len, buffer + offset, &int_len);
                 offset += int_len;
 
@@ -985,7 +994,9 @@ serialize(serf_bucket_t *bucket)
             }
             else
             {
-              /* It is more efficient not to encode */
+                /* It is more efficient not to encode */
+                serialize_ensure_buffer(bucket, 8 + entry->value_len,
+                                        &buffer, &offset);
                 hpack_int(0x00, 7, entry->value_len, buffer + offset, &len);
                 offset += len;
 
@@ -994,9 +1005,36 @@ serialize(serf_bucket_t *bucket)
             }
         }
 
-        /* ### TODO: Store the item in the lr dynamic table if we are allowed
-                     to do that. We currently 'forget' that step, so we only
-                     use pre-cached values */
+        /* If we didn't re-use key+value and we are allowed to index the
+           item, let's do that. Note that we already told the other side that
+           we did this, as that side has to keep its table in sync */
+        if (!reuseVal && !entry->dont_index) {
+            serf_hpack_entry_t *tbl_entry;
+
+            tbl_entry = serf_bucket_mem_calloc(tbl->alloc, sizeof(*tbl_entry));
+
+            tbl_entry->key = serf_bstrmemdup(tbl->alloc,
+                                             entry->key, entry->key_len);
+            tbl_entry->key_len = entry->key_len;
+            tbl_entry->value = serf_bstrmemdup(tbl->alloc,
+                                               entry->value, entry->value_len);
+            tbl_entry->value_len = entry->value_len;
+            tbl_entry->free_key = entry->free_val = true;
+
+            tbl_entry->next = tbl->lr_first;
+            tbl->lr_first = tbl_entry;
+            tbl->lr_size += HPACK_ENTRY_SIZE(tbl_entry);
+            if (tbl_entry->next)
+                tbl_entry->next->prev = tbl_entry;
+            else
+                tbl->rl_last = tbl_entry;
+
+            if (tbl->lr_size > tbl->rl_max_table_size) {
+                hpack_shrink_table(&tbl->lr_first,
+                                   &tbl->lr_last, &tbl->lr_size,
+                                   tbl->lr_max_table_size, tbl->alloc);
+            }
+        }
 
         /* And now free the item */
         hpack_free_entry(entry, alloc);
@@ -1460,14 +1498,11 @@ handle_read_entry_and_clear(serf_hpack_d
         entry->free_key = entry->free_val = true;
         entry->next = tbl->rl_first;
         tbl->rl_first = entry;
-        tbl->rl_count++;
         tbl->rl_size += HPACK_ENTRY_SIZE(entry);
         if (entry->next)
             entry->next->prev = entry;
         else
             tbl->rl_last = entry;
-
-          /* We don't update lr_start... that is the idea */
     }
     else
     {


Reply via email to