##// END OF EJS Templates
perfmanifest: allow and require passing in a rev...
Siddharth Agarwal -
r19712:79e5de2b default
parent child Browse files
Show More
@@ -1,410 +1,411 b''
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
6 6 import time, os, sys
7 7
8 8 cmdtable = {}
9 9 command = cmdutil.command(cmdtable)
10 10
11 11 def timer(func, title=None):
12 12 results = []
13 13 begin = time.time()
14 14 count = 0
15 15 while True:
16 16 ostart = os.times()
17 17 cstart = time.time()
18 18 r = func()
19 19 cstop = time.time()
20 20 ostop = os.times()
21 21 count += 1
22 22 a, b = ostart, ostop
23 23 results.append((cstop - cstart, b[0] - a[0], b[1]-a[1]))
24 24 if cstop - begin > 3 and count >= 100:
25 25 break
26 26 if cstop - begin > 10 and count >= 3:
27 27 break
28 28 if title:
29 29 sys.stderr.write("! %s\n" % title)
30 30 if r:
31 31 sys.stderr.write("! result: %s\n" % r)
32 32 m = min(results)
33 33 sys.stderr.write("! wall %f comb %f user %f sys %f (best of %d)\n"
34 34 % (m[0], m[1] + m[2], m[1], m[2], count))
35 35
36 36 @command('perfwalk')
37 37 def perfwalk(ui, repo, *pats):
38 38 try:
39 39 m = scmutil.match(repo[None], pats, {})
40 40 timer(lambda: len(list(repo.dirstate.walk(m, [], True, False))))
41 41 except Exception:
42 42 try:
43 43 m = scmutil.match(repo[None], pats, {})
44 44 timer(lambda: len([b for a, b, c in repo.dirstate.statwalk([], m)]))
45 45 except Exception:
46 46 timer(lambda: len(list(cmdutil.walk(repo, pats, {}))))
47 47
48 48 @command('perfannotate')
49 49 def perfannotate(ui, repo, f):
50 50 fc = repo['.'][f]
51 51 timer(lambda: len(fc.annotate(True)))
52 52
53 53 @command('perfstatus',
54 54 [('u', 'unknown', False,
55 55 'ask status to look for unknown files')])
56 56 def perfstatus(ui, repo, **opts):
57 57 #m = match.always(repo.root, repo.getcwd())
58 58 #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False,
59 59 # False))))
60 60 timer(lambda: sum(map(len, repo.status(**opts))))
61 61
62 62 @command('perfaddremove')
63 63 def perfaddremove(ui, repo):
64 64 try:
65 65 oldquiet = repo.ui.quiet
66 66 repo.ui.quiet = True
67 67 timer(lambda: scmutil.addremove(repo, dry_run=True))
68 68 finally:
69 69 repo.ui.quiet = oldquiet
70 70
71 71 def clearcaches(cl):
72 72 # behave somewhat consistently across internal API changes
73 73 if util.safehasattr(cl, 'clearcaches'):
74 74 cl.clearcaches()
75 75 elif util.safehasattr(cl, '_nodecache'):
76 76 from mercurial.node import nullid, nullrev
77 77 cl._nodecache = {nullid: nullrev}
78 78 cl._nodepos = None
79 79
80 80 @command('perfheads')
81 81 def perfheads(ui, repo):
82 82 cl = repo.changelog
83 83 def d():
84 84 len(cl.headrevs())
85 85 clearcaches(cl)
86 86 timer(d)
87 87
88 88 @command('perftags')
89 89 def perftags(ui, repo):
90 90 import mercurial.changelog, mercurial.manifest
91 91 def t():
92 92 repo.changelog = mercurial.changelog.changelog(repo.sopener)
93 93 repo.manifest = mercurial.manifest.manifest(repo.sopener)
94 94 repo._tags = None
95 95 return len(repo.tags())
96 96 timer(t)
97 97
98 98 @command('perfancestors')
99 99 def perfancestors(ui, repo):
100 100 heads = repo.changelog.headrevs()
101 101 def d():
102 102 for a in repo.changelog.ancestors(heads):
103 103 pass
104 104 timer(d)
105 105
106 106 @command('perfancestorset')
107 107 def perfancestorset(ui, repo, revset):
108 108 revs = repo.revs(revset)
109 109 heads = repo.changelog.headrevs()
110 110 def d():
111 111 s = repo.changelog.ancestors(heads)
112 112 for rev in revs:
113 113 rev in s
114 114 timer(d)
115 115
116 116 @command('perfdirs')
117 117 def perfdirs(ui, repo):
118 118 dirstate = repo.dirstate
119 119 'a' in dirstate
120 120 def d():
121 121 dirstate.dirs()
122 122 del dirstate._dirs
123 123 timer(d)
124 124
125 125 @command('perfdirstate')
126 126 def perfdirstate(ui, repo):
127 127 "a" in repo.dirstate
128 128 def d():
129 129 repo.dirstate.invalidate()
130 130 "a" in repo.dirstate
131 131 timer(d)
132 132
133 133 @command('perfdirstatedirs')
134 134 def perfdirstatedirs(ui, repo):
135 135 "a" in repo.dirstate
136 136 def d():
137 137 "a" in repo.dirstate._dirs
138 138 del repo.dirstate._dirs
139 139 timer(d)
140 140
141 141 @command('perfdirstatewrite')
142 142 def perfdirstatewrite(ui, repo):
143 143 ds = repo.dirstate
144 144 "a" in ds
145 145 def d():
146 146 ds._dirty = True
147 147 ds.write()
148 148 timer(d)
149 149
150 150 @command('perfmergecalculate',
151 151 [('r', 'rev', '.', 'rev to merge against')])
152 152 def perfmergecalculate(ui, repo, rev):
153 153 wctx = repo[None]
154 154 rctx = scmutil.revsingle(repo, rev, rev)
155 155 ancestor = wctx.ancestor(rctx)
156 156 # we don't want working dir files to be stat'd in the benchmark, so prime
157 157 # that cache
158 158 wctx.dirty()
159 159 def d():
160 160 # acceptremote is True because we don't want prompts in the middle of
161 161 # our benchmark
162 162 merge.calculateupdates(repo, wctx, rctx, ancestor, False, False, False,
163 163 acceptremote=True)
164 164 timer(d)
165 165
166 166 @command('perfpathcopies', [], "REV REV")
167 167 def perfpathcopies(ui, repo, rev1, rev2):
168 168 ctx1 = scmutil.revsingle(repo, rev1, rev1)
169 169 ctx2 = scmutil.revsingle(repo, rev2, rev2)
170 170 def d():
171 171 copies.pathcopies(ctx1, ctx2)
172 172 timer(d)
173 173
174 @command('perfmanifest')
175 def perfmanifest(ui, repo):
174 @command('perfmanifest', [], 'REV')
175 def perfmanifest(ui, repo, rev):
176 ctx = scmutil.revsingle(repo, rev, rev)
177 t = ctx.manifestnode()
176 178 def d():
177 t = repo.manifest.tip()
178 179 repo.manifest._mancache.clear()
179 180 repo.manifest._cache = None
180 181 repo.manifest.read(t)
181 182 timer(d)
182 183
183 184 @command('perfchangeset')
184 185 def perfchangeset(ui, repo, rev):
185 186 n = repo[rev].node()
186 187 def d():
187 188 repo.changelog.read(n)
188 189 #repo.changelog._cache = None
189 190 timer(d)
190 191
191 192 @command('perfindex')
192 193 def perfindex(ui, repo):
193 194 import mercurial.revlog
194 195 mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
195 196 n = repo["tip"].node()
196 197 def d():
197 198 cl = mercurial.revlog.revlog(repo.sopener, "00changelog.i")
198 199 cl.rev(n)
199 200 timer(d)
200 201
201 202 @command('perfstartup')
202 203 def perfstartup(ui, repo):
203 204 cmd = sys.argv[0]
204 205 def d():
205 206 os.system("HGRCPATH= %s version -q > /dev/null" % cmd)
206 207 timer(d)
207 208
208 209 @command('perfparents')
209 210 def perfparents(ui, repo):
210 211 nl = [repo.changelog.node(i) for i in xrange(1000)]
211 212 def d():
212 213 for n in nl:
213 214 repo.changelog.parents(n)
214 215 timer(d)
215 216
216 217 @command('perflookup')
217 218 def perflookup(ui, repo, rev):
218 219 timer(lambda: len(repo.lookup(rev)))
219 220
220 221 @command('perfrevrange')
221 222 def perfrevrange(ui, repo, *specs):
222 223 revrange = scmutil.revrange
223 224 timer(lambda: len(revrange(repo, specs)))
224 225
225 226 @command('perfnodelookup')
226 227 def perfnodelookup(ui, repo, rev):
227 228 import mercurial.revlog
228 229 mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
229 230 n = repo[rev].node()
230 231 cl = mercurial.revlog.revlog(repo.sopener, "00changelog.i")
231 232 def d():
232 233 cl.rev(n)
233 234 clearcaches(cl)
234 235 timer(d)
235 236
236 237 @command('perflog',
237 238 [('', 'rename', False, 'ask log to follow renames')])
238 239 def perflog(ui, repo, **opts):
239 240 ui.pushbuffer()
240 241 timer(lambda: commands.log(ui, repo, rev=[], date='', user='',
241 242 copies=opts.get('rename')))
242 243 ui.popbuffer()
243 244
244 245 @command('perftemplating')
245 246 def perftemplating(ui, repo):
246 247 ui.pushbuffer()
247 248 timer(lambda: commands.log(ui, repo, rev=[], date='', user='',
248 249 template='{date|shortdate} [{rev}:{node|short}]'
249 250 ' {author|person}: {desc|firstline}\n'))
250 251 ui.popbuffer()
251 252
252 253 @command('perfcca')
253 254 def perfcca(ui, repo):
254 255 timer(lambda: scmutil.casecollisionauditor(ui, False, repo.dirstate))
255 256
256 257 @command('perffncacheload')
257 258 def perffncacheload(ui, repo):
258 259 s = repo.store
259 260 def d():
260 261 s.fncache._load()
261 262 timer(d)
262 263
263 264 @command('perffncachewrite')
264 265 def perffncachewrite(ui, repo):
265 266 s = repo.store
266 267 s.fncache._load()
267 268 def d():
268 269 s.fncache._dirty = True
269 270 s.fncache.write()
270 271 timer(d)
271 272
272 273 @command('perffncacheencode')
273 274 def perffncacheencode(ui, repo):
274 275 s = repo.store
275 276 s.fncache._load()
276 277 def d():
277 278 for p in s.fncache.entries:
278 279 s.encode(p)
279 280 timer(d)
280 281
281 282 @command('perfdiffwd')
282 283 def perfdiffwd(ui, repo):
283 284 """Profile diff of working directory changes"""
284 285 options = {
285 286 'w': 'ignore_all_space',
286 287 'b': 'ignore_space_change',
287 288 'B': 'ignore_blank_lines',
288 289 }
289 290
290 291 for diffopt in ('', 'w', 'b', 'B', 'wB'):
291 292 opts = dict((options[c], '1') for c in diffopt)
292 293 def d():
293 294 ui.pushbuffer()
294 295 commands.diff(ui, repo, **opts)
295 296 ui.popbuffer()
296 297 title = 'diffopts: %s' % (diffopt and ('-' + diffopt) or 'none')
297 298 timer(d, title)
298 299
299 300 @command('perfrevlog',
300 301 [('d', 'dist', 100, 'distance between the revisions')],
301 302 "[INDEXFILE]")
302 303 def perfrevlog(ui, repo, file_, **opts):
303 304 from mercurial import revlog
304 305 dist = opts['dist']
305 306 def d():
306 307 r = revlog.revlog(lambda fn: open(fn, 'rb'), file_)
307 308 for x in xrange(0, len(r), dist):
308 309 r.revision(r.node(x))
309 310
310 311 timer(d)
311 312
312 313 @command('perfrevset',
313 314 [('C', 'clear', False, 'clear volatile cache between each call.')],
314 315 "REVSET")
315 316 def perfrevset(ui, repo, expr, clear=False):
316 317 """benchmark the execution time of a revset
317 318
318 319 Use the --clean option if need to evaluate the impact of build volatile
319 320 revisions set cache on the revset execution. Volatile cache hold filtered
320 321 and obsolete related cache."""
321 322 def d():
322 323 if clear:
323 324 repo.invalidatevolatilesets()
324 325 repo.revs(expr)
325 326 timer(d)
326 327
327 328 @command('perfvolatilesets')
328 329 def perfvolatilesets(ui, repo, *names):
329 330 """benchmark the computation of various volatile set
330 331
331 332 Volatile set computes element related to filtering and obsolescence."""
332 333 repo = repo.unfiltered()
333 334
334 335 def getobs(name):
335 336 def d():
336 337 repo.invalidatevolatilesets()
337 338 obsolete.getrevs(repo, name)
338 339 return d
339 340
340 341 allobs = sorted(obsolete.cachefuncs)
341 342 if names:
342 343 allobs = [n for n in allobs if n in names]
343 344
344 345 for name in allobs:
345 346 timer(getobs(name), title=name)
346 347
347 348 def getfiltered(name):
348 349 def d():
349 350 repo.invalidatevolatilesets()
350 351 repoview.filteredrevs(repo, name)
351 352 return d
352 353
353 354 allfilter = sorted(repoview.filtertable)
354 355 if names:
355 356 allfilter = [n for n in allfilter if n in names]
356 357
357 358 for name in allfilter:
358 359 timer(getfiltered(name), title=name)
359 360
360 361 @command('perfbranchmap',
361 362 [('f', 'full', False,
362 363 'Includes build time of subset'),
363 364 ])
364 365 def perfbranchmap(ui, repo, full=False):
365 366 """benchmark the update of a branchmap
366 367
367 368 This benchmarks the full repo.branchmap() call with read and write disabled
368 369 """
369 370 def getbranchmap(filtername):
370 371 """generate a benchmark function for the filtername"""
371 372 if filtername is None:
372 373 view = repo
373 374 else:
374 375 view = repo.filtered(filtername)
375 376 def d():
376 377 if full:
377 378 view._branchcaches.clear()
378 379 else:
379 380 view._branchcaches.pop(filtername, None)
380 381 view.branchmap()
381 382 return d
382 383 # add filter in smaller subset to bigger subset
383 384 possiblefilters = set(repoview.filtertable)
384 385 allfilters = []
385 386 while possiblefilters:
386 387 for name in possiblefilters:
387 388 subset = repoview.subsettable.get(name)
388 389 if subset not in possiblefilters:
389 390 break
390 391 else:
391 392 assert False, 'subset cycle %s!' % possiblefilters
392 393 allfilters.append(name)
393 394 possiblefilters.remove(name)
394 395
395 396 # warm the cache
396 397 if not full:
397 398 for name in allfilters:
398 399 repo.filtered(name).branchmap()
399 400 # add unfiltered
400 401 allfilters.append(None)
401 402 oldread = branchmap.read
402 403 oldwrite = branchmap.branchcache.write
403 404 try:
404 405 branchmap.read = lambda repo: None
405 406 branchmap.write = lambda repo: None
406 407 for name in allfilters:
407 408 timer(getbranchmap(name), title=str(name))
408 409 finally:
409 410 branchmap.read = oldread
410 411 branchmap.branchcache.write = oldwrite
General Comments 0
You need to be logged in to leave comments. Login now