[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[RFC] : full-text instead of vdelta against empty bytestream

From: David Kimdon <dwhedon_at_debian.org>
Date: 2003-10-20 00:55:22 CEST

Hi,

The included patch removes vdelta calculation when we are sending the
full text of the target. I'm still not sure of the over-all benefit
of this and stat_tests.py 10 is failing, not sure why yet. There is
definately a dramitic CPU-time savings wherever the vdelta no longer
needs to be calculated, but we aren't always CPU-bound. I left some
data and the script I used to create it up at
http://people.debian.org/~dwhedon/svn-tests/ for those who are
curious.

Comments and critisism welcome,

-David

--------------------------------------------

For assorted operations don't create a vdelta against an empty byte stream.
Instead, send the full text directly to the consumer. Note that this doesn't
require any changes on the consumer side and as such doesn't introduce any
client-server incompatibilities.

* subversion/libsvn_delta/text_delta.c
  (send_string) : New function. This function does most of what
  svn_txdelta_send_string() needs to do with the notable exception of sending
  the final NULL to the window handler.
  (svn_txdelta_send_string) : Use a new helper function send_string to do most
  of the work and then send the final NULL to the window handler.
  (svn_txdelta_send_stream) : Rather than creating a diff against an empty
  byte stream send the stream directly to the handler as new data for
  the target.
* subversion/libsvn_repos/delta.c
  (delta_files) : If there is no source file send the target full-text using
  svn_txdelta_send_stream().

Index: subversion/libsvn_repos/delta.c
===================================================================
--- subversion/libsvn_repos/delta.c (revision 7448)
+++ subversion/libsvn_repos/delta.c (working copy)
@@ -583,26 +583,48 @@
 
       if (c->text_deltas)
         {
- /* Get a delta stream turning an empty file into one having
- TARGET_PATH's contents. */
- SVN_ERR (svn_fs_get_file_delta_stream
- (&delta_stream,
- source_path ? c->source_root : NULL,
- source_path ? source_path : NULL,
- c->target_root, target_path, subpool));
- }
+ if (source_path)
+ {
+ /* Get a delta stream that turns SOURCE_PATH into a file with
+ TARGET_PATH's contents. */
+ SVN_ERR (svn_fs_get_file_delta_stream
+ (&delta_stream,
+ source_path ? c->source_root : NULL,
+ source_path ? source_path : NULL,
+ c->target_root, target_path, subpool));
+
+ SVN_ERR (svn_fs_file_md5_checksum
+ (source_digest, c->source_root, source_path, subpool));
 
- if (source_path)
- {
- SVN_ERR (svn_fs_file_md5_checksum
- (source_digest, c->source_root, source_path, subpool));
+ source_hex_digest = svn_md5_digest_to_cstring (source_digest,
+ subpool);
+
+ SVN_ERR (send_text_delta (c, file_baton, source_hex_digest,
+ delta_stream, subpool));
+ }
+ else
+ {
+ /* Send TARGET_PATH full-text, no delta needed. */
+ svn_stream_t *stream;
+ svn_txdelta_window_handler_t delta_handler;
+ void *delta_handler_baton;
+
+ /* XXX -This handler will understand when we send it full-text,
+ * the apply_textdelta name is a bit misleading. */
+ SVN_ERR (c->editor->apply_textdelta
+ (file_baton, NULL, subpool,
+ &delta_handler, &delta_handler_baton));
+
+ SVN_ERR (svn_fs_file_contents (&stream, c->target_root,
+ target_path, subpool));
 
- source_hex_digest = svn_md5_digest_to_cstring (source_digest,
- subpool);
+ SVN_ERR(svn_txdelta_send_stream (stream,
+ delta_handler,
+ delta_handler_baton,
+ NULL,
+ subpool));
+ }
         }
-
- SVN_ERR (send_text_delta (c, file_baton, source_hex_digest,
- delta_stream, subpool));
     }
 
   /* Cleanup. */
Index: subversion/libsvn_delta/text_delta.c
===================================================================
--- subversion/libsvn_delta/text_delta.c (revision 7448)
+++ subversion/libsvn_delta/text_delta.c (working copy)
@@ -522,11 +522,11 @@
 
 /* Convenience routines */
 
-svn_error_t *
-svn_txdelta_send_string (const svn_string_t *string,
- svn_txdelta_window_handler_t handler,
- void *handler_baton,
- apr_pool_t *pool)
+
+static svn_error_t *
+send_string (const svn_string_t *string,
+ svn_txdelta_window_handler_t handler,
+ void *handler_baton)
 {
   svn_txdelta_window_t window = { 0 };
   svn_txdelta_op_t op;
@@ -545,6 +545,18 @@
   /* Push the one window at the handler. */
   SVN_ERR ((*handler) (&window, handler_baton));
   
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_txdelta_send_string (const svn_string_t *string,
+ svn_txdelta_window_handler_t handler,
+ void *handler_baton,
+ apr_pool_t *pool)
+{
+ SVN_ERR (send_string (string, handler, handler_baton));
+
   /* Push a NULL at the handler, because we're done. */
   SVN_ERR ((*handler) (NULL, handler_baton));
   
@@ -557,29 +569,41 @@
                                       unsigned char *digest,
                                       apr_pool_t *pool)
 {
- svn_txdelta_stream_t *txstream;
- svn_error_t *err;
+ apr_size_t len = SVN_STREAM_CHUNK_SIZE;
+ apr_md5_ctx_t context;
+ svn_string_t string;
+ char *buf;
+
+ if (digest)
+ apr_md5_init (&context);
+
+ buf = apr_palloc (pool, SVN_STREAM_CHUNK_SIZE);
+ string.data = buf;
+
+ len = SVN_STREAM_CHUNK_SIZE;
+ SVN_ERR (svn_stream_read (stream, buf, &len));
 
- /* ### this is a hack. we should simply read from the stream, construct
- ### some windows, and pass those to the handler. there isn't any reason
- ### to crank up a full "diff" algorithm just to copy a stream.
- ###
- ### will fix RSN. */
-
- /* Create a delta stream which converts an *empty* bytestream into the
- target bytestream. */
- svn_txdelta (&txstream, svn_stream_empty (pool), stream, pool);
- err = svn_txdelta_send_txstream (txstream, handler, handler_baton, pool);
-
- if (digest && (! err))
+ while (len)
     {
- const unsigned char *result_md5;
- result_md5 = svn_txdelta_md5_digest (txstream);
- /* Since err is null, result_md5 "cannot" be null. */
- memcpy (digest, result_md5, MD5_DIGESTSIZE);
+ if (digest)
+ apr_md5_update (&context, buf, len);
+
+ string.len = len;
+
+ SVN_ERR (send_string (&string, handler, handler_baton));
+
+ len = SVN_STREAM_CHUNK_SIZE;
+
+ SVN_ERR (svn_stream_read (stream, buf, &len));
     }
 
- return err;
+ if (digest)
+ apr_md5_final (digest, &context);
+
+ /* Push a NULL at the handler, because we're done. */
+ SVN_ERR ((*handler) (NULL, handler_baton));
+
+ return SVN_NO_ERROR;
 }
 
 svn_error_t *svn_txdelta_send_txstream (svn_txdelta_stream_t *txstream,

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Mon Oct 20 02:06:28 2003

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.