You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by jc...@apache.org on 2011/01/19 00:54:36 UTC

svn commit: r1060625 - /subversion/branches/diff-optimizations-bytes/subversion/libsvn_diff/diff_file.c

Author: jcorvel
Date: Tue Jan 18 23:54:36 2011
New Revision: 1060625

URL: http://svn.apache.org/viewvc?rev=1060625&view=rev
Log:
On the diff-optimizations-bytes branch:

As a further optimization of prefix/suffix scanning, allocate the file[]
array on the stack instead of the heap (all members become directly
addressable through the stack pointer because all static sub-functions will
actually be in-lined).

* subversion/libsvn_diff/diff_file.c
  (INCREMENT_POINTERS, DECREMENT_POINTERS): Handle all_files as an array of
   file_info structs, instead of an array of pointers to those structs. But,
   pass a pointer to the file_info to increment_chunk and decrement_chunk.
  (is_one_at_bof, is_one_at_eof, find_identical_prefix,
   find_identical_suffix): Make the file[] argument an array of file_info
   structs, instead of an array of pointers to those structs.
  (datasources_open): Allocate the files[] on the stack, and pass them like
   that to the underlying functions. After all underlying functions did their
   work, copy the files back to the file_baton.

Patch by: stefan2

Modified:
    subversion/branches/diff-optimizations-bytes/subversion/libsvn_diff/diff_file.c

Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_diff/diff_file.c?rev=1060625&r1=1060624&r2=1060625&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_diff/diff_file.c Tue Jan 18 23:54:36 2011
@@ -259,10 +259,10 @@ datasource_open(void *baton, svn_diff_da
                                                                              \
     for (svn_macro__i = 0; svn_macro__i < (files_len); svn_macro__i++)       \
     {                                                                        \
-      if ((all_files)[svn_macro__i]->curp < (all_files)[svn_macro__i]->endp - 1) \
-        (all_files)[svn_macro__i]->curp++;                                   \
+      if ((all_files)[svn_macro__i].curp < (all_files)[svn_macro__i].endp - 1)\
+        (all_files)[svn_macro__i].curp++;                                    \
       else                                                                   \
-        SVN_ERR(increment_chunk((all_files)[svn_macro__i], (pool)));         \
+        SVN_ERR(increment_chunk(&(all_files)[svn_macro__i], (pool)));        \
     }                                                                        \
   } while (0)
 
@@ -277,10 +277,10 @@ datasource_open(void *baton, svn_diff_da
                                                                              \
     for (svn_macro__i = 0; svn_macro__i < (files_len); svn_macro__i++)       \
     {                                                                        \
-      if ((all_files)[svn_macro__i]->curp > (all_files)[svn_macro__i]->buffer) \
-        (all_files)[svn_macro__i]->curp--;                                   \
+      if ((all_files)[svn_macro__i].curp > (all_files)[svn_macro__i].buffer) \
+        (all_files)[svn_macro__i].curp--;                                    \
       else                                                                   \
-        SVN_ERR(decrement_chunk((all_files)[svn_macro__i], (pool)));         \
+        SVN_ERR(decrement_chunk(&(all_files)[svn_macro__i], (pool)));        \
     }                                                                        \
   } while (0)
 
