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