On Thu, Jul 21, 2011 at 6:53 AM, <phi...@apache.org> wrote: > Author: philip > Date: Thu Jul 21 10:53:15 2011 > New Revision: 1149105 > > URL: http://svn.apache.org/viewvc?rev=1149105&view=rev > Log: > Fix issue 3966, log_noop_revs in merge is far too slow. > > * subversion/libsvn_client/merge.c: > (rangelist_merge_revision): New, specialised rangelist merge. > (log_noop_revs): Use specialised rangelist merge. > > Modified: > subversion/trunk/subversion/libsvn_client/merge.c > > Modified: subversion/trunk/subversion/libsvn_client/merge.c > URL: > http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1149105&r1=1149104&r2=1149105&view=diff > ============================================================================== > --- subversion/trunk/subversion/libsvn_client/merge.c (original) > +++ subversion/trunk/subversion/libsvn_client/merge.c Thu Jul 21 10:53:15 2011 > @@ -7868,6 +7868,36 @@ typedef struct log_noop_baton_t > apr_pool_t *pool; > } log_noop_baton_t; > > +/* Helper for log_noop_revs, this is not a general purpose rangelist > + merge. Merge the single revision range REVISION-1 to REVISION into > + RANGELIST. The existing ranges in RANGELIST must be ordered from > + highest/youngest to lowest/oldest. */
Hi Philip, The rangelist APIs expect[1] the elements to be sorted from to lowest/oldest to highest/youngest, so you are creating an invalid array which the svn_rangelist_APIs won't understand correctly. In rr1149228 I switched remove_noop_subtree_ranges's call to svn_ra_get_log2 to get the logs from oldest to youngest, so log_noop_revs/rangelist_merge_revision get the revs in that order, can build a valid rangelist, and can still avoid the worst-case performance of svn_rangelist_merge when adding a single range younger than any in the output rangelist. Paul [1] svn_mergeinfo.h: * (b) A "rangelist". An array (@c apr_array_header_t *) of non-overlapping * merge ranges (@c svn_merge_range_t *), sorted as said by * @c svn_sort_compare_ranges(). An empty range list is represented by * an empty array. Unless specifically noted otherwise, all APIs require * rangelists that describe only forward ranges, i.e. the range's start * revision is less than its end revision. > +static svn_error_t * > +rangelist_merge_revision(apr_array_header_t *rangelist, > + svn_revnum_t revision, > + apr_pool_t *result_pool) > +{ > + svn_merge_range_t *new_range; > + if (rangelist->nelts) > + { > + svn_merge_range_t *range = APR_ARRAY_IDX(rangelist, rangelist->nelts - > 1, > + svn_merge_range_t *); > + if (range->start == revision) > + { > + range->start = revision - 1; > + return SVN_NO_ERROR; > + } > + } > + new_range = apr_palloc(result_pool, sizeof(*new_range)); > + new_range->start = revision - 1; > + new_range->end = revision; > + new_range->inheritable = TRUE; > + > + APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = new_range; > + > + return SVN_NO_ERROR; > +} > + > /* Implements the svn_log_entry_receiver_t interface. > > BATON is an log_noop_baton_t *. > @@ -7892,7 +7922,6 @@ log_noop_revs(void *baton, > svn_boolean_t log_entry_rev_required = FALSE; > apr_array_header_t *rl1; > apr_array_header_t *rl2; > - apr_array_header_t *rangelist; > > /* The baton's pool is essentially an iterpool so we must clear it > * for each invocation of this function, preserving the result > @@ -7909,12 +7938,10 @@ log_noop_revs(void *baton, > > revision = log_entry->revision; > > - rangelist = svn_rangelist__initialize(revision - 1, revision, TRUE, > - log_gap_baton->pool); > /* Unconditionally add LOG_ENTRY->REVISION to BATON->OPERATIVE_MERGES. */ > - SVN_ERR(svn_rangelist_merge(&(log_gap_baton->operative_ranges), > - rangelist, > - log_gap_baton->pool)); > + SVN_ERR(rangelist_merge_revision(log_gap_baton->operative_ranges, > + revision, > + log_gap_baton->pool)); > > /* Examine each path affected by LOG_ENTRY->REVISION. If the explicit or > inherited mergeinfo for *all* of the corresponding paths under > @@ -7977,6 +8004,10 @@ log_noop_revs(void *baton, > if (paths_explicit_rangelist) > { > apr_array_header_t *intersecting_range; > + apr_array_header_t *rangelist; > + > + rangelist = svn_rangelist__initialize(revision - 1, revision, TRUE, > + log_gap_baton->pool); > > /* If PATH inherited mergeinfo we must consider inheritance in the > event the inherited mergeinfo is actually non-inheritable. */ > @@ -7995,9 +8026,9 @@ log_noop_revs(void *baton, > } > > if (!log_entry_rev_required) > - SVN_ERR(svn_rangelist_merge(&(log_gap_baton->merged_ranges), > - rangelist, > - log_gap_baton->pool)); > + SVN_ERR(rangelist_merge_revision(log_gap_baton->merged_ranges, > + revision, > + log_gap_baton->pool)); > > return SVN_NO_ERROR; > } > > >