Mercurial > hg
comparison mercurial/manifest.py @ 39668:24870f1be088
narrow: when writing treemanifests, skip inspecting directories outside narrow
This provides significant speed benefits when narrow and treemanifests are in
use, see the timing numbers below. Note that like previously, differences of <5%
are considered noise.
The below timing numbers are in the same style as previously (example:
ee7ee0c516ca). 'before' is 9db85644, and does not include that example commit's
improvements.
diff --git:
repo | N | T | before (mean +- stdev) | after (mean +- stdev) | % of before
------+---+---+------------------------+-----------------------+------------
m-u | | | 1.327 s +- 0.051 s | 1.296 s +- 0.009 s | 97.7%
m-u | | x | 1.310 s +- 0.020 s | 1.295 s +- 0.015 s | 98.9%
m-u | x | | 1.295 s +- 0.018 s | 1.296 s +- 0.007 s | 100.1%
m-u | x | x | 83.5 ms +- 0.8 ms | 84.1 ms +- 0.8 ms | 100.7%
l-d-r | | | 205.1 ms +- 3.5 ms | 205.0 ms +- 3.8 ms | 100.0%
l-d-r | | x | 194.2 ms +- 5.6 ms | 192.3 ms +- 4.3 ms | 99.0%
l-d-r | x | | 99.1 ms +- 2.2 ms | 97.8 ms +- 0.9 ms | 98.7%
l-d-r | x | x | 66.2 ms +- 1.0 ms | 67.2 ms +- 2.7 ms | 101.5%
diff -c . --git:
repo | N | T | before (mean +- stdev) | after (mean +- stdev) | % of before
------+---+---+------------------------+-----------------------+------------
m-u | | | 233.9 ms +- 1.9 ms | 235.6 ms +- 5.1 ms | 100.7%
m-u | | x | 151.4 ms +- 1.2 ms | 152.2 ms +- 2.0 ms | 100.5%
m-u | x | | 234.8 ms +- 2.7 ms | 235.0 ms +- 2.7 ms | 100.1%
m-u | x | x | 127.8 ms +- 2.1 ms | 126.0 ms +- 1.1 ms | 98.6%
l-d-r | | | 82.5 ms +- 1.6 ms | 82.3 ms +- 2.0 ms | 99.8%
l-d-r | | x | 3.742 s +- 0.017 s | 3.819 s +- 0.208 s | 102.1%
l-d-r | x | | 84.4 ms +- 1.5 ms | 83.2 ms +- 1.0 ms | 98.6%
l-d-r | x | x | 751.2 ms +- 5.0 ms | 755.8 ms +- 12.9 ms | 100.6%
rebase -r . --keep -d .^^:
repo | N | T | before (mean +- stdev) | after (mean +- stdev) | % of before
------+---+---+------------------------+-----------------------+------------
m-u | | | 5.519 s +- 0.038 s | 5.526 s +- 0.057 s | 100.1%
m-u | | x | 5.588 s +- 0.048 s | 5.607 s +- 0.061 s | 100.3%
m-u | x | | 5.520 s +- 0.044 s | 5.546 s +- 0.059 s | 100.5%
m-u | x | x | 586.6 ms +- 12.8 ms | 554.9 ms +- 21.2 ms | 94.6% <--
l-d-r | | | 629.8 ms +- 5.5 ms | 627.4 ms +- 6.6 ms | 99.6%
l-d-r | | x | 6.165 s +- 0.058 s | 6.255 s +- 0.303 s | 101.5%
l-d-r | x | | 270.2 ms +- 2.3 ms | 271.4 ms +- 2.7 ms | 100.4%
l-d-r | x | x | 4.700 s +- 0.025 s | 1.651 s +- 0.016 s | 35.1% <--
status --change . --copies:
repo | N | T | before (mean +- stdev) | after (mean +- stdev) | % of before
------+---+---+------------------------+-----------------------+------------
m-u | | | 215.4 ms +- 2.3 ms | 216.5 ms +- 4.2 ms | 100.5%
m-u | | x | 132.9 ms +- 1.2 ms | 132.0 ms +- 1.4 ms | 99.3%
m-u | x | | 217.0 ms +- 1.9 ms | 215.4 ms +- 1.9 ms | 99.3%
m-u | x | x | 108.6 ms +- 1.0 ms | 108.2 ms +- 1.5 ms | 99.6%
l-d-r | | | 80.0 ms +- 1.3 ms | 80.5 ms +- 1.1 ms | 100.6%
l-d-r | | x | 3.916 s +- 0.187 s | 3.966 s +- 0.236 s | 101.3%
l-d-r | x | | 84.4 ms +- 3.1 ms | 83.9 ms +- 1.1 ms | 99.4%
l-d-r | x | x | 758.0 ms +- 8.2 ms | 753.5 ms +- 5.0 ms | 99.4%
status --copies:
repo | N | T | before (mean +- stdev) | after (mean +- stdev) | % of before
------+---+---+------------------------+-----------------------+------------
m-u | | | 1.905 s +- 0.025 s | 1.910 s +- 0.044 s | 100.3%
m-u | | x | 1.892 s +- 0.009 s | 1.895 s +- 0.012 s | 100.2%
m-u | x | | 1.891 s +- 0.012 s | 1.902 s +- 0.018 s | 100.6%
m-u | x | x | 93.3 ms +- 0.9 ms | 93.4 ms +- 0.8 ms | 100.1%
l-d-r | | | 570.7 ms +- 7.8 ms | 571.9 ms +- 18.5 ms | 100.2%
l-d-r | | x | 561.5 ms +- 5.2 ms | 562.9 ms +- 6.1 ms | 100.2%
l-d-r | x | | 171.7 ms +- 2.6 ms | 171.9 ms +- 1.2 ms | 100.1%
l-d-r | x | x | 142.7 ms +- 2.0 ms | 140.3 ms +- 1.0 ms | 98.3%
update $rev^; ~/src/hg/hg{hg}/hg update $rev:
repo | N | T | before (mean +- stdev) | after (mean +- stdev) | % of before
------+---+---+------------------------+-----------------------+------------
m-u | | | 3.126 s +- 0.016 s | 3.128 s +- 0.015 s | 100.1%
m-u | | x | 3.014 s +- 0.068 s | 3.008 s +- 0.031 s | 99.8%
m-u | x | | 3.143 s +- 0.037 s | 3.184 s +- 0.086 s | 101.3%
m-u | x | x | 308.0 ms +- 1.8 ms | 308.1 ms +- 5.7 ms | 100.0%
l-d-r | | | 430.8 ms +- 4.5 ms | 436.4 ms +- 8.7 ms | 101.3%
l-d-r | | x | 9.676 s +- 0.127 s | 9.945 s +- 0.272 s | 102.8%
l-d-r | x | | 254.2 ms +- 3.3 ms | 255.7 ms +- 3.1 ms | 100.6%
l-d-r | x | x | 1.571 s +- 0.030 s | 1.555 s +- 0.014 s | 99.0%
Differential Revision: https://phab.mercurial-scm.org/D4606
author | spectral <spectral@google.com> |
---|---|
date | Fri, 14 Sep 2018 16:29:51 -0700 |
parents | 3ba9ef0fb693 |
children | 5ccd791344f3 |
comparison
equal
deleted
inserted
replaced
39667:0b7594ada0db | 39668:24870f1be088 |
---|---|
1201 def _load_for_read(s): | 1201 def _load_for_read(s): |
1202 s.parse(gettext(), readsubtree) | 1202 s.parse(gettext(), readsubtree) |
1203 s._dirty = False | 1203 s._dirty = False |
1204 self._loadfunc = _load_for_read | 1204 self._loadfunc = _load_for_read |
1205 | 1205 |
1206 def writesubtrees(self, m1, m2, writesubtree): | 1206 def writesubtrees(self, m1, m2, writesubtree, match): |
1207 self._load() # for consistency; should never have any effect here | 1207 self._load() # for consistency; should never have any effect here |
1208 m1._load() | 1208 m1._load() |
1209 m2._load() | 1209 m2._load() |
1210 emptytree = treemanifest() | 1210 emptytree = treemanifest() |
1211 def getnode(m, d): | 1211 def getnode(m, d): |
1212 ld = m._lazydirs.get(d) | 1212 ld = m._lazydirs.get(d) |
1213 if ld: | 1213 if ld: |
1214 return ld[1] | 1214 return ld[1] |
1215 return m._dirs.get(d, emptytree)._node | 1215 return m._dirs.get(d, emptytree)._node |
1216 | 1216 |
1217 # we should have always loaded everything by the time we get here for | |
1218 # `self`, but possibly not in `m1` or `m2`. | |
1219 assert not self._lazydirs | |
1220 # let's skip investigating things that `match` says we do not need. | |
1221 visit = match.visitchildrenset(self._dir[:-1] or '.') | |
1222 if visit == 'this' or visit == 'all': | |
1223 visit = None | |
1217 for d, subm in self._dirs.iteritems(): | 1224 for d, subm in self._dirs.iteritems(): |
1225 if visit and d[:-1] not in visit: | |
1226 continue | |
1218 subp1 = getnode(m1, d) | 1227 subp1 = getnode(m1, d) |
1219 subp2 = getnode(m2, d) | 1228 subp2 = getnode(m2, d) |
1220 if subp1 == nullid: | 1229 if subp1 == nullid: |
1221 subp1, subp2 = subp2, subp1 | 1230 subp1, subp2 = subp2, subp1 |
1222 writesubtree(subm, subp1, subp2) | 1231 writesubtree(subm, subp1, subp2, match) |
1223 | 1232 |
1224 def walksubtrees(self, matcher=None): | 1233 def walksubtrees(self, matcher=None): |
1225 """Returns an iterator of the subtrees of this manifest, including this | 1234 """Returns an iterator of the subtrees of this manifest, including this |
1226 manifest itself. | 1235 manifest itself. |
1227 | 1236 |
1443 self._dirlogcache, | 1452 self._dirlogcache, |
1444 treemanifest=self._treeondisk) | 1453 treemanifest=self._treeondisk) |
1445 self._dirlogcache[d] = mfrevlog | 1454 self._dirlogcache[d] = mfrevlog |
1446 return self._dirlogcache[d] | 1455 return self._dirlogcache[d] |
1447 | 1456 |
1448 def add(self, m, transaction, link, p1, p2, added, removed, readtree=None): | 1457 def add(self, m, transaction, link, p1, p2, added, removed, readtree=None, |
1458 match=None): | |
1449 if p1 in self.fulltextcache and util.safehasattr(m, 'fastdelta'): | 1459 if p1 in self.fulltextcache and util.safehasattr(m, 'fastdelta'): |
1450 # If our first parent is in the manifest cache, we can | 1460 # If our first parent is in the manifest cache, we can |
1451 # compute a delta here using properties we know about the | 1461 # compute a delta here using properties we know about the |
1452 # manifest up-front, which may save time later for the | 1462 # manifest up-front, which may save time later for the |
1453 # revlog layer. | 1463 # revlog layer. |
1467 # just encode a fulltext of the manifest and pass that | 1477 # just encode a fulltext of the manifest and pass that |
1468 # through to the revlog layer, and let it handle the delta | 1478 # through to the revlog layer, and let it handle the delta |
1469 # process. | 1479 # process. |
1470 if self._treeondisk: | 1480 if self._treeondisk: |
1471 assert readtree, "readtree must be set for treemanifest writes" | 1481 assert readtree, "readtree must be set for treemanifest writes" |
1482 assert match, "match must be specified for treemanifest writes" | |
1472 m1 = readtree(self.tree, p1) | 1483 m1 = readtree(self.tree, p1) |
1473 m2 = readtree(self.tree, p2) | 1484 m2 = readtree(self.tree, p2) |
1474 n = self._addtree(m, transaction, link, m1, m2, readtree) | 1485 n = self._addtree(m, transaction, link, m1, m2, readtree, |
1486 match=match) | |
1475 arraytext = None | 1487 arraytext = None |
1476 else: | 1488 else: |
1477 text = m.text() | 1489 text = m.text() |
1478 n = self._revlog.addrevision(text, transaction, link, p1, p2) | 1490 n = self._revlog.addrevision(text, transaction, link, p1, p2) |
1479 arraytext = bytearray(text) | 1491 arraytext = bytearray(text) |
1481 if arraytext is not None: | 1493 if arraytext is not None: |
1482 self.fulltextcache[n] = arraytext | 1494 self.fulltextcache[n] = arraytext |
1483 | 1495 |
1484 return n | 1496 return n |
1485 | 1497 |
1486 def _addtree(self, m, transaction, link, m1, m2, readtree): | 1498 def _addtree(self, m, transaction, link, m1, m2, readtree, match): |
1487 # If the manifest is unchanged compared to one parent, | 1499 # If the manifest is unchanged compared to one parent, |
1488 # don't write a new revision | 1500 # don't write a new revision |
1489 if self.tree != '' and (m.unmodifiedsince(m1) or m.unmodifiedsince( | 1501 if self.tree != '' and (m.unmodifiedsince(m1) or m.unmodifiedsince( |
1490 m2)): | 1502 m2)): |
1491 return m.node() | 1503 return m.node() |
1492 def writesubtree(subm, subp1, subp2): | 1504 def writesubtree(subm, subp1, subp2, match): |
1493 sublog = self.dirlog(subm.dir()) | 1505 sublog = self.dirlog(subm.dir()) |
1494 sublog.add(subm, transaction, link, subp1, subp2, None, None, | 1506 sublog.add(subm, transaction, link, subp1, subp2, None, None, |
1495 readtree=readtree) | 1507 readtree=readtree, match=match) |
1496 m.writesubtrees(m1, m2, writesubtree) | 1508 m.writesubtrees(m1, m2, writesubtree, match) |
1497 text = m.dirtext() | 1509 text = m.dirtext() |
1498 n = None | 1510 n = None |
1499 if self.tree != '': | 1511 if self.tree != '': |
1500 # Double-check whether contents are unchanged to one parent | 1512 # Double-check whether contents are unchanged to one parent |
1501 if text == m1.dirtext(): | 1513 if text == m1.dirtext(): |
1695 return memmf | 1707 return memmf |
1696 | 1708 |
1697 def read(self): | 1709 def read(self): |
1698 return self._manifestdict | 1710 return self._manifestdict |
1699 | 1711 |
1700 def write(self, transaction, link, p1, p2, added, removed): | 1712 def write(self, transaction, link, p1, p2, added, removed, match=None): |
1701 return self._storage().add(self._manifestdict, transaction, link, | 1713 return self._storage().add(self._manifestdict, transaction, link, |
1702 p1, p2, added, removed) | 1714 p1, p2, added, removed, match=match) |
1703 | 1715 |
1704 @interfaceutil.implementer(repository.imanifestrevisionstored) | 1716 @interfaceutil.implementer(repository.imanifestrevisionstored) |
1705 class manifestctx(object): | 1717 class manifestctx(object): |
1706 """A class representing a single revision of a manifest, including its | 1718 """A class representing a single revision of a manifest, including its |
1707 contents, its parent revs, and its linkrev. | 1719 contents, its parent revs, and its linkrev. |
1800 return memmf | 1812 return memmf |
1801 | 1813 |
1802 def read(self): | 1814 def read(self): |
1803 return self._treemanifest | 1815 return self._treemanifest |
1804 | 1816 |
1805 def write(self, transaction, link, p1, p2, added, removed): | 1817 def write(self, transaction, link, p1, p2, added, removed, match=None): |
1806 def readtree(dir, node): | 1818 def readtree(dir, node): |
1807 return self._manifestlog.get(dir, node).read() | 1819 return self._manifestlog.get(dir, node).read() |
1808 return self._storage().add(self._treemanifest, transaction, link, | 1820 return self._storage().add(self._treemanifest, transaction, link, |
1809 p1, p2, added, removed, readtree=readtree) | 1821 p1, p2, added, removed, readtree=readtree, |
1822 match=match) | |
1810 | 1823 |
1811 @interfaceutil.implementer(repository.imanifestrevisionstored) | 1824 @interfaceutil.implementer(repository.imanifestrevisionstored) |
1812 class treemanifestctx(object): | 1825 class treemanifestctx(object): |
1813 def __init__(self, manifestlog, dir, node): | 1826 def __init__(self, manifestlog, dir, node): |
1814 self._manifestlog = manifestlog | 1827 self._manifestlog = manifestlog |