##// END OF EJS Templates
perf: add perfrevlogrevision...
Gregory Szorc -
r27470:d394a1a3 default
parent child Browse files
Show More
@@ -1,684 +1,776
1 1 # perf.py - performance test routines
2 2 '''helper extension to measure performance'''
3 3
4 4 from mercurial import cmdutil, scmutil, util, commands, obsolete
5 from mercurial import repoview, branchmap, merge, copies, error
5 from mercurial import repoview, branchmap, merge, copies, error, revlog
6 from mercurial import mdiff
6 7 import time, os, sys
7 8 import random
8 9 import functools
9 10
10 11 formatteropts = commands.formatteropts
12 revlogopts = commands.debugrevlogopts
11 13
12 14 cmdtable = {}
13 15 command = cmdutil.command(cmdtable)
14 16
15 17 def getlen(ui):
16 18 if ui.configbool("perf", "stub"):
17 19 return lambda x: 1
18 20 return len
19 21
20 22 def gettimer(ui, opts=None):
21 23 """return a timer function and formatter: (timer, formatter)
22 24
23 25 This function exists to gather the creation of formatter in a single
24 26 place instead of duplicating it in all performance commands."""
25 27
26 28 # enforce an idle period before execution to counteract power management
27 29 # experimental config: perf.presleep
28 30 time.sleep(ui.configint("perf", "presleep", 1))
29 31
30 32 if opts is None:
31 33 opts = {}
32 34 # redirect all to stderr
33 35 ui = ui.copy()
34 36 ui.fout = ui.ferr
35 37 # get a formatter
36 38 fm = ui.formatter('perf', opts)
37 39 # stub function, runs code only once instead of in a loop
38 40 # experimental config: perf.stub
39 41 if ui.configbool("perf", "stub"):
40 42 return functools.partial(stub_timer, fm), fm
41 43 return functools.partial(_timer, fm), fm
42 44
43 45 def stub_timer(fm, func, title=None):
44 46 func()
45 47
46 48 def _timer(fm, func, title=None):
47 49 results = []
48 50 begin = time.time()
49 51 count = 0
50 52 while True:
51 53 ostart = os.times()
52 54 cstart = time.time()
53 55 r = func()
54 56 cstop = time.time()
55 57 ostop = os.times()
56 58 count += 1
57 59 a, b = ostart, ostop
58 60 results.append((cstop - cstart, b[0] - a[0], b[1]-a[1]))
59 61 if cstop - begin > 3 and count >= 100:
60 62 break
61 63 if cstop - begin > 10 and count >= 3:
62 64 break
63 65
64 66 fm.startitem()
65 67
66 68 if title:
67 69 fm.write('title', '! %s\n', title)
68 70 if r:
69 71 fm.write('result', '! result: %s\n', r)
70 72 m = min(results)
71 73 fm.plain('!')
72 74 fm.write('wall', ' wall %f', m[0])
73 75 fm.write('comb', ' comb %f', m[1] + m[2])
74 76 fm.write('user', ' user %f', m[1])
75 77 fm.write('sys', ' sys %f', m[2])
76 78 fm.write('count', ' (best of %d)', count)
77 79 fm.plain('\n')
78 80
79 81 @command('perfwalk', formatteropts)
80 82 def perfwalk(ui, repo, *pats, **opts):
81 83 timer, fm = gettimer(ui, opts)
82 84 try:
83 85 m = scmutil.match(repo[None], pats, {})
84 86 timer(lambda: len(list(repo.dirstate.walk(m, [], True, False))))
85 87 except Exception:
86 88 try:
87 89 m = scmutil.match(repo[None], pats, {})
88 90 timer(lambda: len([b for a, b, c in repo.dirstate.statwalk([], m)]))
89 91 except Exception:
90 92 timer(lambda: len(list(cmdutil.walk(repo, pats, {}))))
91 93 fm.end()
92 94
93 95 @command('perfannotate', formatteropts)
94 96 def perfannotate(ui, repo, f, **opts):
95 97 timer, fm = gettimer(ui, opts)
96 98 fc = repo['.'][f]
97 99 timer(lambda: len(fc.annotate(True)))
98 100 fm.end()
99 101
100 102 @command('perfstatus',
101 103 [('u', 'unknown', False,
102 104 'ask status to look for unknown files')] + formatteropts)
103 105 def perfstatus(ui, repo, **opts):
104 106 #m = match.always(repo.root, repo.getcwd())
105 107 #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False,
106 108 # False))))
107 109 timer, fm = gettimer(ui, opts)
108 110 timer(lambda: sum(map(len, repo.status(unknown=opts['unknown']))))
109 111 fm.end()
110 112
111 113 @command('perfaddremove', formatteropts)
112 114 def perfaddremove(ui, repo, **opts):
113 115 timer, fm = gettimer(ui, opts)
114 116 try:
115 117 oldquiet = repo.ui.quiet
116 118 repo.ui.quiet = True
117 119 matcher = scmutil.match(repo[None])
118 120 timer(lambda: scmutil.addremove(repo, matcher, "", dry_run=True))
119 121 finally:
120 122 repo.ui.quiet = oldquiet
121 123 fm.end()
122 124
123 125 def clearcaches(cl):
124 126 # behave somewhat consistently across internal API changes
125 127 if util.safehasattr(cl, 'clearcaches'):
126 128 cl.clearcaches()
127 129 elif util.safehasattr(cl, '_nodecache'):
128 130 from mercurial.node import nullid, nullrev
129 131 cl._nodecache = {nullid: nullrev}
130 132 cl._nodepos = None
131 133
132 134 @command('perfheads', formatteropts)
133 135 def perfheads(ui, repo, **opts):
134 136 timer, fm = gettimer(ui, opts)
135 137 cl = repo.changelog
136 138 def d():
137 139 len(cl.headrevs())
138 140 clearcaches(cl)
139 141 timer(d)
140 142 fm.end()
141 143
142 144 @command('perftags', formatteropts)
143 145 def perftags(ui, repo, **opts):
144 146 import mercurial.changelog
145 147 import mercurial.manifest
146 148 timer, fm = gettimer(ui, opts)
147 149 def t():
148 150 repo.changelog = mercurial.changelog.changelog(repo.svfs)
149 151 repo.manifest = mercurial.manifest.manifest(repo.svfs)
150 152 repo._tags = None
151 153 return len(repo.tags())
152 154 timer(t)
153 155 fm.end()
154 156
155 157 @command('perfancestors', formatteropts)
156 158 def perfancestors(ui, repo, **opts):
157 159 timer, fm = gettimer(ui, opts)
158 160 heads = repo.changelog.headrevs()
159 161 def d():
160 162 for a in repo.changelog.ancestors(heads):
161 163 pass
162 164 timer(d)
163 165 fm.end()
164 166
165 167 @command('perfancestorset', formatteropts)
166 168 def perfancestorset(ui, repo, revset, **opts):
167 169 timer, fm = gettimer(ui, opts)
168 170 revs = repo.revs(revset)
169 171 heads = repo.changelog.headrevs()
170 172 def d():
171 173 s = repo.changelog.ancestors(heads)
172 174 for rev in revs:
173 175 rev in s
174 176 timer(d)
175 177 fm.end()
176 178
177 179 @command('perfdirs', formatteropts)
178 180 def perfdirs(ui, repo, **opts):
179 181 timer, fm = gettimer(ui, opts)
180 182 dirstate = repo.dirstate
181 183 'a' in dirstate
182 184 def d():
183 185 dirstate.dirs()
184 186 del dirstate._dirs
185 187 timer(d)
186 188 fm.end()
187 189
188 190 @command('perfdirstate', formatteropts)
189 191 def perfdirstate(ui, repo, **opts):
190 192 timer, fm = gettimer(ui, opts)
191 193 "a" in repo.dirstate
192 194 def d():
193 195 repo.dirstate.invalidate()
194 196 "a" in repo.dirstate
195 197 timer(d)
196 198 fm.end()
197 199
198 200 @command('perfdirstatedirs', formatteropts)
199 201 def perfdirstatedirs(ui, repo, **opts):
200 202 timer, fm = gettimer(ui, opts)
201 203 "a" in repo.dirstate
202 204 def d():
203 205 "a" in repo.dirstate._dirs
204 206 del repo.dirstate._dirs
205 207 timer(d)
206 208 fm.end()
207 209
208 210 @command('perfdirstatefoldmap', formatteropts)
209 211 def perfdirstatefoldmap(ui, repo, **opts):
210 212 timer, fm = gettimer(ui, opts)
211 213 dirstate = repo.dirstate
212 214 'a' in dirstate
213 215 def d():
214 216 dirstate._filefoldmap.get('a')
215 217 del dirstate._filefoldmap
216 218 timer(d)
217 219 fm.end()
218 220
219 221 @command('perfdirfoldmap', formatteropts)
220 222 def perfdirfoldmap(ui, repo, **opts):
221 223 timer, fm = gettimer(ui, opts)
222 224 dirstate = repo.dirstate
223 225 'a' in dirstate
224 226 def d():
225 227 dirstate._dirfoldmap.get('a')
226 228 del dirstate._dirfoldmap
227 229 del dirstate._dirs
228 230 timer(d)
229 231 fm.end()
230 232
231 233 @command('perfdirstatewrite', formatteropts)
232 234 def perfdirstatewrite(ui, repo, **opts):
233 235 timer, fm = gettimer(ui, opts)
234 236 ds = repo.dirstate
235 237 "a" in ds
236 238 def d():
237 239 ds._dirty = True
238 240 ds.write(repo.currenttransaction())
239 241 timer(d)
240 242 fm.end()
241 243
242 244 @command('perfmergecalculate',
243 245 [('r', 'rev', '.', 'rev to merge against')] + formatteropts)
244 246 def perfmergecalculate(ui, repo, rev, **opts):
245 247 timer, fm = gettimer(ui, opts)
246 248 wctx = repo[None]
247 249 rctx = scmutil.revsingle(repo, rev, rev)
248 250 ancestor = wctx.ancestor(rctx)
249 251 # we don't want working dir files to be stat'd in the benchmark, so prime
250 252 # that cache
251 253 wctx.dirty()
252 254 def d():
253 255 # acceptremote is True because we don't want prompts in the middle of
254 256 # our benchmark
255 257 merge.calculateupdates(repo, wctx, rctx, [ancestor], False, False,
256 258 acceptremote=True, followcopies=True)
257 259 timer(d)
258 260 fm.end()
259 261
260 262 @command('perfpathcopies', [], "REV REV")
261 263 def perfpathcopies(ui, repo, rev1, rev2, **opts):
262 264 timer, fm = gettimer(ui, opts)
263 265 ctx1 = scmutil.revsingle(repo, rev1, rev1)
264 266 ctx2 = scmutil.revsingle(repo, rev2, rev2)
265 267 def d():
266 268 copies.pathcopies(ctx1, ctx2)
267 269 timer(d)
268 270 fm.end()
269 271
270 272 @command('perfmanifest', [], 'REV')
271 273 def perfmanifest(ui, repo, rev, **opts):
272 274 timer, fm = gettimer(ui, opts)
273 275 ctx = scmutil.revsingle(repo, rev, rev)
274 276 t = ctx.manifestnode()
275 277 def d():
276 278 repo.manifest.clearcaches()
277 279 repo.manifest.read(t)
278 280 timer(d)
279 281 fm.end()
280 282
281 283 @command('perfchangeset', formatteropts)
282 284 def perfchangeset(ui, repo, rev, **opts):
283 285 timer, fm = gettimer(ui, opts)
284 286 n = repo[rev].node()
285 287 def d():
286 288 repo.changelog.read(n)
287 289 #repo.changelog._cache = None
288 290 timer(d)
289 291 fm.end()
290 292
291 293 @command('perfindex', formatteropts)
292 294 def perfindex(ui, repo, **opts):
293 295 import mercurial.revlog
294 296 timer, fm = gettimer(ui, opts)
295 297 mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
296 298 n = repo["tip"].node()
297 299 def d():
298 300 cl = mercurial.revlog.revlog(repo.svfs, "00changelog.i")
299 301 cl.rev(n)
300 302 timer(d)
301 303 fm.end()
302 304
303 305 @command('perfstartup', formatteropts)
304 306 def perfstartup(ui, repo, **opts):
305 307 timer, fm = gettimer(ui, opts)
306 308 cmd = sys.argv[0]
307 309 def d():
308 310 if os.name != 'nt':
309 311 os.system("HGRCPATH= %s version -q > /dev/null" % cmd)
310 312 else:
311 313 os.environ['HGRCPATH'] = ''
312 314 os.system("%s version -q > NUL" % cmd)
313 315 timer(d)
314 316 fm.end()
315 317
316 318 @command('perfparents', formatteropts)
317 319 def perfparents(ui, repo, **opts):
318 320 timer, fm = gettimer(ui, opts)
319 321 # control the number of commits perfparents iterates over
320 322 # experimental config: perf.parentscount
321 323 count = ui.configint("perf", "parentscount", 1000)
322 324 if len(repo.changelog) < count:
323 325 raise error.Abort("repo needs %d commits for this test" % count)
324 326 repo = repo.unfiltered()
325 327 nl = [repo.changelog.node(i) for i in xrange(count)]
326 328 def d():
327 329 for n in nl:
328 330 repo.changelog.parents(n)
329 331 timer(d)
330 332 fm.end()
331 333
332 334 @command('perfctxfiles', formatteropts)
333 335 def perfctxfiles(ui, repo, x, **opts):
334 336 x = int(x)
335 337 timer, fm = gettimer(ui, opts)
336 338 def d():
337 339 len(repo[x].files())
338 340 timer(d)
339 341 fm.end()
340 342
341 343 @command('perfrawfiles', formatteropts)
342 344 def perfrawfiles(ui, repo, x, **opts):
343 345 x = int(x)
344 346 timer, fm = gettimer(ui, opts)
345 347 cl = repo.changelog
346 348 def d():
347 349 len(cl.read(x)[3])
348 350 timer(d)
349 351 fm.end()
350 352
351 353 @command('perflookup', formatteropts)
352 354 def perflookup(ui, repo, rev, **opts):
353 355 timer, fm = gettimer(ui, opts)
354 356 timer(lambda: len(repo.lookup(rev)))
355 357 fm.end()
356 358
357 359 @command('perfrevrange', formatteropts)
358 360 def perfrevrange(ui, repo, *specs, **opts):
359 361 timer, fm = gettimer(ui, opts)
360 362 revrange = scmutil.revrange
361 363 timer(lambda: len(revrange(repo, specs)))
362 364 fm.end()
363 365
364 366 @command('perfnodelookup', formatteropts)
365 367 def perfnodelookup(ui, repo, rev, **opts):
366 368 timer, fm = gettimer(ui, opts)
367 369 import mercurial.revlog
368 370 mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
369 371 n = repo[rev].node()
370 372 cl = mercurial.revlog.revlog(repo.svfs, "00changelog.i")
371 373 def d():
372 374 cl.rev(n)
373 375 clearcaches(cl)
374 376 timer(d)
375 377 fm.end()
376 378
377 379 @command('perflog',
378 380 [('', 'rename', False, 'ask log to follow renames')] + formatteropts)
379 381 def perflog(ui, repo, rev=None, **opts):
380 382 if rev is None:
381 383 rev=[]
382 384 timer, fm = gettimer(ui, opts)
383 385 ui.pushbuffer()
384 386 timer(lambda: commands.log(ui, repo, rev=rev, date='', user='',
385 387 copies=opts.get('rename')))
386 388 ui.popbuffer()
387 389 fm.end()
388 390
389 391 @command('perfmoonwalk', formatteropts)
390 392 def perfmoonwalk(ui, repo, **opts):
391 393 """benchmark walking the changelog backwards
392 394
393 395 This also loads the changelog data for each revision in the changelog.
394 396 """
395 397 timer, fm = gettimer(ui, opts)
396 398 def moonwalk():
397 399 for i in xrange(len(repo), -1, -1):
398 400 ctx = repo[i]
399 401 ctx.branch() # read changelog data (in addition to the index)
400 402 timer(moonwalk)
401 403 fm.end()
402 404
403 405 @command('perftemplating', formatteropts)
404 406 def perftemplating(ui, repo, rev=None, **opts):
405 407 if rev is None:
406 408 rev=[]
407 409 timer, fm = gettimer(ui, opts)
408 410 ui.pushbuffer()
409 411 timer(lambda: commands.log(ui, repo, rev=rev, date='', user='',
410 412 template='{date|shortdate} [{rev}:{node|short}]'
411 413 ' {author|person}: {desc|firstline}\n'))
412 414 ui.popbuffer()
413 415 fm.end()
414 416
415 417 @command('perfcca', formatteropts)
416 418 def perfcca(ui, repo, **opts):
417 419 timer, fm = gettimer(ui, opts)
418 420 timer(lambda: scmutil.casecollisionauditor(ui, False, repo.dirstate))
419 421 fm.end()
420 422
421 423 @command('perffncacheload', formatteropts)
422 424 def perffncacheload(ui, repo, **opts):
423 425 timer, fm = gettimer(ui, opts)
424 426 s = repo.store
425 427 def d():
426 428 s.fncache._load()
427 429 timer(d)
428 430 fm.end()
429 431
430 432 @command('perffncachewrite', formatteropts)
431 433 def perffncachewrite(ui, repo, **opts):
432 434 timer, fm = gettimer(ui, opts)
433 435 s = repo.store
434 436 s.fncache._load()
435 437 lock = repo.lock()
436 438 tr = repo.transaction('perffncachewrite')
437 439 def d():
438 440 s.fncache._dirty = True
439 441 s.fncache.write(tr)
440 442 timer(d)
441 443 lock.release()
442 444 fm.end()
443 445
444 446 @command('perffncacheencode', formatteropts)
445 447 def perffncacheencode(ui, repo, **opts):
446 448 timer, fm = gettimer(ui, opts)
447 449 s = repo.store
448 450 s.fncache._load()
449 451 def d():
450 452 for p in s.fncache.entries:
451 453 s.encode(p)
452 454 timer(d)
453 455 fm.end()
454 456
455 457 @command('perfdiffwd', formatteropts)
456 458 def perfdiffwd(ui, repo, **opts):
457 459 """Profile diff of working directory changes"""
458 460 timer, fm = gettimer(ui, opts)
459 461 options = {
460 462 'w': 'ignore_all_space',
461 463 'b': 'ignore_space_change',
462 464 'B': 'ignore_blank_lines',
463 465 }
464 466
465 467 for diffopt in ('', 'w', 'b', 'B', 'wB'):
466 468 opts = dict((options[c], '1') for c in diffopt)
467 469 def d():
468 470 ui.pushbuffer()
469 471 commands.diff(ui, repo, **opts)
470 472 ui.popbuffer()
471 473 title = 'diffopts: %s' % (diffopt and ('-' + diffopt) or 'none')
472 474 timer(d, title)
473 475 fm.end()
474 476
475 477 @command('perfrevlog',
476 478 [('d', 'dist', 100, 'distance between the revisions')] + formatteropts,
477 479 "[INDEXFILE]")
478 480 def perfrevlog(ui, repo, file_, **opts):
479 481 timer, fm = gettimer(ui, opts)
480 482 from mercurial import revlog
481 483 dist = opts['dist']
482 484 _len = getlen(ui)
483 485 def d():
484 486 r = revlog.revlog(lambda fn: open(fn, 'rb'), file_)
485 487 for x in xrange(0, _len(r), dist):
486 488 r.revision(r.node(x))
487 489
488 490 timer(d)
489 491 fm.end()
490 492
493 @command('perfrevlogrevision', revlogopts + formatteropts +
494 [('', 'cache', False, 'use caches instead of clearing')],
495 '-c|-m|FILE REV')
496 def perfrevlogrevision(ui, repo, file_, rev=None, cache=None, **opts):
497 """Benchmark obtaining a revlog revision.
498
499 Obtaining a revlog revision consists of roughly the following steps:
500
501 1. Compute the delta chain
502 2. Obtain the raw chunks for that delta chain
503 3. Decompress each raw chunk
504 4. Apply binary patches to obtain fulltext
505 5. Verify hash of fulltext
506
507 This command measures the time spent in each of these phases.
508 """
509 if opts.get('changelog') or opts.get('manifest'):
510 file_, rev = None, file_
511 elif rev is None:
512 raise error.CommandError('perfrevlogrevision', 'invalid arguments')
513
514 r = cmdutil.openrevlog(repo, 'perfrevlogrevision', file_, opts)
515 node = r.lookup(rev)
516 rev = r.rev(node)
517
518 def dodeltachain(rev):
519 if not cache:
520 r.clearcaches()
521 r._deltachain(rev)
522
523 def doread(chain):
524 if not cache:
525 r.clearcaches()
526 r._chunkraw(chain[0], chain[-1])
527
528 def dodecompress(data, chain):
529 if not cache:
530 r.clearcaches()
531
532 start = r.start
533 length = r.length
534 inline = r._inline
535 iosize = r._io.size
536 buffer = util.buffer
537 offset = start(chain[0])
538
539 for rev in chain:
540 chunkstart = start(rev)
541 if inline:
542 chunkstart += (rev + 1) * iosize
543 chunklength = length(rev)
544 b = buffer(data, chunkstart - offset, chunklength)
545 revlog.decompress(b)
546
547 def dopatch(text, bins):
548 if not cache:
549 r.clearcaches()
550 mdiff.patches(text, bins)
551
552 def dohash(text):
553 if not cache:
554 r.clearcaches()
555 r._checkhash(text, node, rev)
556
557 def dorevision():
558 if not cache:
559 r.clearcaches()
560 r.revision(node)
561
562 chain = r._deltachain(rev)[0]
563 data = r._chunkraw(chain[0], chain[-1])
564 bins = r._chunks(chain)
565 text = str(bins[0])
566 bins = bins[1:]
567 text = mdiff.patches(text, bins)
568
569 benches = [
570 (lambda: dorevision(), 'full'),
571 (lambda: dodeltachain(rev), 'deltachain'),
572 (lambda: doread(chain), 'read'),
573 (lambda: dodecompress(data, chain), 'decompress'),
574 (lambda: dopatch(text, bins), 'patch'),
575 (lambda: dohash(text), 'hash'),
576 ]
577
578 for fn, title in benches:
579 timer, fm = gettimer(ui, opts)
580 timer(fn, title=title)
581 fm.end()
582
491 583 @command('perfrevset',
492 584 [('C', 'clear', False, 'clear volatile cache between each call.'),
493 585 ('', 'contexts', False, 'obtain changectx for each revision')]
494 586 + formatteropts, "REVSET")
495 587 def perfrevset(ui, repo, expr, clear=False, contexts=False, **opts):
496 588 """benchmark the execution time of a revset
497 589
498 590 Use the --clean option if need to evaluate the impact of build volatile
499 591 revisions set cache on the revset execution. Volatile cache hold filtered
500 592 and obsolete related cache."""
501 593 timer, fm = gettimer(ui, opts)
502 594 def d():
503 595 if clear:
504 596 repo.invalidatevolatilesets()
505 597 if contexts:
506 598 for ctx in repo.set(expr): pass
507 599 else:
508 600 for r in repo.revs(expr): pass
509 601 timer(d)
510 602 fm.end()
511 603
512 604 @command('perfvolatilesets', formatteropts)
513 605 def perfvolatilesets(ui, repo, *names, **opts):
514 606 """benchmark the computation of various volatile set
515 607
516 608 Volatile set computes element related to filtering and obsolescence."""
517 609 timer, fm = gettimer(ui, opts)
518 610 repo = repo.unfiltered()
519 611
520 612 def getobs(name):
521 613 def d():
522 614 repo.invalidatevolatilesets()
523 615 obsolete.getrevs(repo, name)
524 616 return d
525 617
526 618 allobs = sorted(obsolete.cachefuncs)
527 619 if names:
528 620 allobs = [n for n in allobs if n in names]
529 621
530 622 for name in allobs:
531 623 timer(getobs(name), title=name)
532 624
533 625 def getfiltered(name):
534 626 def d():
535 627 repo.invalidatevolatilesets()
536 628 repoview.filterrevs(repo, name)
537 629 return d
538 630
539 631 allfilter = sorted(repoview.filtertable)
540 632 if names:
541 633 allfilter = [n for n in allfilter if n in names]
542 634
543 635 for name in allfilter:
544 636 timer(getfiltered(name), title=name)
545 637 fm.end()
546 638
547 639 @command('perfbranchmap',
548 640 [('f', 'full', False,
549 641 'Includes build time of subset'),
550 642 ] + formatteropts)
551 643 def perfbranchmap(ui, repo, full=False, **opts):
552 644 """benchmark the update of a branchmap
553 645
554 646 This benchmarks the full repo.branchmap() call with read and write disabled
555 647 """
556 648 timer, fm = gettimer(ui, opts)
557 649 def getbranchmap(filtername):
558 650 """generate a benchmark function for the filtername"""
559 651 if filtername is None:
560 652 view = repo
561 653 else:
562 654 view = repo.filtered(filtername)
563 655 def d():
564 656 if full:
565 657 view._branchcaches.clear()
566 658 else:
567 659 view._branchcaches.pop(filtername, None)
568 660 view.branchmap()
569 661 return d
570 662 # add filter in smaller subset to bigger subset
571 663 possiblefilters = set(repoview.filtertable)
572 664 allfilters = []
573 665 while possiblefilters:
574 666 for name in possiblefilters:
575 667 subset = branchmap.subsettable.get(name)
576 668 if subset not in possiblefilters:
577 669 break
578 670 else:
579 671 assert False, 'subset cycle %s!' % possiblefilters
580 672 allfilters.append(name)
581 673 possiblefilters.remove(name)
582 674
583 675 # warm the cache
584 676 if not full:
585 677 for name in allfilters:
586 678 repo.filtered(name).branchmap()
587 679 # add unfiltered
588 680 allfilters.append(None)
589 681 oldread = branchmap.read
590 682 oldwrite = branchmap.branchcache.write
591 683 try:
592 684 branchmap.read = lambda repo: None
593 685 branchmap.write = lambda repo: None
594 686 for name in allfilters:
595 687 timer(getbranchmap(name), title=str(name))
596 688 finally:
597 689 branchmap.read = oldread
598 690 branchmap.branchcache.write = oldwrite
599 691 fm.end()
600 692
601 693 @command('perfloadmarkers')
602 694 def perfloadmarkers(ui, repo):
603 695 """benchmark the time to parse the on-disk markers for a repo
604 696
605 697 Result is the number of markers in the repo."""
606 698 timer, fm = gettimer(ui)
607 699 timer(lambda: len(obsolete.obsstore(repo.svfs)))
608 700 fm.end()
609 701
610 702 @command('perflrucachedict', formatteropts +
611 703 [('', 'size', 4, 'size of cache'),
612 704 ('', 'gets', 10000, 'number of key lookups'),
613 705 ('', 'sets', 10000, 'number of key sets'),
614 706 ('', 'mixed', 10000, 'number of mixed mode operations'),
615 707 ('', 'mixedgetfreq', 50, 'frequency of get vs set ops in mixed mode')],
616 708 norepo=True)
617 709 def perflrucache(ui, size=4, gets=10000, sets=10000, mixed=10000,
618 710 mixedgetfreq=50, **opts):
619 711 def doinit():
620 712 for i in xrange(10000):
621 713 util.lrucachedict(size)
622 714
623 715 values = []
624 716 for i in xrange(size):
625 717 values.append(random.randint(0, sys.maxint))
626 718
627 719 # Get mode fills the cache and tests raw lookup performance with no
628 720 # eviction.
629 721 getseq = []
630 722 for i in xrange(gets):
631 723 getseq.append(random.choice(values))
632 724
633 725 def dogets():
634 726 d = util.lrucachedict(size)
635 727 for v in values:
636 728 d[v] = v
637 729 for key in getseq:
638 730 value = d[key]
639 731 value # silence pyflakes warning
640 732
641 733 # Set mode tests insertion speed with cache eviction.
642 734 setseq = []
643 735 for i in xrange(sets):
644 736 setseq.append(random.randint(0, sys.maxint))
645 737
646 738 def dosets():
647 739 d = util.lrucachedict(size)
648 740 for v in setseq:
649 741 d[v] = v
650 742
651 743 # Mixed mode randomly performs gets and sets with eviction.
652 744 mixedops = []
653 745 for i in xrange(mixed):
654 746 r = random.randint(0, 100)
655 747 if r < mixedgetfreq:
656 748 op = 0
657 749 else:
658 750 op = 1
659 751
660 752 mixedops.append((op, random.randint(0, size * 2)))
661 753
662 754 def domixed():
663 755 d = util.lrucachedict(size)
664 756
665 757 for op, v in mixedops:
666 758 if op == 0:
667 759 try:
668 760 d[v]
669 761 except KeyError:
670 762 pass
671 763 else:
672 764 d[v] = v
673 765
674 766 benches = [
675 767 (doinit, 'init'),
676 768 (dogets, 'gets'),
677 769 (dosets, 'sets'),
678 770 (domixed, 'mixed')
679 771 ]
680 772
681 773 for fn, title in benches:
682 774 timer, fm = gettimer(ui, opts)
683 775 timer(fn, title=title)
684 776 fm.end()
@@ -1,148 +1,151
1 1 #require test-repo
2 2
3 3 Set vars:
4 4
5 5 $ CONTRIBDIR="$TESTDIR/../contrib"
6 6
7 7 Prepare repo:
8 8
9 9 $ hg init
10 10
11 11 $ echo this is file a > a
12 12 $ hg add a
13 13 $ hg commit -m first
14 14
15 15 $ echo adding to file a >> a
16 16 $ hg commit -m second
17 17
18 18 $ echo adding more to file a >> a
19 19 $ hg commit -m third
20 20
21 21 $ hg up -r 0
22 22 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
23 23 $ echo merge-this >> a
24 24 $ hg commit -m merge-able
25 25 created new head
26 26
27 27 $ hg up -r 2
28 28 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 29
30 30 perfstatus
31 31
32 32 $ cat >> $HGRCPATH << EOF
33 33 > [extensions]
34 34 > perfstatusext=$CONTRIBDIR/perf.py
35 35 > [perf]
36 36 > presleep=0
37 37 > stub=on
38 38 > parentscount=1
39 39 > EOF
40 40 $ hg help perfstatusext
41 41 perfstatusext extension - helper extension to measure performance
42 42
43 43 list of commands:
44 44
45 45 perfaddremove
46 46 (no help text available)
47 47 perfancestors
48 48 (no help text available)
49 49 perfancestorset
50 50 (no help text available)
51 51 perfannotate (no help text available)
52 52 perfbranchmap
53 53 benchmark the update of a branchmap
54 54 perfcca (no help text available)
55 55 perfchangeset
56 56 (no help text available)
57 57 perfctxfiles (no help text available)
58 58 perfdiffwd Profile diff of working directory changes
59 59 perfdirfoldmap
60 60 (no help text available)
61 61 perfdirs (no help text available)
62 62 perfdirstate (no help text available)
63 63 perfdirstatedirs
64 64 (no help text available)
65 65 perfdirstatefoldmap
66 66 (no help text available)
67 67 perfdirstatewrite
68 68 (no help text available)
69 69 perffncacheencode
70 70 (no help text available)
71 71 perffncacheload
72 72 (no help text available)
73 73 perffncachewrite
74 74 (no help text available)
75 75 perfheads (no help text available)
76 76 perfindex (no help text available)
77 77 perfloadmarkers
78 78 benchmark the time to parse the on-disk markers for a repo
79 79 perflog (no help text available)
80 80 perflookup (no help text available)
81 81 perflrucachedict
82 82 (no help text available)
83 83 perfmanifest (no help text available)
84 84 perfmergecalculate
85 85 (no help text available)
86 86 perfmoonwalk benchmark walking the changelog backwards
87 87 perfnodelookup
88 88 (no help text available)
89 89 perfparents (no help text available)
90 90 perfpathcopies
91 91 (no help text available)
92 92 perfrawfiles (no help text available)
93 93 perfrevlog (no help text available)
94 perfrevlogrevision
95 Benchmark obtaining a revlog revision.
94 96 perfrevrange (no help text available)
95 97 perfrevset benchmark the execution time of a revset
96 98 perfstartup (no help text available)
97 99 perfstatus (no help text available)
98 100 perftags (no help text available)
99 101 perftemplating
100 102 (no help text available)
101 103 perfvolatilesets
102 104 benchmark the computation of various volatile set
103 105 perfwalk (no help text available)
104 106
105 107 (use "hg help -v perfstatusext" to show built-in aliases and global options)
106 108 $ hg perfaddremove
107 109 $ hg perfancestors
108 110 $ hg perfancestorset 2
109 111 $ hg perfannotate a
110 112 $ hg perfbranchmap
111 113 $ hg perfcca
112 114 $ hg perfchangeset 2
113 115 $ hg perfctxfiles 2
114 116 $ hg perfdiffwd
115 117 $ hg perfdirfoldmap
116 118 $ hg perfdirs
117 119 $ hg perfdirstate
118 120 $ hg perfdirstatedirs
119 121 $ hg perfdirstatefoldmap
120 122 $ hg perfdirstatewrite
121 123 $ hg perffncacheencode
122 124 $ hg perffncacheload
123 125 $ hg perffncachewrite
124 126 transaction abort!
125 127 rollback completed
126 128 $ hg perfheads
127 129 $ hg perfindex
128 130 $ hg perfloadmarkers
129 131 $ hg perflog
130 132 $ hg perflookup 2
131 133 $ hg perflrucache
132 134 $ hg perfmanifest 2
133 135 $ hg perfmergecalculate -r 3
134 136 $ hg perfmoonwalk
135 137 $ hg perfnodelookup 2
136 138 $ hg perfpathcopies 1 2
137 139 $ hg perfrawfiles 2
138 140 $ hg perfrevlog .hg/store/data/a.i
141 $ hg perfrevlogrevision -m 0
139 142 $ hg perfrevrange
140 143 $ hg perfrevset 'all()'
141 144 $ hg perfstartup
142 145 $ hg perfstatus
143 146 $ hg perftags
144 147 $ hg perftemplating
145 148 $ hg perfvolatilesets
146 149 $ hg perfwalk
147 150 $ hg perfparents
148 151
General Comments 0
You need to be logged in to leave comments. Login now