Mercurial > hg
changeset 51352:7083b33a2699
delta-find: explicitly deal with usage of the cached revision
We can remove this from the general logic path and directly deal with this
corner case early.
This result in a small change in test-generaldelta.t as it turns out that:
- at commit time we (sometimes) precompute a delta against p1 and pass it as the
cached delta.
- since cached delta where going through the same filtering as everything, we
could "optimize" the base if it applied to an empty delta, resulting in not
using the pre-computed delta.
The simpler logic fix the second item, making the cached delta base always actually
tested when requested.
Note that the computation of a fast delta against p1 only is questionable, but
looking into that is out of scope for this series.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Sun, 07 Jan 2024 03:08:46 +0100 |
parents | bbbfa00d1e67 |
children | 5cc04a6da19d |
files | mercurial/revlogutils/deltas.py tests/test-generaldelta.t |
diffstat | 2 files changed, 27 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/revlogutils/deltas.py Sun Jan 07 03:02:30 2024 +0100 +++ b/mercurial/revlogutils/deltas.py Sun Jan 07 03:08:46 2024 +0100 @@ -840,7 +840,24 @@ assert self.revlog.delta_config.general_delta self._candidates_iterator = self._refined_groups() self._last_good = None - self._next_internal_group() + if ( + self.cachedelta is not None + and self.cachedelta[2] > DELTA_BASE_REUSE_NO + and self._pre_filter_rev(self.cachedelta[0]) + ): + # First we try to reuse a the delta contained in the bundle. (or from + # the source revlog) + # + # This logic only applies to general delta repositories and can be + # disabled through configuration. Disabling reuse source delta is + # useful when we want to make sure we recomputed "optimal" deltas. + self.current_stage = _STAGE_CACHED + self._internal_group = (self.cachedelta[0],) + self._internal_idx = 0 + self.current_group = self._internal_group + self.tested.update(self.current_group) + else: + self._next_internal_group() def _next_internal_group(self): # self._internal_group can be larger than self.current_group @@ -868,6 +885,14 @@ old_good = self._last_good if good_delta is not None: self._last_good = good_delta.base + if self.current_stage == _STAGE_CACHED and good_delta is not None: + # the cache is good, let us use the cache as requested + self._candidates_iterator = None + self._internal_group = None + self._internal_idx = None + self.current_group = None + return + if (self._internal_idx < len(self._internal_group)) and ( old_good != good_delta ): @@ -1032,23 +1057,6 @@ def _refined_groups(self): good = None - # First we try to reuse a the delta contained in the bundle. (or from - # the source revlog) - # - # This logic only applies to general delta repositories and can be - # disabled through configuration. Disabling reuse source delta is - # useful when we want to make sure we recomputed "optimal" deltas. - if ( - self.cachedelta is not None - and self.cachedelta[2] > DELTA_BASE_REUSE_NO - ): - # Assume what we received from the server is a good choice - # build delta will reuse the cache - self.current_stage = _STAGE_CACHED - good = yield (self.cachedelta[0],) - if good is not None: - yield None - return groups = self._raw_groups() for candidates in groups: good = yield candidates
--- a/tests/test-generaldelta.t Sun Jan 07 03:02:30 2024 +0100 +++ b/tests/test-generaldelta.t Sun Jan 07 03:08:46 2024 +0100 @@ -271,7 +271,7 @@ 51 17 -1 4 3 50 prev 3?? 5?? 6?? 1.0???? 6?? 0 0.00000 (glob) 52 51 -1 4 4 51 p1 58 640 6?? 1.0???? 6?? 0 0.00000 (glob) 53 52 -1 5 1 -1 base 0 0 0 0.00000 0 0 0.00000 - 54 53 -1 6 1 -1 base 3?? 640 3?? 0.5???? 3?? 0 0.00000 (glob) + 54 53 -1 5 2 53 p1 3?? 640 3?? 0.5???? 3?? 0 0.00000 (glob) $ hg clone --pull source-repo --config experimental.maxdeltachainspan=2800 relax-chain --config format.generaldelta=yes requesting all changes adding changesets