subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
Subject svn commit: r1666965 - /subversion/trunk/subversion/mod_dav_svn/reports/log.c
Date Mon, 16 Mar 2015 11:30:05 GMT
Author: rhuijben
Date: Mon Mar 16 11:30:04 2015
New Revision: 1666965

Reduce the perceived very slow operation of svn log URL via mod_dav on
large result sets that return not that much data, by flushing the
httpd output cache a few times for the 'first few log results'.

Usually httpd tries to produce data 8 KByte at a time, but depending on
the type of log request this may be every few hundred revisions and
in not that uncommon cases on only after 5-30 seconds.
This patch explicitly flushes the caching after 1,2,4,8,16,...2048
results, so the log handling will appear to be streamy as expected,
while it falls back to the original handling when retrieving very
many/all revisions.

In theory this makes the log report a bit slower, because flushes cost
a bit performance... but in general you (and some operations like
'svn merge') just want the first result (or first few results) as fast
as possible. (And in many cases ^C or SVN_ERR_CEASE_INVOCATION, the
remaining results).

This patch should reduce the initial delay before the first result of:
$ svn log ^/subversion/branches/1.8.x -q
which is currently about 10 seconds for me, to less than a second.

See the '1.9.x JavaHL: long initial delay when performing a log' thread
for an even worse example.

This minor fix migh just fix one of the reasons why many users call
Subversion slow, and prefer a local repository.

* subversion/mod_dav_svn/reports/log.c
  (log_receiver_baton): Add two variables.
  (log_receiver): Add explicit flush code on every 2^x for x 0..11 revisions.
  (dav_svn__log_report): Update baton init.


Modified: subversion/trunk/subversion/mod_dav_svn/reports/log.c
--- subversion/trunk/subversion/mod_dav_svn/reports/log.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/log.c Mon Mar 16 11:30:04 2015
@@ -65,6 +65,10 @@ struct log_receiver_baton
   /* whether the client can handle encoded binary property values */
   svn_boolean_t encode_binary_props;
+  /* Helper variables to force early bucket brigade flushes */
+  int result_count;
+  int next_forced_flush;
@@ -282,6 +286,33 @@ log_receiver(void *baton,
   SVN_ERR(dav_svn__brigade_puts(lrb->bb, lrb->output,
                                 "</S:log-item>" DEBUG_CR));
+  /* In general APR will flush the bucket every 8 KByte, but log items
+     may not be generated that fast, especially in combination with authz
+     and busy servers. This algorithm makes sure the client gets the first
+     two results very fast (but less efficient), while it gradually removes
+     its performance hit and falls back to the APR standard buffer handling,
+     which streamlines the http processing */
+  lrb->result_count++;
+  if (lrb->result_count == lrb->next_forced_flush)
+    {
+      apr_off_t len = 0;
+      (void)apr_brigade_length(lrb->bb, FALSE, &len);
+      if (len != 0)
+        {
+          apr_status_t apr_err = ap_fflush(lrb->output, lrb->bb);
+          if (apr_err)
+            return svn_error_create(apr_err, NULL, NULL);
+          if (lrb->output->c->aborted)
+            return svn_error_create(SVN_ERR_APMOD_CONNECTION_ABORTED,
+                                    NULL, NULL);
+        }
+      if (lrb->result_count < 2048)
+        lrb->next_forced_flush = lrb->next_forced_flush * 2;
+    }
   return SVN_NO_ERROR;
@@ -427,6 +458,9 @@ dav_svn__log_report(const dav_resource *
   lrb.stack_depth = 0;
   /* lrb.requested_custom_revprops set above */
+  lrb.result_count = 0;
+  lrb.next_forced_flush = 1;
   /* Our svn_log_entry_receiver_t sends the <S:log-report> header in
      a lazy fashion.  Before writing the first log message, it assures
      that the header has already been sent (checking the needs_header

View raw message