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