##// END OF EJS Templates
manifest: persist the manifestfulltext cache...
manifest: persist the manifestfulltext cache Reconstructing the manifest from the revlog takes time, so much so that there already is a LRU cache to avoid having to load a manifest multiple times. This patch persists that LRU cache in the .hg/cache directory, so we can re-use this cache across hg commands. Commit benchmark (run on Macos 10.13 on a 2017-model Macbook Pro with Core i7 2.9GHz and flash drive), testing without and with patch run 5 times, baseline is r2a227782e754: * committing to an existing file, against the mozilla-central repository. Baseline real time average 1.9692, with patch 1.3786. A new debugcommand "hg debugmanifestfulltextcache" lets you inspect the cache, clear it, or add specific manifest nodeids to it. When calling repo.updatecaches(), the manifest(s) for the working copy parents are added to the cache. The hg perfmanifest command has an additional --clear-disk switch to clear this cache when testing manifest loading performance. Using this command to test performance on the firefox repository for revision f947d902ed91, whose manifest has a delta chain length of 60540, we see: $ hg perfmanifest f947d902ed91 --clear-disk ! wall 0.972253 comb 0.970000 user 0.850000 sys 0.120000 (best of 10) $ hg debugmanifestfulltextcache -a `hg log --debug -r f947d902ed91 | grep manifest | cut -d: -f3` Cache contains 1 manifest entries, in order of most to least recent: id: 0294517df4aad07c70701db43bc7ff24c3ce7dbc, size 25.6 MB Total cache data size 25.6 MB, on-disk 0 bytes $ hg perfmanifest f947d902ed91 ! wall 0.036748 comb 0.040000 user 0.020000 sys 0.020000 (best of 100) Worst-case scenario: a manifest text loaded from a single delta; in the firefox repository manifest node 9a1246ff762e is the chain base for the manifest attached to revision f947d902ed91. Loading this from a full cache file is just as fast as without the cache; the extra node ids ensure a big full cache: $ for node in 9a1246ff762e 1a1922c14a3e 54a31d11a36a 0294517df4aa; do > hgd debugmanifestfulltextcache -a $node > /dev/null > done $ hgd perfmanifest -m 9a1246ff762e ! wall 0.077513 comb 0.080000 user 0.030000 sys 0.050000 (best of 100) $ hgd perfmanifest -m 9a1246ff762e --clear-disk ! wall 0.078547 comb 0.080000 user 0.070000 sys 0.010000 (best of 100)

File last commit:

r36209:80301c90 default
r38803:0a57945a default
Show More
base85.py
80 lines | 2.0 KiB | text/x-python | PythonLexer
Brendan Cully
Pure python base85 fallback...
r7701 # base85.py: pure python base85 codec
#
# Copyright (C) 2009 Brendan Cully <brendan@kublai.com>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Brendan Cully
Pure python base85 fallback...
r7701
Gregory Szorc
base85: use absolute_import
r27334 from __future__ import absolute_import
Brendan Cully
Pure python base85 fallback...
r7701 import struct
Pulkit Goyal
py3: use pycompat.bytestr to convert _b85chars to bytes...
r35962 from .. import pycompat
_b85chars = pycompat.bytestr("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
"ghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~")
Mads Kiilerich
Optimization of pure.base85.b85encode...
r7835 _b85chars2 = [(a + b) for a in _b85chars for b in _b85chars]
Brendan Cully
Pure python base85 fallback...
r7701 _b85dec = {}
def _mkb85dec():
Martin Geisler
replace "i in range(len(xs))" with "i, x in enumerate(xs)"...
r8632 for i, c in enumerate(_b85chars):
_b85dec[c] = i
Brendan Cully
Pure python base85 fallback...
r7701
def b85encode(text, pad=False):
"""encode text in base85 format"""
l = len(text)
r = l % 4
if r:
text += '\0' * (4 - r)
longs = len(text) >> 2
words = struct.unpack('>%dL' % (longs), text)
Alejandro Santos
compat: use // for integer division
r9029 out = ''.join(_b85chars[(word // 52200625) % 85] +
_b85chars2[(word // 7225) % 7225] +
Mads Kiilerich
Optimization of pure.base85.b85encode...
r7835 _b85chars2[word % 7225]
for word in words)
Brendan Cully
Pure python base85 fallback...
r7701
if pad:
return out
# Trim padding
olen = l % 4
if olen:
olen += 1
Alejandro Santos
compat: use // for integer division
r9029 olen += l // 4 * 5
Brendan Cully
Pure python base85 fallback...
r7701 return out[:olen]
def b85decode(text):
"""decode base85-encoded text"""
if not _b85dec:
_mkb85dec()
l = len(text)
out = []
for i in range(0, len(text), 5):
Matt Mackall
many, many trivial check-code fixups
r10282 chunk = text[i:i + 5]
Pulkit Goyal
py3: converts bytes to pycompat.bytestr to get bytechrs while enumerating...
r36209 chunk = pycompat.bytestr(chunk)
Brendan Cully
Pure python base85 fallback...
r7701 acc = 0
Martin Geisler
replace "i in range(len(xs))" with "i, x in enumerate(xs)"...
r8632 for j, c in enumerate(chunk):
Brendan Cully
Pure python base85 fallback...
r7701 try:
Martin Geisler
replace "i in range(len(xs))" with "i, x in enumerate(xs)"...
r8632 acc = acc * 85 + _b85dec[c]
Brendan Cully
Pure python base85 fallback...
r7701 except KeyError:
Patrick Mezard
pure/base85: align exception type/msg on base85.c...
r16598 raise ValueError('bad base85 character at position %d'
% (i + j))
Brendan Cully
Pure python base85 fallback...
r7701 if acc > 4294967295:
Patrick Mezard
pure/base85: align exception type/msg on base85.c...
r16598 raise ValueError('Base85 overflow in hunk starting at byte %d' % i)
Brendan Cully
Pure python base85 fallback...
r7701 out.append(acc)
# Pad final chunk if necessary
cl = l % 5
if cl:
acc *= 85 ** (5 - cl)
if cl > 1:
acc += 0xffffff >> (cl - 2) * 8
out[-1] = acc
out = struct.pack('>%dL' % (len(out)), *out)
if cl:
out = out[:-(5 - cl)]
return out