phases: invalidate the phases set less often on retract boundary
We already have the information to update the phase set, so we do so directly
instead of invalidating the cache.
This show a sizeable speedup in our `perf::unbundle` benchmark on the
many-draft mozilla-try repository.
### data-env-vars.name = mozilla-try-2023-03-22-zstd-sparse-revlog
# benchmark.name = hg.perf.perf-unbundle
# bin-env-vars.hg.flavor = no-rust
# bin-env-vars.hg.py-re2-module = default
# benchmark.variants.
issue6528 = disabled
# benchmark.variants.revs = last-10
before: 2.055259 seconds
after: 1.887064 seconds (-8.18%)
# benchmark.variants.revs = last-100
before: 2.409239 seconds
after: 2.222429 seconds (-7.75%)
# benchmark.variants.revs = last-1000
before: 3.945648 seconds
after: 3.762480 seconds (-4.64%)
--- a/mercurial/bundlerepo.py Wed Feb 21 13:05:23 2024 +0100
+++ b/mercurial/bundlerepo.py Wed Feb 21 13:05:29 2024 +0100
@@ -269,9 +269,10 @@
def _write(self, fp):
raise NotImplementedError
- def _updateroots(self, repo, phase, newroots, tr):
+ def _updateroots(self, repo, phase, newroots, tr, invalidate=True):
self._phaseroots[phase] = newroots
- self.invalidate()
+ if invalidate:
+ self.invalidate()
self.dirty = True
--- a/mercurial/phases.py Wed Feb 21 13:05:23 2024 +0100
+++ b/mercurial/phases.py Wed Feb 21 13:05:29 2024 +0100
@@ -624,10 +624,11 @@
fp.write(b'%i %s\n' % (phase, hex(h)))
self.dirty = False
- def _updateroots(self, repo, phase, newroots, tr):
+ def _updateroots(self, repo, phase, newroots, tr, invalidate=True):
self._phaseroots[phase] = newroots
- self.invalidate()
self.dirty = True
+ if invalidate:
+ self.invalidate()
assert repo.filtername is None
wrepo = weakref.ref(repo)
@@ -811,11 +812,23 @@
changed_revs[r] = r_phase
elif r in currentroots:
replaced_roots.add(r)
+ sets = self._phasesets
+ sets[targetphase].update(changed_revs)
+ for r, old in changed_revs.items():
+ if old > public:
+ sets[old].discard(r)
if new_roots:
assert changed_revs
+
final_roots = new_roots | currentroots - replaced_roots
- self._updateroots(repo, targetphase, final_roots, tr)
+ self._updateroots(
+ repo,
+ targetphase,
+ final_roots,
+ tr,
+ invalidate=False,
+ )
if targetphase > 1:
retracted = set(changed_revs)
for lower_phase in range(1, targetphase):
@@ -824,7 +837,13 @@
continue
if lower_roots & retracted:
simpler_roots = lower_roots - retracted
- self._updateroots(repo, lower_phase, simpler_roots, tr)
+ self._updateroots(
+ repo,
+ lower_phase,
+ simpler_roots,
+ tr,
+ invalidate=False,
+ )
return changed_revs
else:
assert not changed_revs