##// END OF EJS Templates
perfmanifest: fix cache invalidation...
Siddharth Agarwal -
r19711:0a881ea4 default
parent child Browse files
Show More
@@ -1,410 +1,410 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 174 @command('perfmanifest')
175 175 def perfmanifest(ui, repo):
176 176 def d():
177 177 t = repo.manifest.tip()
178 repo.manifest._mancache.clear()
179 repo.manifest._cache = None
178 180 repo.manifest.read(t)
179 repo.manifest.mapcache = None
180 repo.manifest._cache = None
181 181 timer(d)
182 182
183 183 @command('perfchangeset')
184 184 def perfchangeset(ui, repo, rev):
185 185 n = repo[rev].node()
186 186 def d():
187 187 repo.changelog.read(n)
188 188 #repo.changelog._cache = None
189 189 timer(d)
190 190
191 191 @command('perfindex')
192 192 def perfindex(ui, repo):
193 193 import mercurial.revlog
194 194 mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
195 195 n = repo["tip"].node()
196 196 def d():
197 197 cl = mercurial.revlog.revlog(repo.sopener, "00changelog.i")
198 198 cl.rev(n)
199 199 timer(d)
200 200
201 201 @command('perfstartup')
202 202 def perfstartup(ui, repo):
203 203 cmd = sys.argv[0]
204 204 def d():
205 205 os.system("HGRCPATH= %s version -q > /dev/null" % cmd)
206 206 timer(d)
207 207
208 208 @command('perfparents')
209 209 def perfparents(ui, repo):
210 210 nl = [repo.changelog.node(i) for i in xrange(1000)]
211 211 def d():
212 212 for n in nl:
213 213 repo.changelog.parents(n)
214 214 timer(d)
215 215
216 216 @command('perflookup')
217 217 def perflookup(ui, repo, rev):
218 218 timer(lambda: len(repo.lookup(rev)))
219 219
220 220 @command('perfrevrange')
221 221 def perfrevrange(ui, repo, *specs):
222 222 revrange = scmutil.revrange
223 223 timer(lambda: len(revrange(repo, specs)))
224 224
225 225 @command('perfnodelookup')
226 226 def perfnodelookup(ui, repo, rev):
227 227 import mercurial.revlog
228 228 mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
229 229 n = repo[rev].node()
230 230 cl = mercurial.revlog.revlog(repo.sopener, "00changelog.i")
231 231 def d():
232 232 cl.rev(n)
233 233 clearcaches(cl)
234 234 timer(d)
235 235
236 236 @command('perflog',
237 237 [('', 'rename', False, 'ask log to follow renames')])
238 238 def perflog(ui, repo, **opts):
239 239 ui.pushbuffer()
240 240 timer(lambda: commands.log(ui, repo, rev=[], date='', user='',
241 241 copies=opts.get('rename')))
242 242 ui.popbuffer()
243 243
244 244 @command('perftemplating')
245 245 def perftemplating(ui, repo):
246 246 ui.pushbuffer()
247 247 timer(lambda: commands.log(ui, repo, rev=[], date='', user='',
248 248 template='{date|shortdate} [{rev}:{node|short}]'
249 249 ' {author|person}: {desc|firstline}\n'))
250 250 ui.popbuffer()
251 251
252 252 @command('perfcca')
253 253 def perfcca(ui, repo):
254 254 timer(lambda: scmutil.casecollisionauditor(ui, False, repo.dirstate))
255 255
256 256 @command('perffncacheload')
257 257 def perffncacheload(ui, repo):
258 258 s = repo.store
259 259 def d():
260 260 s.fncache._load()
261 261 timer(d)
262 262
263 263 @command('perffncachewrite')
264 264 def perffncachewrite(ui, repo):
265 265 s = repo.store
266 266 s.fncache._load()
267 267 def d():
268 268 s.fncache._dirty = True
269 269 s.fncache.write()
270 270 timer(d)
271 271
272 272 @command('perffncacheencode')
273 273 def perffncacheencode(ui, repo):
274 274 s = repo.store
275 275 s.fncache._load()
276 276 def d():
277 277 for p in s.fncache.entries:
278 278 s.encode(p)
279 279 timer(d)
280 280
281 281 @command('perfdiffwd')
282 282 def perfdiffwd(ui, repo):
283 283 """Profile diff of working directory changes"""
284 284 options = {
285 285 'w': 'ignore_all_space',
286 286 'b': 'ignore_space_change',
287 287 'B': 'ignore_blank_lines',
288 288 }
289 289
290 290 for diffopt in ('', 'w', 'b', 'B', 'wB'):
291 291 opts = dict((options[c], '1') for c in diffopt)
292 292 def d():
293 293 ui.pushbuffer()
294 294 commands.diff(ui, repo, **opts)
295 295 ui.popbuffer()
296 296 title = 'diffopts: %s' % (diffopt and ('-' + diffopt) or 'none')
297 297 timer(d, title)
298 298
299 299 @command('perfrevlog',
300 300 [('d', 'dist', 100, 'distance between the revisions')],
301 301 "[INDEXFILE]")
302 302 def perfrevlog(ui, repo, file_, **opts):
303 303 from mercurial import revlog
304 304 dist = opts['dist']
305 305 def d():
306 306 r = revlog.revlog(lambda fn: open(fn, 'rb'), file_)
307 307 for x in xrange(0, len(r), dist):
308 308 r.revision(r.node(x))
309 309
310 310 timer(d)
311 311
312 312 @command('perfrevset',
313 313 [('C', 'clear', False, 'clear volatile cache between each call.')],
314 314 "REVSET")
315 315 def perfrevset(ui, repo, expr, clear=False):
316 316 """benchmark the execution time of a revset
317 317
318 318 Use the --clean option if need to evaluate the impact of build volatile
319 319 revisions set cache on the revset execution. Volatile cache hold filtered
320 320 and obsolete related cache."""
321 321 def d():
322 322 if clear:
323 323 repo.invalidatevolatilesets()
324 324 repo.revs(expr)
325 325 timer(d)
326 326
327 327 @command('perfvolatilesets')
328 328 def perfvolatilesets(ui, repo, *names):
329 329 """benchmark the computation of various volatile set
330 330
331 331 Volatile set computes element related to filtering and obsolescence."""
332 332 repo = repo.unfiltered()
333 333
334 334 def getobs(name):
335 335 def d():
336 336 repo.invalidatevolatilesets()
337 337 obsolete.getrevs(repo, name)
338 338 return d
339 339
340 340 allobs = sorted(obsolete.cachefuncs)
341 341 if names:
342 342 allobs = [n for n in allobs if n in names]
343 343
344 344 for name in allobs:
345 345 timer(getobs(name), title=name)
346 346
347 347 def getfiltered(name):
348 348 def d():
349 349 repo.invalidatevolatilesets()
350 350 repoview.filteredrevs(repo, name)
351 351 return d
352 352
353 353 allfilter = sorted(repoview.filtertable)
354 354 if names:
355 355 allfilter = [n for n in allfilter if n in names]
356 356
357 357 for name in allfilter:
358 358 timer(getfiltered(name), title=name)
359 359
360 360 @command('perfbranchmap',
361 361 [('f', 'full', False,
362 362 'Includes build time of subset'),
363 363 ])
364 364 def perfbranchmap(ui, repo, full=False):
365 365 """benchmark the update of a branchmap
366 366
367 367 This benchmarks the full repo.branchmap() call with read and write disabled
368 368 """
369 369 def getbranchmap(filtername):
370 370 """generate a benchmark function for the filtername"""
371 371 if filtername is None:
372 372 view = repo
373 373 else:
374 374 view = repo.filtered(filtername)
375 375 def d():
376 376 if full:
377 377 view._branchcaches.clear()
378 378 else:
379 379 view._branchcaches.pop(filtername, None)
380 380 view.branchmap()
381 381 return d
382 382 # add filter in smaller subset to bigger subset
383 383 possiblefilters = set(repoview.filtertable)
384 384 allfilters = []
385 385 while possiblefilters:
386 386 for name in possiblefilters:
387 387 subset = repoview.subsettable.get(name)
388 388 if subset not in possiblefilters:
389 389 break
390 390 else:
391 391 assert False, 'subset cycle %s!' % possiblefilters
392 392 allfilters.append(name)
393 393 possiblefilters.remove(name)
394 394
395 395 # warm the cache
396 396 if not full:
397 397 for name in allfilters:
398 398 repo.filtered(name).branchmap()
399 399 # add unfiltered
400 400 allfilters.append(None)
401 401 oldread = branchmap.read
402 402 oldwrite = branchmap.branchcache.write
403 403 try:
404 404 branchmap.read = lambda repo: None
405 405 branchmap.write = lambda repo: None
406 406 for name in allfilters:
407 407 timer(getbranchmap(name), title=str(name))
408 408 finally:
409 409 branchmap.read = oldread
410 410 branchmap.branchcache.write = oldwrite
General Comments 0
You need to be logged in to leave comments. Login now