mirror of
https://github.com/facebook/sapling.git
synced 2024-10-06 06:47:41 +03:00
contrib: remove revlog related perf tests
Summary: Those tests are going to break with the latest changelog. We're moving away from revlog so let's just remove the tests. Reviewed By: DurhamG Differential Revision: D22657198 fbshipit-source-id: 6d1540050d70c58636577fa3325daca511273a2b
This commit is contained in:
parent
fad9d569cb
commit
3acb04ea22
@ -674,43 +674,6 @@ def perfbundleread(ui, repo, bundlepath, **opts):
|
||||
fm.end()
|
||||
|
||||
|
||||
@command(
|
||||
"perfchangegroupchangelog",
|
||||
formatteropts
|
||||
+ [
|
||||
("", "version", "02", "changegroup version"),
|
||||
("r", "rev", "", "revisions to add to changegroup"),
|
||||
],
|
||||
)
|
||||
def perfchangegroupchangelog(ui, repo, version="02", rev=None, **opts):
|
||||
"""Benchmark producing a changelog group for a changegroup.
|
||||
|
||||
This measures the time spent processing the changelog during a
|
||||
bundle operation. This occurs during `hg bundle` and on a server
|
||||
processing a `getbundle` wire protocol request (handles clones
|
||||
and pull requests).
|
||||
|
||||
By default, all revisions are added to the changegroup.
|
||||
"""
|
||||
cl = repo.changelog
|
||||
revs = [cl.lookup(r) for r in repo.revs(rev or "all()")]
|
||||
bundler = changegroup.getbundler(version, repo)
|
||||
|
||||
def lookup(node):
|
||||
# The real bundler reads the revision in order to access the
|
||||
# manifest node and files list. Do that here.
|
||||
cl.read(node)
|
||||
return node
|
||||
|
||||
def d():
|
||||
for chunk in bundler.group(revs, cl, lookup):
|
||||
pass
|
||||
|
||||
timer, fm = gettimer(ui, opts)
|
||||
timer(d)
|
||||
fm.end()
|
||||
|
||||
|
||||
@command("perfdirs", formatteropts)
|
||||
def perfdirs(ui, repo, **opts):
|
||||
timer, fm = gettimer(ui, opts)
|
||||
@ -1073,71 +1036,6 @@ def perffncacheencode(ui, repo, **opts):
|
||||
fm.end()
|
||||
|
||||
|
||||
@command(
|
||||
"perfbdiff",
|
||||
revlogopts
|
||||
+ formatteropts
|
||||
+ [
|
||||
("", "count", 1, "number of revisions to test (when using --startrev)"),
|
||||
("", "alldata", False, "test bdiffs for all associated revisions"),
|
||||
],
|
||||
"-c|-m|FILE REV",
|
||||
)
|
||||
def perfbdiff(ui, repo, file_, rev=None, count=None, **opts):
|
||||
"""benchmark a bdiff between revisions
|
||||
|
||||
By default, benchmark a bdiff between its delta parent and itself.
|
||||
|
||||
With ``--count``, benchmark bdiffs between delta parents and self for N
|
||||
revisions starting at the specified revision.
|
||||
|
||||
With ``--alldata``, assume the requested revision is a changeset and
|
||||
measure bdiffs for all changes related to that changeset (manifest
|
||||
and filelogs).
|
||||
"""
|
||||
if opts["alldata"]:
|
||||
opts["changelog"] = True
|
||||
|
||||
if opts.get("changelog") or opts.get("manifest"):
|
||||
file_, rev = None, file_
|
||||
elif rev is None:
|
||||
raise error.CommandError("perfbdiff", "invalid arguments")
|
||||
|
||||
textpairs = []
|
||||
|
||||
r = cmdutil.openrevlog(repo, "perfbdiff", file_, opts)
|
||||
|
||||
startrev = r.rev(r.lookup(rev))
|
||||
for rev in range(startrev, min(startrev + count, len(r) - 1)):
|
||||
if opts["alldata"]:
|
||||
# Load revisions associated with changeset.
|
||||
ctx = repo[rev]
|
||||
mtext = repo.manifestlog._revlog.revision(ctx.manifestnode())
|
||||
for pctx in ctx.parents():
|
||||
pman = repo.manifestlog._revlog.revision(pctx.manifestnode())
|
||||
textpairs.append((pman, mtext))
|
||||
|
||||
# Load filelog revisions by iterating manifest delta.
|
||||
man = ctx.manifest()
|
||||
pman = ctx.p1().manifest()
|
||||
for filename, change in pman.diff(man).items():
|
||||
fctx = repo.file(filename)
|
||||
f1 = fctx.revision(change[0][0] or -1)
|
||||
f2 = fctx.revision(change[1][0] or -1)
|
||||
textpairs.append((f1, f2))
|
||||
else:
|
||||
dp = r.deltaparent(rev)
|
||||
textpairs.append((r.revision(dp), r.revision(rev)))
|
||||
|
||||
def d():
|
||||
for pair in textpairs:
|
||||
mdiff.textdiff(*pair)
|
||||
|
||||
timer, fm = gettimer(ui, opts)
|
||||
timer(d)
|
||||
fm.end()
|
||||
|
||||
|
||||
@command("perfdiffwd", formatteropts)
|
||||
def perfdiffwd(ui, repo, **opts):
|
||||
"""Profile diff of working directory changes"""
|
||||
@ -1161,396 +1059,6 @@ def perfdiffwd(ui, repo, **opts):
|
||||
fm.end()
|
||||
|
||||
|
||||
@command("perfrevlogindex", revlogopts + formatteropts, "-c|-m|FILE")
|
||||
def perfrevlogindex(ui, repo, file_=None, **opts):
|
||||
"""Benchmark operations against a revlog index.
|
||||
|
||||
This tests constructing a revlog instance, reading index data,
|
||||
parsing index data, and performing various operations related to
|
||||
index data.
|
||||
"""
|
||||
|
||||
rl = cmdutil.openrevlog(repo, "perfrevlogindex", file_, opts)
|
||||
|
||||
opener = getattr(rl, "opener") # trick linter
|
||||
indexfile = rl.indexfile
|
||||
data = opener.read(indexfile)
|
||||
|
||||
header = struct.unpack(">I", data[0:4])[0]
|
||||
version = header & 0xFFFF
|
||||
if version == 1:
|
||||
revlogio = revlog.revlogio()
|
||||
inline = header & (1 << 16)
|
||||
else:
|
||||
raise error.Abort(("unsupported revlog version: %d") % version)
|
||||
|
||||
rllen = len(rl)
|
||||
|
||||
node0 = rl.node(0)
|
||||
node25 = rl.node(rllen // 4)
|
||||
node50 = rl.node(rllen // 2)
|
||||
node75 = rl.node(rllen // 4 * 3)
|
||||
node100 = rl.node(rllen - 1)
|
||||
|
||||
allrevs = range(rllen)
|
||||
allrevsrev = list(reversed(allrevs))
|
||||
allnodes = [rl.node(rev) for rev in range(rllen)]
|
||||
allnodesrev = list(reversed(allnodes))
|
||||
|
||||
def constructor():
|
||||
revlog.revlog(opener, indexfile)
|
||||
|
||||
def read():
|
||||
with opener(indexfile) as fh:
|
||||
fh.read()
|
||||
|
||||
def parseindex():
|
||||
revlogio.parseindex(data, inline)
|
||||
|
||||
def getentry(revornode):
|
||||
index = revlogio.parseindex(data, inline)[0]
|
||||
index[revornode]
|
||||
|
||||
def getentries(revs, count=1):
|
||||
index = revlogio.parseindex(data, inline)[0]
|
||||
|
||||
for i in range(count):
|
||||
for rev in revs:
|
||||
index[rev]
|
||||
|
||||
def resolvenode(node):
|
||||
nodemap = revlogio.parseindex(data, inline)[1]
|
||||
# This only works for the C code.
|
||||
if nodemap is None:
|
||||
return
|
||||
|
||||
try:
|
||||
nodemap[node]
|
||||
except error.RevlogError:
|
||||
pass
|
||||
|
||||
def resolvenodes(nodes, count=1):
|
||||
nodemap = revlogio.parseindex(data, inline)[1]
|
||||
if nodemap is None:
|
||||
return
|
||||
|
||||
for i in range(count):
|
||||
for node in nodes:
|
||||
try:
|
||||
nodemap[node]
|
||||
except error.RevlogError:
|
||||
pass
|
||||
|
||||
benches = [
|
||||
(constructor, "revlog constructor"),
|
||||
(read, "read"),
|
||||
(parseindex, "create index object"),
|
||||
(lambda: getentry(0), "retrieve index entry for rev 0"),
|
||||
(lambda: resolvenode("a" * 20), "look up missing node"),
|
||||
(lambda: resolvenode(node0), "look up node at rev 0"),
|
||||
(lambda: resolvenode(node25), "look up node at 1/4 len"),
|
||||
(lambda: resolvenode(node50), "look up node at 1/2 len"),
|
||||
(lambda: resolvenode(node75), "look up node at 3/4 len"),
|
||||
(lambda: resolvenode(node100), "look up node at tip"),
|
||||
# 2x variation is to measure caching impact.
|
||||
(lambda: resolvenodes(allnodes), "look up all nodes (forward)"),
|
||||
(lambda: resolvenodes(allnodes, 2), "look up all nodes 2x (forward)"),
|
||||
(lambda: resolvenodes(allnodesrev), "look up all nodes (reverse)"),
|
||||
(lambda: resolvenodes(allnodesrev, 2), "look up all nodes 2x (reverse)"),
|
||||
(lambda: getentries(allrevs), "retrieve all index entries (forward)"),
|
||||
(lambda: getentries(allrevs, 2), "retrieve all index entries 2x (forward)"),
|
||||
(lambda: getentries(allrevsrev), "retrieve all index entries (reverse)"),
|
||||
(lambda: getentries(allrevsrev, 2), "retrieve all index entries 2x (reverse)"),
|
||||
]
|
||||
|
||||
for fn, title in benches:
|
||||
timer, fm = gettimer(ui, opts)
|
||||
timer(fn, title=title)
|
||||
fm.end()
|
||||
|
||||
|
||||
@command(
|
||||
"perfrevlogrevisions",
|
||||
revlogopts
|
||||
+ formatteropts
|
||||
+ [
|
||||
("d", "dist", 100, "distance between the revisions"),
|
||||
("s", "startrev", 0, "revision to start reading at"),
|
||||
("", "reverse", False, "read in reverse"),
|
||||
],
|
||||
"-c|-m|FILE",
|
||||
)
|
||||
def perfrevlogrevisions(ui, repo, file_=None, startrev=0, reverse=False, **opts):
|
||||
"""Benchmark reading a series of revisions from a revlog.
|
||||
|
||||
By default, we read every ``-d/--dist`` revision from 0 to tip of
|
||||
the specified revlog.
|
||||
|
||||
The start revision can be defined via ``-s/--startrev``.
|
||||
"""
|
||||
rl = cmdutil.openrevlog(repo, "perfrevlogrevisions", file_, opts)
|
||||
rllen = getlen(ui)(rl)
|
||||
|
||||
def d():
|
||||
rl.clearcaches()
|
||||
|
||||
beginrev = startrev
|
||||
endrev = rllen
|
||||
dist = opts["dist"]
|
||||
|
||||
if reverse:
|
||||
beginrev, endrev = endrev, beginrev
|
||||
dist = -1 * dist
|
||||
|
||||
for x in xrange(beginrev, endrev, dist):
|
||||
# Old revisions don't support passing int.
|
||||
n = rl.node(x)
|
||||
rl.revision(n)
|
||||
|
||||
timer, fm = gettimer(ui, opts)
|
||||
timer(d)
|
||||
fm.end()
|
||||
|
||||
|
||||
@command(
|
||||
"perfrevlogchunks",
|
||||
revlogopts
|
||||
+ formatteropts
|
||||
+ [
|
||||
("e", "engines", "", "compression engines to use"),
|
||||
("s", "startrev", 0, "revision to start at"),
|
||||
],
|
||||
"-c|-m|FILE",
|
||||
)
|
||||
def perfrevlogchunks(ui, repo, file_=None, engines=None, startrev=0, **opts):
|
||||
"""Benchmark operations on revlog chunks.
|
||||
|
||||
Logically, each revlog is a collection of fulltext revisions. However,
|
||||
stored within each revlog are "chunks" of possibly compressed data. This
|
||||
data needs to be read and decompressed or compressed and written.
|
||||
|
||||
This command measures the time it takes to read+decompress and recompress
|
||||
chunks in a revlog. It effectively isolates I/O and compression performance.
|
||||
For measurements of higher-level operations like resolving revisions,
|
||||
see ``perfrevlogrevisions`` and ``perfrevlogrevision``.
|
||||
"""
|
||||
rl = cmdutil.openrevlog(repo, "perfrevlogchunks", file_, opts)
|
||||
|
||||
# _chunkraw was renamed to _getsegmentforrevs.
|
||||
try:
|
||||
segmentforrevs = rl._getsegmentforrevs
|
||||
except AttributeError:
|
||||
segmentforrevs = rl._chunkraw
|
||||
|
||||
# Verify engines argument.
|
||||
if engines:
|
||||
engines = set(e.strip() for e in engines.split(","))
|
||||
for engine in engines:
|
||||
try:
|
||||
util.compressionengines[engine]
|
||||
except KeyError:
|
||||
raise error.Abort("unknown compression engine: %s" % engine)
|
||||
else:
|
||||
engines = []
|
||||
for e in util.compengines:
|
||||
engine = util.compengines[e]
|
||||
try:
|
||||
if engine.available():
|
||||
engine.revlogcompressor().compress("dummy")
|
||||
engines.append(e)
|
||||
except NotImplementedError:
|
||||
pass
|
||||
|
||||
revs = list(rl.revs(startrev, len(rl) - 1))
|
||||
|
||||
def rlfh(rl):
|
||||
if rl._inline:
|
||||
return getsvfs(repo)(rl.indexfile)
|
||||
else:
|
||||
return getsvfs(repo)(rl.datafile)
|
||||
|
||||
def doread():
|
||||
rl.clearcaches()
|
||||
for rev in revs:
|
||||
segmentforrevs(rev, rev)
|
||||
|
||||
def doreadcachedfh():
|
||||
rl.clearcaches()
|
||||
fh = rlfh(rl)
|
||||
for rev in revs:
|
||||
segmentforrevs(rev, rev, df=fh)
|
||||
|
||||
def doreadbatch():
|
||||
rl.clearcaches()
|
||||
segmentforrevs(revs[0], revs[-1])
|
||||
|
||||
def doreadbatchcachedfh():
|
||||
rl.clearcaches()
|
||||
fh = rlfh(rl)
|
||||
segmentforrevs(revs[0], revs[-1], df=fh)
|
||||
|
||||
def dochunk():
|
||||
rl.clearcaches()
|
||||
fh = rlfh(rl)
|
||||
for rev in revs:
|
||||
rl._chunk(rev, df=fh)
|
||||
|
||||
chunks = [None]
|
||||
|
||||
def dochunkbatch():
|
||||
rl.clearcaches()
|
||||
fh = rlfh(rl)
|
||||
# Save chunks as a side-effect.
|
||||
chunks[0] = rl._chunks(revs, df=fh)
|
||||
|
||||
def docompress(compressor):
|
||||
rl.clearcaches()
|
||||
|
||||
try:
|
||||
# Swap in the requested compression engine.
|
||||
oldcompressor = rl._compressor
|
||||
rl._compressor = compressor
|
||||
for chunk in chunks[0]:
|
||||
rl.compress(chunk)
|
||||
finally:
|
||||
rl._compressor = oldcompressor
|
||||
|
||||
benches = [
|
||||
(lambda: doread(), "read"),
|
||||
(lambda: doreadcachedfh(), "read w/ reused fd"),
|
||||
(lambda: doreadbatch(), "read batch"),
|
||||
(lambda: doreadbatchcachedfh(), "read batch w/ reused fd"),
|
||||
(lambda: dochunk(), "chunk"),
|
||||
(lambda: dochunkbatch(), "chunk batch"),
|
||||
]
|
||||
|
||||
for engine in sorted(engines):
|
||||
compressor = util.compengines[engine].revlogcompressor()
|
||||
benches.append(
|
||||
(functools.partial(docompress, compressor), "compress w/ %s" % engine)
|
||||
)
|
||||
|
||||
for fn, title in benches:
|
||||
timer, fm = gettimer(ui, opts)
|
||||
timer(fn, title=title)
|
||||
fm.end()
|
||||
|
||||
|
||||
@command(
|
||||
"perfrevlogrevision",
|
||||
revlogopts
|
||||
+ formatteropts
|
||||
+ [("", "cache", False, "use caches instead of clearing")],
|
||||
"-c|-m|FILE REV",
|
||||
)
|
||||
def perfrevlogrevision(ui, repo, file_, rev=None, cache=None, **opts):
|
||||
"""Benchmark obtaining a revlog revision.
|
||||
|
||||
Obtaining a revlog revision consists of roughly the following steps:
|
||||
|
||||
1. Compute the delta chain
|
||||
2. Obtain the raw chunks for that delta chain
|
||||
3. Decompress each raw chunk
|
||||
4. Apply binary patches to obtain fulltext
|
||||
5. Verify hash of fulltext
|
||||
|
||||
This command measures the time spent in each of these phases.
|
||||
"""
|
||||
if opts.get("changelog") or opts.get("manifest"):
|
||||
file_, rev = None, file_
|
||||
elif rev is None:
|
||||
raise error.CommandError("perfrevlogrevision", "invalid arguments")
|
||||
|
||||
r = cmdutil.openrevlog(repo, "perfrevlogrevision", file_, opts)
|
||||
|
||||
# _chunkraw was renamed to _getsegmentforrevs.
|
||||
try:
|
||||
segmentforrevs = r._getsegmentforrevs
|
||||
except AttributeError:
|
||||
segmentforrevs = r._chunkraw
|
||||
|
||||
node = r.lookup(rev)
|
||||
rev = r.rev(node)
|
||||
|
||||
def getrawchunks(data, chain):
|
||||
start = r.start
|
||||
length = r.length
|
||||
inline = r._inline
|
||||
iosize = r._io.size
|
||||
buffer = util.buffer
|
||||
offset = start(chain[0])
|
||||
|
||||
chunks = []
|
||||
ladd = chunks.append
|
||||
|
||||
for rev in chain:
|
||||
chunkstart = start(rev)
|
||||
if inline:
|
||||
chunkstart += (rev + 1) * iosize
|
||||
chunklength = length(rev)
|
||||
ladd(buffer(data, chunkstart - offset, chunklength))
|
||||
|
||||
return chunks
|
||||
|
||||
def dodeltachain(rev):
|
||||
if not cache:
|
||||
r.clearcaches()
|
||||
r._deltachain(rev)
|
||||
|
||||
def doread(chain):
|
||||
if not cache:
|
||||
r.clearcaches()
|
||||
segmentforrevs(chain[0], chain[-1])
|
||||
|
||||
def dorawchunks(data, chain):
|
||||
if not cache:
|
||||
r.clearcaches()
|
||||
getrawchunks(data, chain)
|
||||
|
||||
def dodecompress(chunks):
|
||||
decomp = r.decompress
|
||||
for chunk in chunks:
|
||||
decomp(chunk)
|
||||
|
||||
def dopatch(text, bins):
|
||||
if not cache:
|
||||
r.clearcaches()
|
||||
mdiff.patches(text, bins)
|
||||
|
||||
def dohash(text):
|
||||
if not cache:
|
||||
r.clearcaches()
|
||||
r.checkhash(text, node, rev=rev)
|
||||
|
||||
def dorevision():
|
||||
if not cache:
|
||||
r.clearcaches()
|
||||
r.revision(node)
|
||||
|
||||
chain = r._deltachain(rev)[0]
|
||||
data = segmentforrevs(chain[0], chain[-1])[1]
|
||||
rawchunks = getrawchunks(data, chain)
|
||||
bins = r._chunks(chain)
|
||||
text = str(bins[0])
|
||||
bins = bins[1:]
|
||||
text = mdiff.patches(text, bins)
|
||||
|
||||
benches = [
|
||||
(lambda: dorevision(), "full"),
|
||||
(lambda: dodeltachain(rev), "deltachain"),
|
||||
(lambda: doread(chain), "read"),
|
||||
(lambda: dorawchunks(data, chain), "rawchunks"),
|
||||
(lambda: dodecompress(rawchunks), "decompress"),
|
||||
(lambda: dopatch(text, bins), "patch"),
|
||||
(lambda: dohash(text), "hash"),
|
||||
]
|
||||
|
||||
for fn, title in benches:
|
||||
timer, fm = gettimer(ui, opts)
|
||||
timer(fn, title=title)
|
||||
fm.end()
|
||||
|
||||
|
||||
@command(
|
||||
"perfrevset",
|
||||
[
|
||||
|
@ -45,11 +45,8 @@ perfstatus
|
||||
$ hg perfancestors
|
||||
$ hg perfancestorset 2
|
||||
$ hg perfannotate a
|
||||
$ hg perfbdiff -c 1
|
||||
$ hg perfbdiff --alldata 1
|
||||
$ hg perfbookmarks
|
||||
$ hg perfcca
|
||||
$ hg perfchangegroupchangelog
|
||||
$ hg perfchangeset 2
|
||||
$ hg perfctxfiles 2
|
||||
$ hg perfdiffwd
|
||||
@ -72,10 +69,6 @@ perfstatus
|
||||
$ hg perfnodelookup 2
|
||||
$ hg perfpathcopies 1 2
|
||||
$ hg perfrawfiles 2
|
||||
$ hg perfrevlogindex -c
|
||||
$ hg perfrevlogrevisions .hg/store/data/a.i
|
||||
$ hg perfrevlogrevision -m 0
|
||||
$ hg perfrevlogchunks -c
|
||||
$ hg perfrevrange
|
||||
$ hg perfrevset 'all()'
|
||||
$ hg perfstartup
|
||||
|
Loading…
Reference in New Issue
Block a user