D4150: linelog: optimize replacelines
quark (Jun Wu)
phabricator at mercurial-scm.org
Tue Aug 7 02:00:09 UTC 2018
quark created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.
REVISION SUMMARY
The optimization to avoid calling `annotate` inside replacelines is critical
for practical uses.
Before this patch:
hg perflinelogedits
! wall 10.883419 comb 10.770000 user 10.670000 sys 0.100000 (best of 3)
After this patch:
hg perflinelogedits
! wall 0.219167 comb 0.220000 user 0.210000 sys 0.010000 (best of 39)
REPOSITORY
rHG Mercurial
REVISION DETAIL
https://phab.mercurial-scm.org/D4150
AFFECTED FILES
mercurial/linelog.py
CHANGE DETAILS
diff --git a/mercurial/linelog.py b/mercurial/linelog.py
--- a/mercurial/linelog.py
+++ b/mercurial/linelog.py
@@ -313,17 +313,22 @@
appendinst = self._program.append
# insert
+ blineinfos = []
+ bappend = blineinfos.append
if b1 < b2:
# Determine the jump target for the JGE at the start of
# the new block.
tgt = oldproglen + (b2 - b1 + 1)
# Jump to skip the insert if we're at an older revision.
appendinst(_jl(rev, tgt))
for linenum in pycompat.xrange(b1, b2):
if _internal_blines is None:
+ bappend(lineinfo(rev, linenum, programlen()))
appendinst(_line(rev, linenum))
else:
- appendinst(_line(*_internal_blines[linenum]))
+ newrev, newlinenum = _internal_blines[linenum]
+ bappend(lineinfo(newrev, newlinenum, programlen()))
+ appendinst(_line(newrev, newlinenum))
# delete
if a1 < a2:
if a2 > len(ar.lines):
@@ -342,19 +347,26 @@
endaddr = ar.lines[a2 - 1]._offset + 1
appendinst(_jge(rev, endaddr))
# copy instruction from a1
+ a1instpc = programlen()
appendinst(a1inst)
# if a1inst isn't a jump or EOF, then we need to add an unconditional
# jump back into the program here.
if not isinstance(a1inst, (_jump, _eof)):
appendinst(_jump(0, a1info._offset + 1))
# Patch instruction at a1, which makes our patch live.
self._program[a1info._offset] = _jump(0, oldproglen)
- # For compat with the C version, re-annotate rev so that
- # self.annotateresult is cromulent.. We could fix up the
- # annotateresult in place (which is how the C version works),
- # but for now we'll pass on that and see if it matters in
- # practice.
- self.annotate(max(self._lastannotate.rev, rev))
+
+ # Update self._lastannotate in place. This serves as a cache to avoid
+ # expensive "self.annotate" in this function. It is critical to
+ # performance.
+ if len(self._lastannotate.lines) > a1:
+ self._lastannotate.lines[a1]._offset = a1instpc
+ else:
+ assert isinstance(a1inst, _eof)
+ self._lastannotate._eof = a1instpc
+ self._lastannotate.lines[a1:a2] = blineinfos
+ self._lastannotate.rev = max(self._lastannotate.rev, rev)
+
if rev > self._maxrev:
self._maxrev = rev
To: quark, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list