@@ -350,12 +350,12 @@ decrement_chunk(struct file_info *file, 
  * the file (this can happen while scanning backwards). This is the case if
  * one of them has chunk == -1. */
 static svn_boolean_t
-is_one_at_bof(struct file_info *file[], apr_size_t file_len)
+is_one_at_bof(struct file_info file[], apr_size_t file_len)
 {
   apr_size_t i;
 
   for (i = 0; i < file_len; i++)
-    if (file[i]->chunk == -1)
+    if (file[i].chunk == -1)
       return TRUE;
 
   return FALSE;
@@ -364,12 +364,12 @@ is_one_at_bof(struct file_info *file[], 
 /* Check whether one of the FILEs has its pointers at EOF (this is the case if
  * one of them has curp == endp (this can only happen at the last chunk)) */
 static svn_boolean_t
-is_one_at_eof(struct file_info *file[], apr_size_t file_len)
+is_one_at_eof(struct file_info file[], apr_size_t file_len)
 {
   apr_size_t i;
 
   for (i = 0; i < file_len; i++)
-    if (file[i]->curp == file[i]->endp)
+    if (file[i].curp == file[i].endp)
       return TRUE;
 
   return FALSE;
@@ -385,7 +385,7 @@ is_one_at_eof(struct file_info *file[], 
  * of the FILEs are set to point at the first byte after the prefix. */
 static svn_error_t *
 find_identical_prefix(svn_boolean_t *reached_one_eof, apr_off_t *prefix_lines,
-                      struct file_info *file[], apr_size_t file_len,
+                      struct file_info file[], apr_size_t file_len,
                       apr_pool_t *pool)
 {
   svn_boolean_t had_cr = FALSE;
@@ -394,21 +394,20 @@ find_identical_prefix(svn_boolean_t *rea
 
   *prefix_lines = 0;
   for (i = 1, is_match = TRUE; i < file_len; i++)
-    is_match = is_match && *file[0]->curp == *file[i]->curp;
+    is_match = is_match && *file[0].curp == *file[i].curp;
   while (is_match)
     {
       /* ### TODO: see if we can take advantage of 
          diff options like ignore_eol_style or ignore_space. */
       /* check for eol, and count */
-      if (*file[0]->curp == '\r')
+      if (*file[0].curp == '\r')
         {
           (*prefix_lines)++;
           had_cr = TRUE;
         }
-      else if (*file[0]->curp == '\n' && !had_cr)
+      else if (*file[0].curp == '\n' && !had_cr)
         {
           (*prefix_lines)++;
-          had_cr = FALSE;
         }
       else 
         {
@@ -423,7 +422,7 @@ find_identical_prefix(svn_boolean_t *rea
         break;
       else
         for (i = 1, is_match = TRUE; i < file_len; i++)
-          is_match = is_match && *file[0]->curp == *file[i]->curp;
+          is_match = is_match && *file[0].curp == *file[i].curp;
     }
 
   if (had_cr)
@@ -435,7 +434,7 @@ find_identical_prefix(svn_boolean_t *rea
       svn_boolean_t ended_at_nonmatching_newline = FALSE;
       for (i = 0; i < file_len; i++)
         ended_at_nonmatching_newline = ended_at_nonmatching_newline 
-                                       || *file[i]->curp == '\n';
+                                       || *file[i].curp == '\n';
       if (ended_at_nonmatching_newline)
         {
           (*prefix_lines)--;
@@ -448,7 +447,7 @@ find_identical_prefix(svn_boolean_t *rea
 
   /* Back up to the last eol sequence (\n, \r\n or \r) */
   while (!is_one_at_bof(file, file_len) && 
-         *file[0]->curp != '\n' && *file[0]->curp != '\r')
+         *file[0].curp != '\n' && *file[0].curp != '\r')
     DECREMENT_POINTERS(file, file_len, pool);
 
   /* Slide one byte forward, to point past the eol sequence */
@@ -467,11 +466,10 @@ find_identical_prefix(svn_boolean_t *rea
  * find_identical_prefix), so we can determine where suffix scanning should 
  * ultimately stop. */
 static svn_error_t *
-find_identical_suffix(struct file_info *file[], apr_size_t file_len,
+find_identical_suffix(struct file_info file[], apr_size_t file_len,
                       apr_pool_t *pool)
 {
   struct file_info file_for_suffix[4];
-  struct file_info *file_for_suffix_ptr[4];
   apr_off_t length[4];
   apr_off_t suffix_min_chunk0;
   apr_off_t suffix_min_offset0;
@@ -480,26 +478,22 @@ find_identical_suffix(struct file_info *
   svn_boolean_t is_match, reached_prefix;
   apr_size_t i;
 
-  for (i = 0; i < file_len; i++)
-    {
-      memset(&file_for_suffix[i], 0, sizeof(file_for_suffix[i]));
-      file_for_suffix_ptr[i] = &file_for_suffix[i];
-    }
+  memset(file_for_suffix, 0, sizeof(file_for_suffix));
 
   /* Initialize file_for_suffix[].
      Read last chunk, position curp at last byte. */
   for (i = 0; i < file_len; i++)
     {
-      file_for_suffix[i].path = file[i]->path;
-      file_for_suffix[i].file = file[i]->file;
-      file_for_suffix[i].size = file[i]->size;
+      file_for_suffix[i].path = file[i].path;
+      file_for_suffix[i].file = file[i].file;
+      file_for_suffix[i].size = file[i].size;
       file_for_suffix[i].chunk =
         (int) offset_to_chunk(file_for_suffix[i].size); /* last chunk */
       length[i] = offset_in_chunk(file_for_suffix[i].size);
-      if (file_for_suffix[i].chunk == file[i]->chunk)
+      if (file_for_suffix[i].chunk == file[i].chunk)
         {
           /* Prefix ended in last chunk, so we can reuse the prefix buffer */
-          file_for_suffix[i].buffer = file[i]->buffer;
+          file_for_suffix[i].buffer = file[i].buffer;
         }
       else
         {
@@ -517,17 +511,17 @@ find_identical_suffix(struct file_info *
 
   /* Get the chunk and pointer offset (for file[0]) at which we should stop
      scanning backward for the identical suffix, i.e. when we reach prefix. */
-  suffix_min_chunk0 = file[0]->chunk;
-  suffix_min_offset0 = file[0]->curp - file[0]->buffer;
+  suffix_min_chunk0 = file[0].chunk;
+  suffix_min_offset0 = file[0].curp - file[0].buffer;
 
   /* Compensate if other files are smaller than file[0] */
-  for (i = 1, min_file_size = file[0]->size; i < file_len; i++)
-    if (file[i]->size < min_file_size)
-      min_file_size = file[i]->size;
-  if (file[0]->size > min_file_size)
+  for (i = 1, min_file_size = file[0].size; i < file_len; i++)
+    if (file[i].size < min_file_size)
+      min_file_size = file[i].size;
+  if (file[0].size > min_file_size)
     {
-      suffix_min_chunk0 += (file[0]->size - min_file_size) / CHUNK_SIZE;
-      suffix_min_offset0 += (file[0]->size - min_file_size) % CHUNK_SIZE;
+      suffix_min_chunk0 += (file[0].size - min_file_size) / CHUNK_SIZE;
+      suffix_min_offset0 += (file[0].size - min_file_size) % CHUNK_SIZE;
     }
 
   /* Scan backwards until mismatch or until we reach the prefix. */
@@ -536,13 +530,13 @@ find_identical_suffix(struct file_info *
       is_match && *file_for_suffix[0].curp == *file_for_suffix[i].curp;
   while (is_match)
     {
-      DECREMENT_POINTERS(file_for_suffix_ptr, file_len, pool);
+      DECREMENT_POINTERS(file_for_suffix, file_len, pool);
       
       reached_prefix = file_for_suffix[0].chunk == suffix_min_chunk0 
                        && (file_for_suffix[0].curp - file_for_suffix[0].buffer)
                           == suffix_min_offset0;
 
-      if (reached_prefix || is_one_at_bof(file_for_suffix_ptr, file_len))
+      if (reached_prefix || is_one_at_bof(file_for_suffix, file_len))
         break;
       else
         for (i = 1, is_match = TRUE; i < file_len; i++)
@@ -551,34 +545,34 @@ find_identical_suffix(struct file_info *
     }
 
   /* Slide one byte forward, to point at the first byte of identical suffix */
-  INCREMENT_POINTERS(file_for_suffix_ptr, file_len, pool);
+  INCREMENT_POINTERS(file_for_suffix, file_len, pool);
 
   /* Slide forward until we find an eol sequence to add the rest of the line
      we're in. Then add SUFFIX_LINES_TO_KEEP more lines. Stop if at least 
      one file reaches its end. */
   do
     {
-      while (!is_one_at_eof(file_for_suffix_ptr, file_len)
+      while (!is_one_at_eof(file_for_suffix, file_len)
              && *file_for_suffix[0].curp != '\n'
              && *file_for_suffix[0].curp != '\r')
-        INCREMENT_POINTERS(file_for_suffix_ptr, file_len, pool);
+        INCREMENT_POINTERS(file_for_suffix, file_len, pool);
 
       /* Slide one or two more bytes, to point past the eol. */
-      if (!is_one_at_eof(file_for_suffix_ptr, file_len)
+      if (!is_one_at_eof(file_for_suffix, file_len)
           && *file_for_suffix[0].curp == '\r')
-        INCREMENT_POINTERS(file_for_suffix_ptr, file_len, pool);
-      if (!is_one_at_eof(file_for_suffix_ptr, file_len)
+        INCREMENT_POINTERS(file_for_suffix, file_len, pool);
+      if (!is_one_at_eof(file_for_suffix, file_len)
           && *file_for_suffix[0].curp == '\n')
-        INCREMENT_POINTERS(file_for_suffix_ptr, file_len, pool);
+        INCREMENT_POINTERS(file_for_suffix, file_len, pool);
     }
-  while (!is_one_at_eof(file_for_suffix_ptr, file_len) 
+  while (!is_one_at_eof(file_for_suffix, file_len) 
          && suffix_lines_to_keep--);
 
   /* Save the final suffix information in the original file_info */
   for (i = 0; i < file_len; i++)
     {
-      file[i]->suffix_start_chunk = file_for_suffix[i].chunk;
-      file[i]->suffix_offset_in_chunk = 
+      file[i].suffix_start_chunk = file_for_suffix[i].chunk;
+      file[i].suffix_offset_in_chunk = 
         file_for_suffix[i].curp - file_for_suffix[i].buffer;
     }
 
@@ -607,7 +601,7 @@ datasources_open(void *baton, apr_off_t 
                  apr_size_t datasource_len)
 {
   svn_diff__file_baton_t *file_baton = baton;
-  struct file_info *file[4];
+  struct file_info files[4];
   apr_finfo_t finfo[4];
   apr_off_t length[4];
   svn_boolean_t reached_one_eof;
@@ -616,18 +610,21 @@ datasources_open(void *baton, apr_off_t 
   /* Open datasources and read first chunk */
   for (i = 0; i < datasource_len; i++)
     {
-      file[i] = &file_baton->files[datasource_to_index(datasource[i])];
-      SVN_ERR(svn_io_file_open(&file[i]->file, file[i]->path,
+      struct file_info *file
+          = &file_baton->files[datasource_to_index(datasource[i])];
+      SVN_ERR(svn_io_file_open(&file->file, file->path,
                                APR_READ, APR_OS_DEFAULT, file_baton->pool));
       SVN_ERR(svn_io_file_info_get(&finfo[i], APR_FINFO_SIZE,
-                                   file[i]->file, file_baton->pool));
-      file[i]->size = finfo[i].size;
+                                   file->file, file_baton->pool));
+      file->size = finfo[i].size;
       length[i] = finfo[i].size > CHUNK_SIZE ? CHUNK_SIZE : finfo[i].size;
-      file[i]->buffer = apr_palloc(file_baton->pool, (apr_size_t) length[i]);
-      SVN_ERR(read_chunk(file[i]->file, file[i]->path, file[i]->buffer,
+      file->buffer = apr_palloc(file_baton->pool, (apr_size_t) length[i]);
+      SVN_ERR(read_chunk(file->file, file->path, file->buffer,
                          length[i], 0, file_baton->pool));
-      file[i]->endp = file[i]->buffer + length[i];
-      file[i]->curp = file[i]->buffer;
+      file->endp = file->buffer + length[i];
+      file->curp = file->buffer;
+
+      files[i] = *file;
     }
 
   for (i = 0; i < datasource_len; i++)
@@ -636,14 +633,16 @@ datasources_open(void *baton, apr_off_t 
       return SVN_NO_ERROR;
 
   SVN_ERR(find_identical_prefix(&reached_one_eof, prefix_lines,
-                                file, datasource_len, file_baton->pool));
+                                files, datasource_len, file_baton->pool));
 
-  if (reached_one_eof)
-    /* At least one file consisted totally of identical prefix, 
-     * so there will be no identical suffix. We're done. */
-    return SVN_NO_ERROR;
+  if (!reached_one_eof)
+    /* No file consisted totally of identical prefix,
+     * so there may be some identical suffix.  */
+    SVN_ERR(find_identical_suffix(files, datasource_len, file_baton->pool));
 
-  SVN_ERR(find_identical_suffix(file, datasource_len, file_baton->pool));
+  /* Copy local results back to baton. */
+  for (i = 0; i < datasource_len; i++)
+    file_baton->files[datasource_to_index(datasource[i])] = files[i];
 
   return SVN_NO_ERROR;
 }