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