Mercurial > hg
comparison contrib/perf.py @ 23171:8afae1d5d108
perf: use a formatter for output
We use a `formatter` object in the perf extensions. This allow the use of
formatted output like json. To avoid adding logic to create a formatter and pass
it around to the timer function in every command, we add a `gettimer` function
in charge of returning a `timer` function as simple as before but embedding an
appropriate formatter.
This new `gettimer` function also return the formatter as it needs to be
explicitly closed at the end of the command.
example output:
$ hg --config ui.formatjson=True perfvolatilesets visible obsolete
[
{
"comb": 0.02,
"count": 126,
"sys": 0.0,
"title": "obsolete",
"user": 0.02,
"wall": 0.0199398994446
},
{
"comb": 0.02,
"count": 117,
"sys": 0.0,
"title": "visible",
"user": 0.02,
"wall": 0.0250301361084
}
]
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Tue, 04 Nov 2014 10:40:06 +0000 |
parents | d8ff1f671aed |
children | ccb93e9affc1 |
comparison
equal
deleted
inserted
replaced
23170:02e8f9b60052 | 23171:8afae1d5d108 |
---|---|
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 | 8 |
8 cmdtable = {} | 9 cmdtable = {} |
9 command = cmdutil.command(cmdtable) | 10 command = cmdutil.command(cmdtable) |
10 | 11 |
11 def timer(func, title=None): | 12 def gettimer(ui, opts=None): |
13 """return a timer function and formatter: (timer, formatter) | |
14 | |
15 This functions exist to gather the creation of formatter in a single | |
16 place instead of duplicating it in all performance command.""" | |
17 if opts is None: | |
18 opts = {} | |
19 # redirect all to stderr | |
20 ui = ui.copy() | |
21 ui.fout = ui.ferr | |
22 # get a formatter | |
23 fm = ui.formatter('perf', opts) | |
24 return functools.partial(_timer, fm), fm | |
25 | |
26 def _timer(fm, func, title=None): | |
12 results = [] | 27 results = [] |
13 begin = time.time() | 28 begin = time.time() |
14 count = 0 | 29 count = 0 |
15 while True: | 30 while True: |
16 ostart = os.times() | 31 ostart = os.times() |
23 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])) |
24 if cstop - begin > 3 and count >= 100: | 39 if cstop - begin > 3 and count >= 100: |
25 break | 40 break |
26 if cstop - begin > 10 and count >= 3: | 41 if cstop - begin > 10 and count >= 3: |
27 break | 42 break |
43 | |
44 fm.startitem() | |
45 | |
28 if title: | 46 if title: |
29 sys.stderr.write("! %s\n" % title) | 47 fm.write('title', '! %s\n', title) |
30 if r: | 48 if r: |
31 sys.stderr.write("! result: %s\n" % r) | 49 fm.write('result', '! result: %s\n', r) |
32 m = min(results) | 50 m = min(results) |
33 sys.stderr.write("! wall %f comb %f user %f sys %f (best of %d)\n" | 51 fm.plain('!') |
34 % (m[0], m[1] + m[2], m[1], m[2], count)) | 52 fm.write('wall', ' wall %f', m[0]) |
53 fm.write('comb', ' comb %f', m[1] + m[2]) | |
54 fm.write('user', ' user %f', m[1]) | |
55 fm.write('sys', ' sys %f', m[2]) | |
56 fm.write('count', ' (best of %d)', count) | |
57 fm.plain('\n') | |
35 | 58 |
36 @command('perfwalk') | 59 @command('perfwalk') |
37 def perfwalk(ui, repo, *pats): | 60 def perfwalk(ui, repo, *pats): |
61 timer, fm = gettimer(ui) | |
38 try: | 62 try: |
39 m = scmutil.match(repo[None], pats, {}) | 63 m = scmutil.match(repo[None], pats, {}) |
40 timer(lambda: len(list(repo.dirstate.walk(m, [], True, False)))) | 64 timer(lambda: len(list(repo.dirstate.walk(m, [], True, False)))) |
41 except Exception: | 65 except Exception: |
42 try: | 66 try: |
43 m = scmutil.match(repo[None], pats, {}) | 67 m = scmutil.match(repo[None], pats, {}) |
44 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)])) |
45 except Exception: | 69 except Exception: |
46 timer(lambda: len(list(cmdutil.walk(repo, pats, {})))) | 70 timer(lambda: len(list(cmdutil.walk(repo, pats, {})))) |
71 fm.end() | |
47 | 72 |
48 @command('perfannotate') | 73 @command('perfannotate') |
49 def perfannotate(ui, repo, f): | 74 def perfannotate(ui, repo, f): |
75 timer, fm = gettimer(ui) | |
50 fc = repo['.'][f] | 76 fc = repo['.'][f] |
51 timer(lambda: len(fc.annotate(True))) | 77 timer(lambda: len(fc.annotate(True))) |
78 fm.end() | |
52 | 79 |
53 @command('perfstatus', | 80 @command('perfstatus', |
54 [('u', 'unknown', False, | 81 [('u', 'unknown', False, |
55 'ask status to look for unknown files')]) | 82 'ask status to look for unknown files')]) |
56 def perfstatus(ui, repo, **opts): | 83 def perfstatus(ui, repo, **opts): |
57 #m = match.always(repo.root, repo.getcwd()) | 84 #m = match.always(repo.root, repo.getcwd()) |
58 #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False, | 85 #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False, |
59 # False)))) | 86 # False)))) |
87 timer, fm = gettimer(ui) | |
60 timer(lambda: sum(map(len, repo.status(**opts)))) | 88 timer(lambda: sum(map(len, repo.status(**opts)))) |
89 fm.end() | |
61 | 90 |
62 @command('perfaddremove') | 91 @command('perfaddremove') |
63 def perfaddremove(ui, repo): | 92 def perfaddremove(ui, repo): |
93 timer, fm = gettimer(ui) | |
64 try: | 94 try: |
65 oldquiet = repo.ui.quiet | 95 oldquiet = repo.ui.quiet |
66 repo.ui.quiet = True | 96 repo.ui.quiet = True |
67 timer(lambda: scmutil.addremove(repo, dry_run=True)) | 97 timer(lambda: scmutil.addremove(repo, dry_run=True)) |
68 finally: | 98 finally: |
69 repo.ui.quiet = oldquiet | 99 repo.ui.quiet = oldquiet |
100 fm.end() | |
70 | 101 |
71 def clearcaches(cl): | 102 def clearcaches(cl): |
72 # behave somewhat consistently across internal API changes | 103 # behave somewhat consistently across internal API changes |
73 if util.safehasattr(cl, 'clearcaches'): | 104 if util.safehasattr(cl, 'clearcaches'): |
74 cl.clearcaches() | 105 cl.clearcaches() |
77 cl._nodecache = {nullid: nullrev} | 108 cl._nodecache = {nullid: nullrev} |
78 cl._nodepos = None | 109 cl._nodepos = None |
79 | 110 |
80 @command('perfheads') | 111 @command('perfheads') |
81 def perfheads(ui, repo): | 112 def perfheads(ui, repo): |
113 timer, fm = gettimer(ui) | |
82 cl = repo.changelog | 114 cl = repo.changelog |
83 def d(): | 115 def d(): |
84 len(cl.headrevs()) | 116 len(cl.headrevs()) |
85 clearcaches(cl) | 117 clearcaches(cl) |
86 timer(d) | 118 timer(d) |
119 fm.end() | |
87 | 120 |
88 @command('perftags') | 121 @command('perftags') |
89 def perftags(ui, repo): | 122 def perftags(ui, repo): |
90 import mercurial.changelog | 123 import mercurial.changelog |
91 import mercurial.manifest | 124 import mercurial.manifest |
125 timer, fm = gettimer(ui) | |
92 def t(): | 126 def t(): |
93 repo.changelog = mercurial.changelog.changelog(repo.sopener) | 127 repo.changelog = mercurial.changelog.changelog(repo.sopener) |
94 repo.manifest = mercurial.manifest.manifest(repo.sopener) | 128 repo.manifest = mercurial.manifest.manifest(repo.sopener) |
95 repo._tags = None | 129 repo._tags = None |
96 return len(repo.tags()) | 130 return len(repo.tags()) |
97 timer(t) | 131 timer(t) |
132 fm.end() | |
98 | 133 |
99 @command('perfancestors') | 134 @command('perfancestors') |
100 def perfancestors(ui, repo): | 135 def perfancestors(ui, repo): |
136 timer, fm = gettimer(ui) | |
101 heads = repo.changelog.headrevs() | 137 heads = repo.changelog.headrevs() |
102 def d(): | 138 def d(): |
103 for a in repo.changelog.ancestors(heads): | 139 for a in repo.changelog.ancestors(heads): |
104 pass | 140 pass |
105 timer(d) | 141 timer(d) |
142 fm.end() | |
106 | 143 |
107 @command('perfancestorset') | 144 @command('perfancestorset') |
108 def perfancestorset(ui, repo, revset): | 145 def perfancestorset(ui, repo, revset): |
146 timer, fm = gettimer(ui) | |
109 revs = repo.revs(revset) | 147 revs = repo.revs(revset) |
110 heads = repo.changelog.headrevs() | 148 heads = repo.changelog.headrevs() |
111 def d(): | 149 def d(): |
112 s = repo.changelog.ancestors(heads) | 150 s = repo.changelog.ancestors(heads) |
113 for rev in revs: | 151 for rev in revs: |
114 rev in s | 152 rev in s |
115 timer(d) | 153 timer(d) |
154 fm.end() | |
116 | 155 |
117 @command('perfdirs') | 156 @command('perfdirs') |
118 def perfdirs(ui, repo): | 157 def perfdirs(ui, repo): |
158 timer, fm = gettimer(ui) | |
119 dirstate = repo.dirstate | 159 dirstate = repo.dirstate |
120 'a' in dirstate | 160 'a' in dirstate |
121 def d(): | 161 def d(): |
122 dirstate.dirs() | 162 dirstate.dirs() |
123 del dirstate._dirs | 163 del dirstate._dirs |
124 timer(d) | 164 timer(d) |
165 fm.end() | |
125 | 166 |
126 @command('perfdirstate') | 167 @command('perfdirstate') |
127 def perfdirstate(ui, repo): | 168 def perfdirstate(ui, repo): |
169 timer, fm = gettimer(ui) | |
128 "a" in repo.dirstate | 170 "a" in repo.dirstate |
129 def d(): | 171 def d(): |
130 repo.dirstate.invalidate() | 172 repo.dirstate.invalidate() |
131 "a" in repo.dirstate | 173 "a" in repo.dirstate |
132 timer(d) | 174 timer(d) |
175 fm.end() | |
133 | 176 |
134 @command('perfdirstatedirs') | 177 @command('perfdirstatedirs') |
135 def perfdirstatedirs(ui, repo): | 178 def perfdirstatedirs(ui, repo): |
179 timer, fm = gettimer(ui) | |
136 "a" in repo.dirstate | 180 "a" in repo.dirstate |
137 def d(): | 181 def d(): |
138 "a" in repo.dirstate._dirs | 182 "a" in repo.dirstate._dirs |
139 del repo.dirstate._dirs | 183 del repo.dirstate._dirs |
140 timer(d) | 184 timer(d) |
185 fm.end() | |
141 | 186 |
142 @command('perfdirstatefoldmap') | 187 @command('perfdirstatefoldmap') |
143 def perffoldmap(ui, repo): | 188 def perffoldmap(ui, repo): |
189 timer, fm = gettimer(ui) | |
144 dirstate = repo.dirstate | 190 dirstate = repo.dirstate |
145 'a' in dirstate | 191 'a' in dirstate |
146 def d(): | 192 def d(): |
147 dirstate._foldmap.get('a') | 193 dirstate._foldmap.get('a') |
148 del dirstate._foldmap | 194 del dirstate._foldmap |
149 del dirstate._dirs | 195 del dirstate._dirs |
150 timer(d) | 196 timer(d) |
197 fm.end() | |
151 | 198 |
152 @command('perfdirstatewrite') | 199 @command('perfdirstatewrite') |
153 def perfdirstatewrite(ui, repo): | 200 def perfdirstatewrite(ui, repo): |
201 timer, fm = gettimer(ui) | |
154 ds = repo.dirstate | 202 ds = repo.dirstate |
155 "a" in ds | 203 "a" in ds |
156 def d(): | 204 def d(): |
157 ds._dirty = True | 205 ds._dirty = True |
158 ds.write() | 206 ds.write() |
159 timer(d) | 207 timer(d) |
208 fm.end() | |
160 | 209 |
161 @command('perfmergecalculate', | 210 @command('perfmergecalculate', |
162 [('r', 'rev', '.', 'rev to merge against')]) | 211 [('r', 'rev', '.', 'rev to merge against')]) |
163 def perfmergecalculate(ui, repo, rev): | 212 def perfmergecalculate(ui, repo, rev): |
213 timer, fm = gettimer(ui) | |
164 wctx = repo[None] | 214 wctx = repo[None] |
165 rctx = scmutil.revsingle(repo, rev, rev) | 215 rctx = scmutil.revsingle(repo, rev, rev) |
166 ancestor = wctx.ancestor(rctx) | 216 ancestor = wctx.ancestor(rctx) |
167 # 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 |
168 # that cache | 218 # that cache |
171 # 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 |
172 # our benchmark | 222 # our benchmark |
173 merge.calculateupdates(repo, wctx, rctx, ancestor, False, False, False, | 223 merge.calculateupdates(repo, wctx, rctx, ancestor, False, False, False, |
174 acceptremote=True) | 224 acceptremote=True) |
175 timer(d) | 225 timer(d) |
226 fm.end() | |
176 | 227 |
177 @command('perfpathcopies', [], "REV REV") | 228 @command('perfpathcopies', [], "REV REV") |
178 def perfpathcopies(ui, repo, rev1, rev2): | 229 def perfpathcopies(ui, repo, rev1, rev2): |
230 timer, fm = gettimer(ui) | |
179 ctx1 = scmutil.revsingle(repo, rev1, rev1) | 231 ctx1 = scmutil.revsingle(repo, rev1, rev1) |
180 ctx2 = scmutil.revsingle(repo, rev2, rev2) | 232 ctx2 = scmutil.revsingle(repo, rev2, rev2) |
181 def d(): | 233 def d(): |
182 copies.pathcopies(ctx1, ctx2) | 234 copies.pathcopies(ctx1, ctx2) |
183 timer(d) | 235 timer(d) |
236 fm.end() | |
184 | 237 |
185 @command('perfmanifest', [], 'REV') | 238 @command('perfmanifest', [], 'REV') |
186 def perfmanifest(ui, repo, rev): | 239 def perfmanifest(ui, repo, rev): |
240 timer, fm = gettimer(ui) | |
187 ctx = scmutil.revsingle(repo, rev, rev) | 241 ctx = scmutil.revsingle(repo, rev, rev) |
188 t = ctx.manifestnode() | 242 t = ctx.manifestnode() |
189 def d(): | 243 def d(): |
190 repo.manifest._mancache.clear() | 244 repo.manifest._mancache.clear() |
191 repo.manifest._cache = None | 245 repo.manifest._cache = None |
192 repo.manifest.read(t) | 246 repo.manifest.read(t) |
193 timer(d) | 247 timer(d) |
248 fm.end() | |
194 | 249 |
195 @command('perfchangeset') | 250 @command('perfchangeset') |
196 def perfchangeset(ui, repo, rev): | 251 def perfchangeset(ui, repo, rev): |
252 timer, fm = gettimer(ui) | |
197 n = repo[rev].node() | 253 n = repo[rev].node() |
198 def d(): | 254 def d(): |
199 repo.changelog.read(n) | 255 repo.changelog.read(n) |
200 #repo.changelog._cache = None | 256 #repo.changelog._cache = None |
201 timer(d) | 257 timer(d) |
258 fm.end() | |
202 | 259 |
203 @command('perfindex') | 260 @command('perfindex') |
204 def perfindex(ui, repo): | 261 def perfindex(ui, repo): |
205 import mercurial.revlog | 262 import mercurial.revlog |
263 timer, fm = gettimer(ui) | |
206 mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg | 264 mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg |
207 n = repo["tip"].node() | 265 n = repo["tip"].node() |
208 def d(): | 266 def d(): |
209 cl = mercurial.revlog.revlog(repo.sopener, "00changelog.i") | 267 cl = mercurial.revlog.revlog(repo.sopener, "00changelog.i") |
210 cl.rev(n) | 268 cl.rev(n) |
211 timer(d) | 269 timer(d) |
270 fm.end() | |
212 | 271 |
213 @command('perfstartup') | 272 @command('perfstartup') |
214 def perfstartup(ui, repo): | 273 def perfstartup(ui, repo): |
274 timer, fm = gettimer(ui) | |
215 cmd = sys.argv[0] | 275 cmd = sys.argv[0] |
216 def d(): | 276 def d(): |
217 os.system("HGRCPATH= %s version -q > /dev/null" % cmd) | 277 os.system("HGRCPATH= %s version -q > /dev/null" % cmd) |
218 timer(d) | 278 timer(d) |
279 fm.end() | |
219 | 280 |
220 @command('perfparents') | 281 @command('perfparents') |
221 def perfparents(ui, repo): | 282 def perfparents(ui, repo): |
283 timer, fm = gettimer(ui) | |
222 nl = [repo.changelog.node(i) for i in xrange(1000)] | 284 nl = [repo.changelog.node(i) for i in xrange(1000)] |
223 def d(): | 285 def d(): |
224 for n in nl: | 286 for n in nl: |
225 repo.changelog.parents(n) | 287 repo.changelog.parents(n) |
226 timer(d) | 288 timer(d) |
289 fm.end() | |
227 | 290 |
228 @command('perflookup') | 291 @command('perflookup') |
229 def perflookup(ui, repo, rev): | 292 def perflookup(ui, repo, rev): |
293 timer, fm = gettimer(ui) | |
230 timer(lambda: len(repo.lookup(rev))) | 294 timer(lambda: len(repo.lookup(rev))) |
295 fm.end() | |
231 | 296 |
232 @command('perfrevrange') | 297 @command('perfrevrange') |
233 def perfrevrange(ui, repo, *specs): | 298 def perfrevrange(ui, repo, *specs): |
299 timer, fm = gettimer(ui) | |
234 revrange = scmutil.revrange | 300 revrange = scmutil.revrange |
235 timer(lambda: len(revrange(repo, specs))) | 301 timer(lambda: len(revrange(repo, specs))) |
302 fm.end() | |
236 | 303 |
237 @command('perfnodelookup') | 304 @command('perfnodelookup') |
238 def perfnodelookup(ui, repo, rev): | 305 def perfnodelookup(ui, repo, rev): |
306 timer, fm = gettimer(ui) | |
239 import mercurial.revlog | 307 import mercurial.revlog |
240 mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg | 308 mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg |
241 n = repo[rev].node() | 309 n = repo[rev].node() |
242 cl = mercurial.revlog.revlog(repo.sopener, "00changelog.i") | 310 cl = mercurial.revlog.revlog(repo.sopener, "00changelog.i") |
243 def d(): | 311 def d(): |
244 cl.rev(n) | 312 cl.rev(n) |
245 clearcaches(cl) | 313 clearcaches(cl) |
246 timer(d) | 314 timer(d) |
315 fm.end() | |
247 | 316 |
248 @command('perflog', | 317 @command('perflog', |
249 [('', 'rename', False, 'ask log to follow renames')]) | 318 [('', 'rename', False, 'ask log to follow renames')]) |
250 def perflog(ui, repo, **opts): | 319 def perflog(ui, repo, **opts): |
320 timer, fm = gettimer(ui) | |
251 ui.pushbuffer() | 321 ui.pushbuffer() |
252 timer(lambda: commands.log(ui, repo, rev=[], date='', user='', | 322 timer(lambda: commands.log(ui, repo, rev=[], date='', user='', |
253 copies=opts.get('rename'))) | 323 copies=opts.get('rename'))) |
254 ui.popbuffer() | 324 ui.popbuffer() |
325 fm.end() | |
255 | 326 |
256 @command('perfmoonwalk') | 327 @command('perfmoonwalk') |
257 def perfmoonwalk(ui, repo): | 328 def perfmoonwalk(ui, repo): |
258 """benchmark walking the changelog backwards | 329 """benchmark walking the changelog backwards |
259 | 330 |
260 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. |
261 """ | 332 """ |
333 timer, fm = gettimer(ui) | |
262 def moonwalk(): | 334 def moonwalk(): |
263 for i in xrange(len(repo), -1, -1): | 335 for i in xrange(len(repo), -1, -1): |
264 ctx = repo[i] | 336 ctx = repo[i] |
265 ctx.branch() # read changelog data (in addition to the index) | 337 ctx.branch() # read changelog data (in addition to the index) |
266 timer(moonwalk) | 338 timer(moonwalk) |
339 fm.end() | |
267 | 340 |
268 @command('perftemplating') | 341 @command('perftemplating') |
269 def perftemplating(ui, repo): | 342 def perftemplating(ui, repo): |
343 timer, fm = gettimer(ui) | |
270 ui.pushbuffer() | 344 ui.pushbuffer() |
271 timer(lambda: commands.log(ui, repo, rev=[], date='', user='', | 345 timer(lambda: commands.log(ui, repo, rev=[], date='', user='', |
272 template='{date|shortdate} [{rev}:{node|short}]' | 346 template='{date|shortdate} [{rev}:{node|short}]' |
273 ' {author|person}: {desc|firstline}\n')) | 347 ' {author|person}: {desc|firstline}\n')) |
274 ui.popbuffer() | 348 ui.popbuffer() |
349 fm.end() | |
275 | 350 |
276 @command('perfcca') | 351 @command('perfcca') |
277 def perfcca(ui, repo): | 352 def perfcca(ui, repo): |
353 timer, fm = gettimer(ui) | |
278 timer(lambda: scmutil.casecollisionauditor(ui, False, repo.dirstate)) | 354 timer(lambda: scmutil.casecollisionauditor(ui, False, repo.dirstate)) |
355 fm.end() | |
279 | 356 |
280 @command('perffncacheload') | 357 @command('perffncacheload') |
281 def perffncacheload(ui, repo): | 358 def perffncacheload(ui, repo): |
359 timer, fm = gettimer(ui) | |
282 s = repo.store | 360 s = repo.store |
283 def d(): | 361 def d(): |
284 s.fncache._load() | 362 s.fncache._load() |
285 timer(d) | 363 timer(d) |
364 fm.end() | |
286 | 365 |
287 @command('perffncachewrite') | 366 @command('perffncachewrite') |
288 def perffncachewrite(ui, repo): | 367 def perffncachewrite(ui, repo): |
368 timer, fm = gettimer(ui) | |
289 s = repo.store | 369 s = repo.store |
290 s.fncache._load() | 370 s.fncache._load() |
291 def d(): | 371 def d(): |
292 s.fncache._dirty = True | 372 s.fncache._dirty = True |
293 s.fncache.write() | 373 s.fncache.write() |
294 timer(d) | 374 timer(d) |
375 fm.end() | |
295 | 376 |
296 @command('perffncacheencode') | 377 @command('perffncacheencode') |
297 def perffncacheencode(ui, repo): | 378 def perffncacheencode(ui, repo): |
379 timer, fm = gettimer(ui) | |
298 s = repo.store | 380 s = repo.store |
299 s.fncache._load() | 381 s.fncache._load() |
300 def d(): | 382 def d(): |
301 for p in s.fncache.entries: | 383 for p in s.fncache.entries: |
302 s.encode(p) | 384 s.encode(p) |
303 timer(d) | 385 timer(d) |
386 fm.end() | |
304 | 387 |
305 @command('perfdiffwd') | 388 @command('perfdiffwd') |
306 def perfdiffwd(ui, repo): | 389 def perfdiffwd(ui, repo): |
307 """Profile diff of working directory changes""" | 390 """Profile diff of working directory changes""" |
391 timer, fm = gettimer(ui) | |
308 options = { | 392 options = { |
309 'w': 'ignore_all_space', | 393 'w': 'ignore_all_space', |
310 'b': 'ignore_space_change', | 394 'b': 'ignore_space_change', |
311 'B': 'ignore_blank_lines', | 395 'B': 'ignore_blank_lines', |
312 } | 396 } |
317 ui.pushbuffer() | 401 ui.pushbuffer() |
318 commands.diff(ui, repo, **opts) | 402 commands.diff(ui, repo, **opts) |
319 ui.popbuffer() | 403 ui.popbuffer() |
320 title = 'diffopts: %s' % (diffopt and ('-' + diffopt) or 'none') | 404 title = 'diffopts: %s' % (diffopt and ('-' + diffopt) or 'none') |
321 timer(d, title) | 405 timer(d, title) |
406 fm.end() | |
322 | 407 |
323 @command('perfrevlog', | 408 @command('perfrevlog', |
324 [('d', 'dist', 100, 'distance between the revisions')], | 409 [('d', 'dist', 100, 'distance between the revisions')], |
325 "[INDEXFILE]") | 410 "[INDEXFILE]") |
326 def perfrevlog(ui, repo, file_, **opts): | 411 def perfrevlog(ui, repo, file_, **opts): |
412 timer, fm = gettimer(ui) | |
327 from mercurial import revlog | 413 from mercurial import revlog |
328 dist = opts['dist'] | 414 dist = opts['dist'] |
329 def d(): | 415 def d(): |
330 r = revlog.revlog(lambda fn: open(fn, 'rb'), file_) | 416 r = revlog.revlog(lambda fn: open(fn, 'rb'), file_) |
331 for x in xrange(0, len(r), dist): | 417 for x in xrange(0, len(r), dist): |
332 r.revision(r.node(x)) | 418 r.revision(r.node(x)) |
333 | 419 |
334 timer(d) | 420 timer(d) |
421 fm.end() | |
335 | 422 |
336 @command('perfrevset', | 423 @command('perfrevset', |
337 [('C', 'clear', False, 'clear volatile cache between each call.')], | 424 [('C', 'clear', False, 'clear volatile cache between each call.')], |
338 "REVSET") | 425 "REVSET") |
339 def perfrevset(ui, repo, expr, clear=False): | 426 def perfrevset(ui, repo, expr, clear=False): |
340 """benchmark the execution time of a revset | 427 """benchmark the execution time of a revset |
341 | 428 |
342 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 |
343 revisions set cache on the revset execution. Volatile cache hold filtered | 430 revisions set cache on the revset execution. Volatile cache hold filtered |
344 and obsolete related cache.""" | 431 and obsolete related cache.""" |
432 timer, fm = gettimer(ui) | |
345 def d(): | 433 def d(): |
346 if clear: | 434 if clear: |
347 repo.invalidatevolatilesets() | 435 repo.invalidatevolatilesets() |
348 for r in repo.revs(expr): pass | 436 for r in repo.revs(expr): pass |
349 timer(d) | 437 timer(d) |
438 fm.end() | |
350 | 439 |
351 @command('perfvolatilesets') | 440 @command('perfvolatilesets') |
352 def perfvolatilesets(ui, repo, *names): | 441 def perfvolatilesets(ui, repo, *names): |
353 """benchmark the computation of various volatile set | 442 """benchmark the computation of various volatile set |
354 | 443 |
355 Volatile set computes element related to filtering and obsolescence.""" | 444 Volatile set computes element related to filtering and obsolescence.""" |
445 timer, fm = gettimer(ui) | |
356 repo = repo.unfiltered() | 446 repo = repo.unfiltered() |
357 | 447 |
358 def getobs(name): | 448 def getobs(name): |
359 def d(): | 449 def d(): |
360 repo.invalidatevolatilesets() | 450 repo.invalidatevolatilesets() |
378 if names: | 468 if names: |
379 allfilter = [n for n in allfilter if n in names] | 469 allfilter = [n for n in allfilter if n in names] |
380 | 470 |
381 for name in allfilter: | 471 for name in allfilter: |
382 timer(getfiltered(name), title=name) | 472 timer(getfiltered(name), title=name) |
473 fm.end() | |
383 | 474 |
384 @command('perfbranchmap', | 475 @command('perfbranchmap', |
385 [('f', 'full', False, | 476 [('f', 'full', False, |
386 'Includes build time of subset'), | 477 'Includes build time of subset'), |
387 ]) | 478 ]) |
388 def perfbranchmap(ui, repo, full=False): | 479 def perfbranchmap(ui, repo, full=False): |
389 """benchmark the update of a branchmap | 480 """benchmark the update of a branchmap |
390 | 481 |
391 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 |
392 """ | 483 """ |
484 timer, fm = gettimer(ui) | |
393 def getbranchmap(filtername): | 485 def getbranchmap(filtername): |
394 """generate a benchmark function for the filtername""" | 486 """generate a benchmark function for the filtername""" |
395 if filtername is None: | 487 if filtername is None: |
396 view = repo | 488 view = repo |
397 else: | 489 else: |
430 for name in allfilters: | 522 for name in allfilters: |
431 timer(getbranchmap(name), title=str(name)) | 523 timer(getbranchmap(name), title=str(name)) |
432 finally: | 524 finally: |
433 branchmap.read = oldread | 525 branchmap.read = oldread |
434 branchmap.branchcache.write = oldwrite | 526 branchmap.branchcache.write = oldwrite |
527 fm.end() |