hg: improve perf interactions with treedirstate

Summary:
There are a couple of ways that dirstate and fsmonitor interact with
treedirstate that are sub-optimal.

When iterating over all files in the dirstate map, use the iterator of keys
(`__iter__` rather than `iteritems`) to hit the treedirstate fastpath that
doesn't build the dirstate tuples.

Use `__getitem__` and catch the `KeyError` rather than `__contains__` followed
by `__getitem__`, as the latter involves two look-ups in the tree.

Skip the indirect call to `hastrackedfile` and `hasremovedfile` as these add
noticable overhead when called many times.

Also fix up the `test-check-code` failure for treedirstate.

Reviewed By: ryanmce

Differential Revision: D6818952

fbshipit-source-id: d49907c282a1b97c66a3d24257bdf54800d7da70
This commit is contained in:
Mark Thomas 2018-01-26 07:01:45 -08:00 committed by Saurabh Singh
parent d942f5a88e
commit 4b7dab149a
4 changed files with 9 additions and 13 deletions

View File

@ -420,13 +420,11 @@ def overridewalk(orig, self, match, subrepos, unknown, ignored, full=True):
if f not in results and matchfn(f))
else:
if matchalways:
visit.update(f for f, st in dmap.iteritems() if f not in results)
visit.update(f for f in dmap if f not in results)
visit.update(f for f in copymap if f not in results)
else:
visit.update(f for f, st in dmap.iteritems()
if f not in results and matchfn(f))
visit.update(f for f in copymap
if f not in results and matchfn(f))
visit.update(f for f in dmap if f not in results and matchfn(f))
visit.update(f for f in copymap if f not in results and matchfn(f))
audit = pathutil.pathauditor(self._root, cached=True).check
auditpass = [f for f in visit if audit(f)]

View File

@ -237,7 +237,8 @@ class treedirstatemap(object):
return self._rmap.hasremovedfile(filename)
def __contains__(self, filename):
return self.hastrackedfile(filename) or self.hasremovedfile(filename)
return (self._rmap.hastrackedfile(filename) or
self._rmap.hasremovedfile(filename))
def trackedfiles(self):
"""Returns a list of all filenames tracked by the dirstate."""
@ -671,7 +672,7 @@ def wrapclose(orig, self):
invocations that involve writing to treedirstate.
"""
# For chg, do not clean up on the "serve" command
if 'CHGINTERNALMARK' in os.environ:
if 'CHGINTERNALMARK' in encoding.environ:
return orig(self)
try:

View File

@ -1025,7 +1025,6 @@ class dirstate(object):
dmap = self._map
dmap.preload()
dcontains = dmap.__contains__
dget = dmap.__getitem__
ladd = lookup.append # aka "unsure"
madd = modified.append
@ -1048,7 +1047,9 @@ class dirstate(object):
full = listclean or match.traversedir is not None
for fn, st in self.walk(match, subrepos, listunknown, listignored,
full=full).iteritems():
if not dcontains(fn):
try:
t = dget(fn)
except KeyError:
if (listignored or mexact(fn)) and dirignore(fn):
if listignored:
iadd(fn)
@ -1063,7 +1064,6 @@ class dirstate(object):
# a list, but falls back to creating a full-fledged iterator in
# general. That is much slower than simply accessing and storing the
# tuple members one by one.
t = dget(fn)
state = t[0]
mode = t[1]
size = t[2]

View File

@ -129,9 +129,6 @@ New errors are not allowed. Warnings are strongly discouraged.
hgext/phabstatus.py:78:
> repodir=os.getcwd(), ca_bundle=ca_certs, repo=repo)
use pycompat.getcwd instead (py3)
hgext/treedirstate.py:674:
> if 'CHGINTERNALMARK' in os.environ:
use encoding.environ instead (py3)
hgext/tweakdefaults.py:275:
> if pipei_bufsize != 4096 and os.name == 'nt':
use pycompat.osname instead (py3)