Hi devs,
here comes the second set of local optimizations.
It contains a number of simple improvements over
the original code.
-- Stefan^2.
[[[
Numerous local optimizations.
* subversion/include/svn_delta.h
(enum svn_delta_action): ensure that these definitions
will always have these values
* subversion/libsvn_delta/compose_delta.c
(search_offset_index): use size_t to index memory
(copy_source_ops): dito; optimize a common case
* subversion/libsvn_delta/svndiff.c
(decode_file_offset, decode_size): use slightly more
efficient formulations
(decode_instruction): directly map action codes -
made possible by defining the enum values
* subversion/libsvn_subr/checksum.c
(svn_checksum_parse_hex): eliminate CTR function calls
* subversion/libsvn_subr/stream.c
(stream_readline): numbytes is invariant until EOF
]]]
Index: subversion/include/svn_delta.h
===================================================================
--- subversion/include/svn_delta.h (revision 937673)
+++ subversion/include/svn_delta.h (working copy)
@@ -100,7 +100,7 @@
* It must be the case that 0 <= @a offset < @a offset +
* @a length <= size of source view.
*/
- svn_txdelta_source,
+ svn_txdelta_source = 0,
/** Append the @a length bytes at @a offset in the target view, to the
* target.
@@ -119,7 +119,7 @@
* useful in encoding long runs of consecutive characters, long runs
* of CR/LF pairs, etc.
*/
- svn_txdelta_target,
+ svn_txdelta_target = 1,
/** Append the @a length bytes at @a offset in the window's @a new string
* to the target.
@@ -129,7 +129,7 @@
* order with no overlap at the moment; svn_txdelta_to_svndiff()
* depends on this.
*/
- svn_txdelta_new
+ svn_txdelta_new = 2
};
/** A single text delta instruction. */
Index: subversion/libsvn_delta/compose_delta.c
===================================================================
--- subversion/libsvn_delta/compose_delta.c (revision 937673)
+++ subversion/libsvn_delta/compose_delta.c (working copy)
@@ -165,10 +165,10 @@
as hint because most lookups come as a sequence of decreasing values
for OFFSET and they concentrate on the lower end of the array. */
-static int
-search_offset_index(const offset_index_t *ndx, apr_size_t offset, int hint)
+static apr_size_t
+search_offset_index(const offset_index_t *ndx, apr_size_t offset, apr_size_t hint)
{
- int lo, hi, op;
+ apr_size_t lo, hi, op;
assert(offset < ndx->offs[ndx->length]);
@@ -635,13 +635,13 @@
static void
copy_source_ops(apr_size_t offset, apr_size_t limit,
apr_size_t target_offset,
- int hint,
+ apr_size_t hint,
svn_txdelta__ops_baton_t *build_baton,
const svn_txdelta_window_t *window,
const offset_index_t *ndx,
apr_pool_t *pool)
{
- int op_ndx = search_offset_index(ndx, offset, hint);
+ apr_size_t op_ndx = search_offset_index(ndx, offset, hint);
for (;; ++op_ndx)
{
const svn_txdelta_op_t *const op = &window->ops[op_ndx];
@@ -694,7 +694,10 @@
The idea here is to transpose the pattern, then generate
another overlapping copy. */
const apr_size_t ptn_length = off[0] - op->offset;
- const apr_size_t ptn_overlap = fix_offset % ptn_length;
+ const apr_size_t ptn_overlap = ptn_length > 2
+ ? fix_offset % ptn_length
+ : fix_offset & (ptn_length-1);
+
apr_size_t fix_off = fix_offset;
apr_size_t tgt_off = target_offset;
assert(ptn_length > ptn_overlap);
Index: subversion/libsvn_delta/svndiff.c
===================================================================
--- subversion/libsvn_delta/svndiff.c (revision 937673)
+++ subversion/libsvn_delta/svndiff.c (working copy)
@@ -361,16 +361,24 @@
const unsigned char *p,
const unsigned char *end)
{
+ svn_filesize_t temp = 0;
if (p + MAX_ENCODED_INT_LEN < end)
end = p + MAX_ENCODED_INT_LEN;
/* Decode bytes until we're done. */
- *val = 0;
while (p < end)
{
- *val = (*val << 7) | (*p & 0x7f);
- if (((*p++ >> 7) & 0x1) == 0)
+ unsigned c = *p;
+ temp = (temp << 7) | (c & 0x7f);
+ ++p;
+
+ if (c < 0x80)
+ {
+ *val = temp;
return p;
+ }
}
+
+ *val = temp;
return NULL;
}
@@ -382,16 +390,24 @@
const unsigned char *p,
const unsigned char *end)
{
+ apr_size_t temp = 0;
if (p + MAX_ENCODED_INT_LEN < end)
end = p + MAX_ENCODED_INT_LEN;
/* Decode bytes until we're done. */
- *val = 0;
while (p < end)
{
- *val = (*val << 7) | (*p & 0x7f);
- if (((*p++ >> 7) & 0x1) == 0)
+ apr_size_t c = *p;
+ temp = (temp << 7) | (c & 0x7f);
+ ++p;
+
+ if (c < 0x80)
+ {
+ *val = temp;
return p;
+ }
}
+
+ *val = temp;
return NULL;
}
@@ -458,27 +474,30 @@
const unsigned char *p,
const unsigned char *end)
{
+ apr_size_t c;
+ apr_size_t action;
+
if (p == end)
return NULL;
/* Decode the instruction selector. */
- switch ((*p >> 6) & 0x3)
- {
- case 0x0: op->action_code = svn_txdelta_source; break;
- case 0x1: op->action_code = svn_txdelta_target; break;
- case 0x2: op->action_code = svn_txdelta_new; break;
- case 0x3: return NULL;
- }
+ c = *p;
+ p++;
+ action = (c >> 6) & 0x3;
+ if (action >= 0x3)
+ return NULL;
+ op->action_code = (enum svn_delta_action)(action);
+
/* Decode the length and offset. */
- op->length = *p++ & 0x3f;
+ op->length = c & 0x3f;
if (op->length == 0)
{
p = decode_size(&op->length, p, end);
if (p == NULL)
return NULL;
}
- if (op->action_code != svn_txdelta_new)
+ if (action != svn_txdelta_new)
{
p = decode_size(&op->offset, p, end);
if (p == NULL)
Index: subversion/libsvn_subr/checksum.c
===================================================================
--- subversion/libsvn_subr/checksum.c (revision 937673)
+++ subversion/libsvn_subr/checksum.c (working copy)
@@ -206,12 +206,39 @@
for (i = 0; i < len; i++)
{
- if ((! isxdigit(hex[i * 2])) || (! isxdigit(hex[i * 2 + 1])))
+ char c1 = hex[i * 2];
+ char c2 = hex[i * 2 + 1];
+
+ svn_boolean_t bad = FALSE;
+ unsigned char upper;
+ unsigned char lower;
+
+ if (c1 > '9')
+ {
+ bad = (c1 > 'f') || (c1 < 'a');
+ upper = c1 - 'a' + 10;
+ }
+ else
+ {
+ bad = c1 < '0';
+ upper = c1 - '0';
+ }
+
+ if (c2 > '9')
+ {
+ bad |= (c2 > 'f') || (c2 < 'a');
+ lower = c2 - 'a' + 10;
+ }
+ else
+ {
+ bad |= c2 < '0';
+ lower = c2 - '0';
+ }
+
+ if (bad)
return svn_error_create(SVN_ERR_BAD_CHECKSUM_PARSE, NULL, NULL);
- ((unsigned char *)(*checksum)->digest)[i] =
- (( isalpha(hex[i*2]) ? hex[i*2] - 'a' + 10 : hex[i*2] - '0') << 4) |
- ( isalpha(hex[i*2+1]) ? hex[i*2+1] - 'a' + 10 : hex[i*2+1] - '0');
+ ((unsigned char *)(*checksum)->digest)[i] = (upper << 4) | lower;
is_zeros |= (*checksum)->digest[i];
}
Index: subversion/libsvn_subr/stream.c
===================================================================
--- subversion/libsvn_subr/stream.c (revision 937673)
+++ subversion/libsvn_subr/stream.c (working copy)
@@ -355,9 +355,9 @@
/* Read into STR up to and including the next EOL sequence. */
match = eol_str;
+ numbytes = 1;
while (*match)
{
- numbytes = 1;
SVN_ERR(svn_stream_read(stream, &c, &numbytes));
if (numbytes != 1)
{
Received on 2010-04-25 16:52:58 CEST