Author: rhuijben
Date: Fri Oct 30 14:10:07 2015
New Revision: 1711483

URL: http://svn.apache.org/viewvc?rev=1711483&view=rev
Log:
Avoid an unneeded copy in the http2 unframe buckets in the very likely
case that we read the header as one buffer. This makes the code more
similar to the prefix bucket added in r1711471.

* buckets/http2_frame_buckets.c
  (http2_unframe_context_t): Rename buffer variable.
  (serf__bucket_http2_unframe_create): Update user.
  (serf__bucket_http2_unframe_read_info): Avoid copy in > 99% of the cases.
    Fill output arguments directly to improve inlining which may find
    bucket->data->... in both calls hard to understand.

Modified:
    serf/trunk/buckets/http2_frame_buckets.c

Modified: serf/trunk/buckets/http2_frame_buckets.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/buckets/http2_frame_buckets.c?rev=1711483&r1=1711482&r2=1711483&view=diff
==============================================================================
--- serf/trunk/buckets/http2_frame_buckets.c (original)
+++ serf/trunk/buckets/http2_frame_buckets.c Fri Oct 30 14:10:07 2015
@@ -48,7 +48,7 @@ typedef struct http2_unframe_context_t
   unsigned char frame_type;
   unsigned char flags;
 
-  unsigned char prefix_buffer[FRAME_PREFIX_SIZE];
+  unsigned char buffer[FRAME_PREFIX_SIZE];
   char destroy_stream;
 } http2_unframe_context_t;
 
@@ -63,7 +63,7 @@ serf__bucket_http2_unframe_create(serf_b
   ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
   ctx->stream = stream;
   ctx->max_payload_size = max_payload_size;
-  ctx->prefix_remaining = sizeof(ctx->prefix_buffer);
+  ctx->prefix_remaining = sizeof(ctx->buffer);
   ctx->eof_callback = NULL;
 
   ctx->destroy_stream = (destroy_stream != 0);
@@ -110,29 +110,44 @@ serf__bucket_http2_unframe_read_info(ser
   status = serf_bucket_read(ctx->stream, ctx->prefix_remaining, &data, &len);
   if (! SERF_BUCKET_READ_ERROR(status))
     {
-      memcpy(ctx->prefix_buffer + FRAME_PREFIX_SIZE - ctx->prefix_remaining,
-             data, len);
+      const unsigned char *header;
 
-      ctx->prefix_remaining -= len;
+      if (len < FRAME_PREFIX_SIZE)
+        {
+          memcpy(ctx->buffer + FRAME_PREFIX_SIZE - ctx->prefix_remaining,
+                 data, len);
+
+          ctx->prefix_remaining -= len;
+          header = ctx->buffer;
+        }
+      else
+        {
+          header = (const void *)data;
+          ctx->prefix_remaining = 0;
+        }
 
       if (ctx->prefix_remaining == 0)
         {
-          apr_size_t payload_length = (ctx->prefix_buffer[0] << 16)
-                                    | (ctx->prefix_buffer[1] << 8)
-                                    | (ctx->prefix_buffer[2]);
-          ctx->frame_type = ctx->prefix_buffer[3];
-          ctx->flags = ctx->prefix_buffer[4];
+          apr_size_t payload_length = (header[0] << 16)
+                                    | (header[1] << 8)
+                                    | (header[2]);
+          ctx->frame_type = header[3];
+          ctx->flags = header[4];
           /* Highest bit of stream_id MUST be ignored */
-          ctx->stream_id = ((ctx->prefix_buffer[5] & 0x7F) << 24)
-                           | (ctx->prefix_buffer[6] << 16)
-                           | (ctx->prefix_buffer[7] << 8)
-                           | (ctx->prefix_buffer[8]);
+          ctx->stream_id = ((header[5] & 0x7F) << 24)
+                           | (header[6] << 16)
+                           | (header[7] << 8)
+                           | (header[8]);
 
           ctx->payload_remaining = payload_length;
 
-          /* Use recursion to fill output arguments if necessary */
-          serf__bucket_http2_unframe_read_info(bucket, stream_id, frame_type,
-                                               flags);
+          /* Fill output arguments if necessary */
+          if (stream_id)
+            *stream_id = ctx->stream_id;
+          if (frame_type)
+            *frame_type = ctx->frame_type;
+          if (flags)
+            *flags = ctx->flags;
 
           /* https://tools.ietf.org/html/rfc7540#section-4.2
             An endpoint MUST send an error code of FRAME_SIZE_ERROR if a frame


Reply via email to