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