Author: stefan2
Date: Sun Feb  8 16:47:33 2015
New Revision: 1658205

URL: http://svn.apache.org/r1658205
Log:
Squeeze a few more percent efficiency from ra_svn protocol parser.
As it turns out, some reports like 'svn diff --summary' have a high
density of command words. Parse them efficiently.

* subversion/libsvn_ra_svn/marshal.c
  (MAX_WORD_LENGTH): Pick a slightly smaller, carefully selected value
                     that will fit with the updated logic in ...
  (read_item): ... here. Add a fast parser path for "word" tokens.

Modified:
    subversion/branches/ra-svn-tuning/subversion/libsvn_ra_svn/marshal.c

Modified: subversion/branches/ra-svn-tuning/subversion/libsvn_ra_svn/marshal.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/ra-svn-tuning/subversion/libsvn_ra_svn/marshal.c?rev=1658205&r1=1658204&r2=1658205&view=diff
==============================================================================
--- subversion/branches/ra-svn-tuning/subversion/libsvn_ra_svn/marshal.c 
(original)
+++ subversion/branches/ra-svn-tuning/subversion/libsvn_ra_svn/marshal.c Sun 
Feb  8 16:47:33 2015
@@ -60,9 +60,10 @@
 
 /* We don't use "words" longer than this in our protocol.  The longest word
  * we are currently using is only about 16 chars long but we leave room for
- * longer future capability and command names.
+ * longer future capability and command names.  See read_item() to understand
+ * why MAX_WORD_LENGTH - 1 should be a multiple of 8.
  */
-#define MAX_WORD_LENGTH 31
+#define MAX_WORD_LENGTH 25
 
 /* The generic parsers will use the following value to limit the recursion
  * depth to some reasonable value.  The current protocol implementation
@@ -1060,17 +1061,40 @@ static svn_error_t *read_item(svn_ra_svn
       char *p = buffer + 1;
 
       buffer[0] = c;
-      while (1)
+      if (conn->read_ptr + MAX_WORD_LENGTH <= conn->read_end)
         {
-          SVN_ERR(readbuf_getchar(conn, pool, p));
-          if (!svn_ctype_isalnum(*p) && *p != '-')
-            break;
+          /* Fast path: we can simply take a chunk from the read
+           * buffer and inspect it with no overflow checks etc.
+           *
+           * Copying these 24 bytes unconditionally is also faster
+           * than a variable-sized memcpy.  Note that P is at BUFFER[1].
+           */
+          memcpy(p, conn->read_ptr, MAX_WORD_LENGTH - 1);
+          *end = 0;
+
+          /* This will terminate at P == END because of *END == NUL. */
+          while (svn_ctype_isalnum(*p) || *p == '-')
+            ++p;
 
-          if (++p == end)
-            return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
-                                    _("Word is too long"));
+          /* Only now do we mark data as actually read. */
+          conn->read_ptr += p - buffer;
+        }
+      else
+        {
+          /* Slow path. Byte-by-byte copying and checking for
+           * input and output buffer boundaries. */
+          for (p = buffer + 1; p != end; ++p)
+            {
+              SVN_ERR(readbuf_getchar(conn, pool, p));
+              if (!svn_ctype_isalnum(*p) && *p != '-')
+                break;
+            }
         }
 
+      if (p == end)
+        return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+                                _("Word is too long"));
+
       c = *p;
       *p = '\0';
 


Reply via email to