##// END OF EJS Templates
perf: don't convert rev to node before calling revlog.revision()
Gregory Szorc -
r32225:73c3e226 default
parent child Browse files
Show More
@@ -1,1321 +1,1321 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 # "historical portability" policy of perf.py:
4 # "historical portability" policy of perf.py:
5 #
5 #
6 # We have to do:
6 # We have to do:
7 # - make perf.py "loadable" with as wide Mercurial version as possible
7 # - make perf.py "loadable" with as wide Mercurial version as possible
8 # This doesn't mean that perf commands work correctly with that Mercurial.
8 # This doesn't mean that perf commands work correctly with that Mercurial.
9 # BTW, perf.py itself has been available since 1.1 (or eb240755386d).
9 # BTW, perf.py itself has been available since 1.1 (or eb240755386d).
10 # - make historical perf command work correctly with as wide Mercurial
10 # - make historical perf command work correctly with as wide Mercurial
11 # version as possible
11 # version as possible
12 #
12 #
13 # We have to do, if possible with reasonable cost:
13 # We have to do, if possible with reasonable cost:
14 # - make recent perf command for historical feature work correctly
14 # - make recent perf command for historical feature work correctly
15 # with early Mercurial
15 # with early Mercurial
16 #
16 #
17 # We don't have to do:
17 # We don't have to do:
18 # - make perf command for recent feature work correctly with early
18 # - make perf command for recent feature work correctly with early
19 # Mercurial
19 # Mercurial
20
20
21 from __future__ import absolute_import
21 from __future__ import absolute_import
22 import functools
22 import functools
23 import gc
23 import gc
24 import os
24 import os
25 import random
25 import random
26 import sys
26 import sys
27 import time
27 import time
28 from mercurial import (
28 from mercurial import (
29 changegroup,
29 changegroup,
30 cmdutil,
30 cmdutil,
31 commands,
31 commands,
32 copies,
32 copies,
33 error,
33 error,
34 extensions,
34 extensions,
35 mdiff,
35 mdiff,
36 merge,
36 merge,
37 util,
37 util,
38 )
38 )
39
39
40 # for "historical portability":
40 # for "historical portability":
41 # try to import modules separately (in dict order), and ignore
41 # try to import modules separately (in dict order), and ignore
42 # failure, because these aren't available with early Mercurial
42 # failure, because these aren't available with early Mercurial
43 try:
43 try:
44 from mercurial import branchmap # since 2.5 (or bcee63733aad)
44 from mercurial import branchmap # since 2.5 (or bcee63733aad)
45 except ImportError:
45 except ImportError:
46 pass
46 pass
47 try:
47 try:
48 from mercurial import obsolete # since 2.3 (or ad0d6c2b3279)
48 from mercurial import obsolete # since 2.3 (or ad0d6c2b3279)
49 except ImportError:
49 except ImportError:
50 pass
50 pass
51 try:
51 try:
52 from mercurial import repoview # since 2.5 (or 3a6ddacb7198)
52 from mercurial import repoview # since 2.5 (or 3a6ddacb7198)
53 except ImportError:
53 except ImportError:
54 pass
54 pass
55 try:
55 try:
56 from mercurial import scmutil # since 1.9 (or 8b252e826c68)
56 from mercurial import scmutil # since 1.9 (or 8b252e826c68)
57 except ImportError:
57 except ImportError:
58 pass
58 pass
59
59
60 # for "historical portability":
60 # for "historical portability":
61 # define util.safehasattr forcibly, because util.safehasattr has been
61 # define util.safehasattr forcibly, because util.safehasattr has been
62 # available since 1.9.3 (or 94b200a11cf7)
62 # available since 1.9.3 (or 94b200a11cf7)
63 _undefined = object()
63 _undefined = object()
64 def safehasattr(thing, attr):
64 def safehasattr(thing, attr):
65 return getattr(thing, attr, _undefined) is not _undefined
65 return getattr(thing, attr, _undefined) is not _undefined
66 setattr(util, 'safehasattr', safehasattr)
66 setattr(util, 'safehasattr', safehasattr)
67
67
68 # for "historical portability":
68 # for "historical portability":
69 # define util.timer forcibly, because util.timer has been available
69 # define util.timer forcibly, because util.timer has been available
70 # since ae5d60bb70c9
70 # since ae5d60bb70c9
71 if safehasattr(time, 'perf_counter'):
71 if safehasattr(time, 'perf_counter'):
72 util.timer = time.perf_counter
72 util.timer = time.perf_counter
73 elif os.name == 'nt':
73 elif os.name == 'nt':
74 util.timer = time.clock
74 util.timer = time.clock
75 else:
75 else:
76 util.timer = time.time
76 util.timer = time.time
77
77
78 # for "historical portability":
78 # for "historical portability":
79 # use locally defined empty option list, if formatteropts isn't
79 # use locally defined empty option list, if formatteropts isn't
80 # available, because commands.formatteropts has been available since
80 # available, because commands.formatteropts has been available since
81 # 3.2 (or 7a7eed5176a4), even though formatting itself has been
81 # 3.2 (or 7a7eed5176a4), even though formatting itself has been
82 # available since 2.2 (or ae5f92e154d3)
82 # available since 2.2 (or ae5f92e154d3)
83 formatteropts = getattr(commands, "formatteropts", [])
83 formatteropts = getattr(commands, "formatteropts", [])
84
84
85 # for "historical portability":
85 # for "historical portability":
86 # use locally defined option list, if debugrevlogopts isn't available,
86 # use locally defined option list, if debugrevlogopts isn't available,
87 # because commands.debugrevlogopts has been available since 3.7 (or
87 # because commands.debugrevlogopts has been available since 3.7 (or
88 # 5606f7d0d063), even though cmdutil.openrevlog() has been available
88 # 5606f7d0d063), even though cmdutil.openrevlog() has been available
89 # since 1.9 (or a79fea6b3e77).
89 # since 1.9 (or a79fea6b3e77).
90 revlogopts = getattr(commands, "debugrevlogopts", [
90 revlogopts = getattr(commands, "debugrevlogopts", [
91 ('c', 'changelog', False, ('open changelog')),
91 ('c', 'changelog', False, ('open changelog')),
92 ('m', 'manifest', False, ('open manifest')),
92 ('m', 'manifest', False, ('open manifest')),
93 ('', 'dir', False, ('open directory manifest')),
93 ('', 'dir', False, ('open directory manifest')),
94 ])
94 ])
95
95
96 cmdtable = {}
96 cmdtable = {}
97
97
98 # for "historical portability":
98 # for "historical portability":
99 # define parsealiases locally, because cmdutil.parsealiases has been
99 # define parsealiases locally, because cmdutil.parsealiases has been
100 # available since 1.5 (or 6252852b4332)
100 # available since 1.5 (or 6252852b4332)
101 def parsealiases(cmd):
101 def parsealiases(cmd):
102 return cmd.lstrip("^").split("|")
102 return cmd.lstrip("^").split("|")
103
103
104 if safehasattr(cmdutil, 'command'):
104 if safehasattr(cmdutil, 'command'):
105 import inspect
105 import inspect
106 command = cmdutil.command(cmdtable)
106 command = cmdutil.command(cmdtable)
107 if 'norepo' not in inspect.getargspec(command)[0]:
107 if 'norepo' not in inspect.getargspec(command)[0]:
108 # for "historical portability":
108 # for "historical portability":
109 # wrap original cmdutil.command, because "norepo" option has
109 # wrap original cmdutil.command, because "norepo" option has
110 # been available since 3.1 (or 75a96326cecb)
110 # been available since 3.1 (or 75a96326cecb)
111 _command = command
111 _command = command
112 def command(name, options=(), synopsis=None, norepo=False):
112 def command(name, options=(), synopsis=None, norepo=False):
113 if norepo:
113 if norepo:
114 commands.norepo += ' %s' % ' '.join(parsealiases(name))
114 commands.norepo += ' %s' % ' '.join(parsealiases(name))
115 return _command(name, list(options), synopsis)
115 return _command(name, list(options), synopsis)
116 else:
116 else:
117 # for "historical portability":
117 # for "historical portability":
118 # define "@command" annotation locally, because cmdutil.command
118 # define "@command" annotation locally, because cmdutil.command
119 # has been available since 1.9 (or 2daa5179e73f)
119 # has been available since 1.9 (or 2daa5179e73f)
120 def command(name, options=(), synopsis=None, norepo=False):
120 def command(name, options=(), synopsis=None, norepo=False):
121 def decorator(func):
121 def decorator(func):
122 if synopsis:
122 if synopsis:
123 cmdtable[name] = func, list(options), synopsis
123 cmdtable[name] = func, list(options), synopsis
124 else:
124 else:
125 cmdtable[name] = func, list(options)
125 cmdtable[name] = func, list(options)
126 if norepo:
126 if norepo:
127 commands.norepo += ' %s' % ' '.join(parsealiases(name))
127 commands.norepo += ' %s' % ' '.join(parsealiases(name))
128 return func
128 return func
129 return decorator
129 return decorator
130
130
131 def getlen(ui):
131 def getlen(ui):
132 if ui.configbool("perf", "stub"):
132 if ui.configbool("perf", "stub"):
133 return lambda x: 1
133 return lambda x: 1
134 return len
134 return len
135
135
136 def gettimer(ui, opts=None):
136 def gettimer(ui, opts=None):
137 """return a timer function and formatter: (timer, formatter)
137 """return a timer function and formatter: (timer, formatter)
138
138
139 This function exists to gather the creation of formatter in a single
139 This function exists to gather the creation of formatter in a single
140 place instead of duplicating it in all performance commands."""
140 place instead of duplicating it in all performance commands."""
141
141
142 # enforce an idle period before execution to counteract power management
142 # enforce an idle period before execution to counteract power management
143 # experimental config: perf.presleep
143 # experimental config: perf.presleep
144 time.sleep(getint(ui, "perf", "presleep", 1))
144 time.sleep(getint(ui, "perf", "presleep", 1))
145
145
146 if opts is None:
146 if opts is None:
147 opts = {}
147 opts = {}
148 # redirect all to stderr unless buffer api is in use
148 # redirect all to stderr unless buffer api is in use
149 if not ui._buffers:
149 if not ui._buffers:
150 ui = ui.copy()
150 ui = ui.copy()
151 uifout = safeattrsetter(ui, 'fout', ignoremissing=True)
151 uifout = safeattrsetter(ui, 'fout', ignoremissing=True)
152 if uifout:
152 if uifout:
153 # for "historical portability":
153 # for "historical portability":
154 # ui.fout/ferr have been available since 1.9 (or 4e1ccd4c2b6d)
154 # ui.fout/ferr have been available since 1.9 (or 4e1ccd4c2b6d)
155 uifout.set(ui.ferr)
155 uifout.set(ui.ferr)
156
156
157 # get a formatter
157 # get a formatter
158 uiformatter = getattr(ui, 'formatter', None)
158 uiformatter = getattr(ui, 'formatter', None)
159 if uiformatter:
159 if uiformatter:
160 fm = uiformatter('perf', opts)
160 fm = uiformatter('perf', opts)
161 else:
161 else:
162 # for "historical portability":
162 # for "historical portability":
163 # define formatter locally, because ui.formatter has been
163 # define formatter locally, because ui.formatter has been
164 # available since 2.2 (or ae5f92e154d3)
164 # available since 2.2 (or ae5f92e154d3)
165 from mercurial import node
165 from mercurial import node
166 class defaultformatter(object):
166 class defaultformatter(object):
167 """Minimized composition of baseformatter and plainformatter
167 """Minimized composition of baseformatter and plainformatter
168 """
168 """
169 def __init__(self, ui, topic, opts):
169 def __init__(self, ui, topic, opts):
170 self._ui = ui
170 self._ui = ui
171 if ui.debugflag:
171 if ui.debugflag:
172 self.hexfunc = node.hex
172 self.hexfunc = node.hex
173 else:
173 else:
174 self.hexfunc = node.short
174 self.hexfunc = node.short
175 def __nonzero__(self):
175 def __nonzero__(self):
176 return False
176 return False
177 __bool__ = __nonzero__
177 __bool__ = __nonzero__
178 def startitem(self):
178 def startitem(self):
179 pass
179 pass
180 def data(self, **data):
180 def data(self, **data):
181 pass
181 pass
182 def write(self, fields, deftext, *fielddata, **opts):
182 def write(self, fields, deftext, *fielddata, **opts):
183 self._ui.write(deftext % fielddata, **opts)
183 self._ui.write(deftext % fielddata, **opts)
184 def condwrite(self, cond, fields, deftext, *fielddata, **opts):
184 def condwrite(self, cond, fields, deftext, *fielddata, **opts):
185 if cond:
185 if cond:
186 self._ui.write(deftext % fielddata, **opts)
186 self._ui.write(deftext % fielddata, **opts)
187 def plain(self, text, **opts):
187 def plain(self, text, **opts):
188 self._ui.write(text, **opts)
188 self._ui.write(text, **opts)
189 def end(self):
189 def end(self):
190 pass
190 pass
191 fm = defaultformatter(ui, 'perf', opts)
191 fm = defaultformatter(ui, 'perf', opts)
192
192
193 # stub function, runs code only once instead of in a loop
193 # stub function, runs code only once instead of in a loop
194 # experimental config: perf.stub
194 # experimental config: perf.stub
195 if ui.configbool("perf", "stub"):
195 if ui.configbool("perf", "stub"):
196 return functools.partial(stub_timer, fm), fm
196 return functools.partial(stub_timer, fm), fm
197 return functools.partial(_timer, fm), fm
197 return functools.partial(_timer, fm), fm
198
198
199 def stub_timer(fm, func, title=None):
199 def stub_timer(fm, func, title=None):
200 func()
200 func()
201
201
202 def _timer(fm, func, title=None):
202 def _timer(fm, func, title=None):
203 gc.collect()
203 gc.collect()
204 results = []
204 results = []
205 begin = util.timer()
205 begin = util.timer()
206 count = 0
206 count = 0
207 while True:
207 while True:
208 ostart = os.times()
208 ostart = os.times()
209 cstart = util.timer()
209 cstart = util.timer()
210 r = func()
210 r = func()
211 cstop = util.timer()
211 cstop = util.timer()
212 ostop = os.times()
212 ostop = os.times()
213 count += 1
213 count += 1
214 a, b = ostart, ostop
214 a, b = ostart, ostop
215 results.append((cstop - cstart, b[0] - a[0], b[1]-a[1]))
215 results.append((cstop - cstart, b[0] - a[0], b[1]-a[1]))
216 if cstop - begin > 3 and count >= 100:
216 if cstop - begin > 3 and count >= 100:
217 break
217 break
218 if cstop - begin > 10 and count >= 3:
218 if cstop - begin > 10 and count >= 3:
219 break
219 break
220
220
221 fm.startitem()
221 fm.startitem()
222
222
223 if title:
223 if title:
224 fm.write('title', '! %s\n', title)
224 fm.write('title', '! %s\n', title)
225 if r:
225 if r:
226 fm.write('result', '! result: %s\n', r)
226 fm.write('result', '! result: %s\n', r)
227 m = min(results)
227 m = min(results)
228 fm.plain('!')
228 fm.plain('!')
229 fm.write('wall', ' wall %f', m[0])
229 fm.write('wall', ' wall %f', m[0])
230 fm.write('comb', ' comb %f', m[1] + m[2])
230 fm.write('comb', ' comb %f', m[1] + m[2])
231 fm.write('user', ' user %f', m[1])
231 fm.write('user', ' user %f', m[1])
232 fm.write('sys', ' sys %f', m[2])
232 fm.write('sys', ' sys %f', m[2])
233 fm.write('count', ' (best of %d)', count)
233 fm.write('count', ' (best of %d)', count)
234 fm.plain('\n')
234 fm.plain('\n')
235
235
236 # utilities for historical portability
236 # utilities for historical portability
237
237
238 def getint(ui, section, name, default):
238 def getint(ui, section, name, default):
239 # for "historical portability":
239 # for "historical portability":
240 # ui.configint has been available since 1.9 (or fa2b596db182)
240 # ui.configint has been available since 1.9 (or fa2b596db182)
241 v = ui.config(section, name, None)
241 v = ui.config(section, name, None)
242 if v is None:
242 if v is None:
243 return default
243 return default
244 try:
244 try:
245 return int(v)
245 return int(v)
246 except ValueError:
246 except ValueError:
247 raise error.ConfigError(("%s.%s is not an integer ('%s')")
247 raise error.ConfigError(("%s.%s is not an integer ('%s')")
248 % (section, name, v))
248 % (section, name, v))
249
249
250 def safeattrsetter(obj, name, ignoremissing=False):
250 def safeattrsetter(obj, name, ignoremissing=False):
251 """Ensure that 'obj' has 'name' attribute before subsequent setattr
251 """Ensure that 'obj' has 'name' attribute before subsequent setattr
252
252
253 This function is aborted, if 'obj' doesn't have 'name' attribute
253 This function is aborted, if 'obj' doesn't have 'name' attribute
254 at runtime. This avoids overlooking removal of an attribute, which
254 at runtime. This avoids overlooking removal of an attribute, which
255 breaks assumption of performance measurement, in the future.
255 breaks assumption of performance measurement, in the future.
256
256
257 This function returns the object to (1) assign a new value, and
257 This function returns the object to (1) assign a new value, and
258 (2) restore an original value to the attribute.
258 (2) restore an original value to the attribute.
259
259
260 If 'ignoremissing' is true, missing 'name' attribute doesn't cause
260 If 'ignoremissing' is true, missing 'name' attribute doesn't cause
261 abortion, and this function returns None. This is useful to
261 abortion, and this function returns None. This is useful to
262 examine an attribute, which isn't ensured in all Mercurial
262 examine an attribute, which isn't ensured in all Mercurial
263 versions.
263 versions.
264 """
264 """
265 if not util.safehasattr(obj, name):
265 if not util.safehasattr(obj, name):
266 if ignoremissing:
266 if ignoremissing:
267 return None
267 return None
268 raise error.Abort(("missing attribute %s of %s might break assumption"
268 raise error.Abort(("missing attribute %s of %s might break assumption"
269 " of performance measurement") % (name, obj))
269 " of performance measurement") % (name, obj))
270
270
271 origvalue = getattr(obj, name)
271 origvalue = getattr(obj, name)
272 class attrutil(object):
272 class attrutil(object):
273 def set(self, newvalue):
273 def set(self, newvalue):
274 setattr(obj, name, newvalue)
274 setattr(obj, name, newvalue)
275 def restore(self):
275 def restore(self):
276 setattr(obj, name, origvalue)
276 setattr(obj, name, origvalue)
277
277
278 return attrutil()
278 return attrutil()
279
279
280 # utilities to examine each internal API changes
280 # utilities to examine each internal API changes
281
281
282 def getbranchmapsubsettable():
282 def getbranchmapsubsettable():
283 # for "historical portability":
283 # for "historical portability":
284 # subsettable is defined in:
284 # subsettable is defined in:
285 # - branchmap since 2.9 (or 175c6fd8cacc)
285 # - branchmap since 2.9 (or 175c6fd8cacc)
286 # - repoview since 2.5 (or 59a9f18d4587)
286 # - repoview since 2.5 (or 59a9f18d4587)
287 for mod in (branchmap, repoview):
287 for mod in (branchmap, repoview):
288 subsettable = getattr(mod, 'subsettable', None)
288 subsettable = getattr(mod, 'subsettable', None)
289 if subsettable:
289 if subsettable:
290 return subsettable
290 return subsettable
291
291
292 # bisecting in bcee63733aad::59a9f18d4587 can reach here (both
292 # bisecting in bcee63733aad::59a9f18d4587 can reach here (both
293 # branchmap and repoview modules exist, but subsettable attribute
293 # branchmap and repoview modules exist, but subsettable attribute
294 # doesn't)
294 # doesn't)
295 raise error.Abort(("perfbranchmap not available with this Mercurial"),
295 raise error.Abort(("perfbranchmap not available with this Mercurial"),
296 hint="use 2.5 or later")
296 hint="use 2.5 or later")
297
297
298 def getsvfs(repo):
298 def getsvfs(repo):
299 """Return appropriate object to access files under .hg/store
299 """Return appropriate object to access files under .hg/store
300 """
300 """
301 # for "historical portability":
301 # for "historical portability":
302 # repo.svfs has been available since 2.3 (or 7034365089bf)
302 # repo.svfs has been available since 2.3 (or 7034365089bf)
303 svfs = getattr(repo, 'svfs', None)
303 svfs = getattr(repo, 'svfs', None)
304 if svfs:
304 if svfs:
305 return svfs
305 return svfs
306 else:
306 else:
307 return getattr(repo, 'sopener')
307 return getattr(repo, 'sopener')
308
308
309 def getvfs(repo):
309 def getvfs(repo):
310 """Return appropriate object to access files under .hg
310 """Return appropriate object to access files under .hg
311 """
311 """
312 # for "historical portability":
312 # for "historical portability":
313 # repo.vfs has been available since 2.3 (or 7034365089bf)
313 # repo.vfs has been available since 2.3 (or 7034365089bf)
314 vfs = getattr(repo, 'vfs', None)
314 vfs = getattr(repo, 'vfs', None)
315 if vfs:
315 if vfs:
316 return vfs
316 return vfs
317 else:
317 else:
318 return getattr(repo, 'opener')
318 return getattr(repo, 'opener')
319
319
320 def repocleartagscachefunc(repo):
320 def repocleartagscachefunc(repo):
321 """Return the function to clear tags cache according to repo internal API
321 """Return the function to clear tags cache according to repo internal API
322 """
322 """
323 if util.safehasattr(repo, '_tagscache'): # since 2.0 (or 9dca7653b525)
323 if util.safehasattr(repo, '_tagscache'): # since 2.0 (or 9dca7653b525)
324 # in this case, setattr(repo, '_tagscache', None) or so isn't
324 # in this case, setattr(repo, '_tagscache', None) or so isn't
325 # correct way to clear tags cache, because existing code paths
325 # correct way to clear tags cache, because existing code paths
326 # expect _tagscache to be a structured object.
326 # expect _tagscache to be a structured object.
327 def clearcache():
327 def clearcache():
328 # _tagscache has been filteredpropertycache since 2.5 (or
328 # _tagscache has been filteredpropertycache since 2.5 (or
329 # 98c867ac1330), and delattr() can't work in such case
329 # 98c867ac1330), and delattr() can't work in such case
330 if '_tagscache' in vars(repo):
330 if '_tagscache' in vars(repo):
331 del repo.__dict__['_tagscache']
331 del repo.__dict__['_tagscache']
332 return clearcache
332 return clearcache
333
333
334 repotags = safeattrsetter(repo, '_tags', ignoremissing=True)
334 repotags = safeattrsetter(repo, '_tags', ignoremissing=True)
335 if repotags: # since 1.4 (or 5614a628d173)
335 if repotags: # since 1.4 (or 5614a628d173)
336 return lambda : repotags.set(None)
336 return lambda : repotags.set(None)
337
337
338 repotagscache = safeattrsetter(repo, 'tagscache', ignoremissing=True)
338 repotagscache = safeattrsetter(repo, 'tagscache', ignoremissing=True)
339 if repotagscache: # since 0.6 (or d7df759d0e97)
339 if repotagscache: # since 0.6 (or d7df759d0e97)
340 return lambda : repotagscache.set(None)
340 return lambda : repotagscache.set(None)
341
341
342 # Mercurial earlier than 0.6 (or d7df759d0e97) logically reaches
342 # Mercurial earlier than 0.6 (or d7df759d0e97) logically reaches
343 # this point, but it isn't so problematic, because:
343 # this point, but it isn't so problematic, because:
344 # - repo.tags of such Mercurial isn't "callable", and repo.tags()
344 # - repo.tags of such Mercurial isn't "callable", and repo.tags()
345 # in perftags() causes failure soon
345 # in perftags() causes failure soon
346 # - perf.py itself has been available since 1.1 (or eb240755386d)
346 # - perf.py itself has been available since 1.1 (or eb240755386d)
347 raise error.Abort(("tags API of this hg command is unknown"))
347 raise error.Abort(("tags API of this hg command is unknown"))
348
348
349 # perf commands
349 # perf commands
350
350
351 @command('perfwalk', formatteropts)
351 @command('perfwalk', formatteropts)
352 def perfwalk(ui, repo, *pats, **opts):
352 def perfwalk(ui, repo, *pats, **opts):
353 timer, fm = gettimer(ui, opts)
353 timer, fm = gettimer(ui, opts)
354 try:
354 try:
355 m = scmutil.match(repo[None], pats, {})
355 m = scmutil.match(repo[None], pats, {})
356 timer(lambda: len(list(repo.dirstate.walk(m, [], True, False))))
356 timer(lambda: len(list(repo.dirstate.walk(m, [], True, False))))
357 except Exception:
357 except Exception:
358 try:
358 try:
359 m = scmutil.match(repo[None], pats, {})
359 m = scmutil.match(repo[None], pats, {})
360 timer(lambda: len([b for a, b, c in repo.dirstate.statwalk([], m)]))
360 timer(lambda: len([b for a, b, c in repo.dirstate.statwalk([], m)]))
361 except Exception:
361 except Exception:
362 timer(lambda: len(list(cmdutil.walk(repo, pats, {}))))
362 timer(lambda: len(list(cmdutil.walk(repo, pats, {}))))
363 fm.end()
363 fm.end()
364
364
365 @command('perfannotate', formatteropts)
365 @command('perfannotate', formatteropts)
366 def perfannotate(ui, repo, f, **opts):
366 def perfannotate(ui, repo, f, **opts):
367 timer, fm = gettimer(ui, opts)
367 timer, fm = gettimer(ui, opts)
368 fc = repo['.'][f]
368 fc = repo['.'][f]
369 timer(lambda: len(fc.annotate(True)))
369 timer(lambda: len(fc.annotate(True)))
370 fm.end()
370 fm.end()
371
371
372 @command('perfstatus',
372 @command('perfstatus',
373 [('u', 'unknown', False,
373 [('u', 'unknown', False,
374 'ask status to look for unknown files')] + formatteropts)
374 'ask status to look for unknown files')] + formatteropts)
375 def perfstatus(ui, repo, **opts):
375 def perfstatus(ui, repo, **opts):
376 #m = match.always(repo.root, repo.getcwd())
376 #m = match.always(repo.root, repo.getcwd())
377 #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False,
377 #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False,
378 # False))))
378 # False))))
379 timer, fm = gettimer(ui, opts)
379 timer, fm = gettimer(ui, opts)
380 timer(lambda: sum(map(len, repo.status(unknown=opts['unknown']))))
380 timer(lambda: sum(map(len, repo.status(unknown=opts['unknown']))))
381 fm.end()
381 fm.end()
382
382
383 @command('perfaddremove', formatteropts)
383 @command('perfaddremove', formatteropts)
384 def perfaddremove(ui, repo, **opts):
384 def perfaddremove(ui, repo, **opts):
385 timer, fm = gettimer(ui, opts)
385 timer, fm = gettimer(ui, opts)
386 try:
386 try:
387 oldquiet = repo.ui.quiet
387 oldquiet = repo.ui.quiet
388 repo.ui.quiet = True
388 repo.ui.quiet = True
389 matcher = scmutil.match(repo[None])
389 matcher = scmutil.match(repo[None])
390 timer(lambda: scmutil.addremove(repo, matcher, "", dry_run=True))
390 timer(lambda: scmutil.addremove(repo, matcher, "", dry_run=True))
391 finally:
391 finally:
392 repo.ui.quiet = oldquiet
392 repo.ui.quiet = oldquiet
393 fm.end()
393 fm.end()
394
394
395 def clearcaches(cl):
395 def clearcaches(cl):
396 # behave somewhat consistently across internal API changes
396 # behave somewhat consistently across internal API changes
397 if util.safehasattr(cl, 'clearcaches'):
397 if util.safehasattr(cl, 'clearcaches'):
398 cl.clearcaches()
398 cl.clearcaches()
399 elif util.safehasattr(cl, '_nodecache'):
399 elif util.safehasattr(cl, '_nodecache'):
400 from mercurial.node import nullid, nullrev
400 from mercurial.node import nullid, nullrev
401 cl._nodecache = {nullid: nullrev}
401 cl._nodecache = {nullid: nullrev}
402 cl._nodepos = None
402 cl._nodepos = None
403
403
404 @command('perfheads', formatteropts)
404 @command('perfheads', formatteropts)
405 def perfheads(ui, repo, **opts):
405 def perfheads(ui, repo, **opts):
406 timer, fm = gettimer(ui, opts)
406 timer, fm = gettimer(ui, opts)
407 cl = repo.changelog
407 cl = repo.changelog
408 def d():
408 def d():
409 len(cl.headrevs())
409 len(cl.headrevs())
410 clearcaches(cl)
410 clearcaches(cl)
411 timer(d)
411 timer(d)
412 fm.end()
412 fm.end()
413
413
414 @command('perftags', formatteropts)
414 @command('perftags', formatteropts)
415 def perftags(ui, repo, **opts):
415 def perftags(ui, repo, **opts):
416 import mercurial.changelog
416 import mercurial.changelog
417 import mercurial.manifest
417 import mercurial.manifest
418 timer, fm = gettimer(ui, opts)
418 timer, fm = gettimer(ui, opts)
419 svfs = getsvfs(repo)
419 svfs = getsvfs(repo)
420 repocleartagscache = repocleartagscachefunc(repo)
420 repocleartagscache = repocleartagscachefunc(repo)
421 def t():
421 def t():
422 repo.changelog = mercurial.changelog.changelog(svfs)
422 repo.changelog = mercurial.changelog.changelog(svfs)
423 repo.manifestlog = mercurial.manifest.manifestlog(svfs, repo)
423 repo.manifestlog = mercurial.manifest.manifestlog(svfs, repo)
424 repocleartagscache()
424 repocleartagscache()
425 return len(repo.tags())
425 return len(repo.tags())
426 timer(t)
426 timer(t)
427 fm.end()
427 fm.end()
428
428
429 @command('perfancestors', formatteropts)
429 @command('perfancestors', formatteropts)
430 def perfancestors(ui, repo, **opts):
430 def perfancestors(ui, repo, **opts):
431 timer, fm = gettimer(ui, opts)
431 timer, fm = gettimer(ui, opts)
432 heads = repo.changelog.headrevs()
432 heads = repo.changelog.headrevs()
433 def d():
433 def d():
434 for a in repo.changelog.ancestors(heads):
434 for a in repo.changelog.ancestors(heads):
435 pass
435 pass
436 timer(d)
436 timer(d)
437 fm.end()
437 fm.end()
438
438
439 @command('perfancestorset', formatteropts)
439 @command('perfancestorset', formatteropts)
440 def perfancestorset(ui, repo, revset, **opts):
440 def perfancestorset(ui, repo, revset, **opts):
441 timer, fm = gettimer(ui, opts)
441 timer, fm = gettimer(ui, opts)
442 revs = repo.revs(revset)
442 revs = repo.revs(revset)
443 heads = repo.changelog.headrevs()
443 heads = repo.changelog.headrevs()
444 def d():
444 def d():
445 s = repo.changelog.ancestors(heads)
445 s = repo.changelog.ancestors(heads)
446 for rev in revs:
446 for rev in revs:
447 rev in s
447 rev in s
448 timer(d)
448 timer(d)
449 fm.end()
449 fm.end()
450
450
451 @command('perfchangegroupchangelog', formatteropts +
451 @command('perfchangegroupchangelog', formatteropts +
452 [('', 'version', '02', 'changegroup version'),
452 [('', 'version', '02', 'changegroup version'),
453 ('r', 'rev', '', 'revisions to add to changegroup')])
453 ('r', 'rev', '', 'revisions to add to changegroup')])
454 def perfchangegroupchangelog(ui, repo, version='02', rev=None, **opts):
454 def perfchangegroupchangelog(ui, repo, version='02', rev=None, **opts):
455 """Benchmark producing a changelog group for a changegroup.
455 """Benchmark producing a changelog group for a changegroup.
456
456
457 This measures the time spent processing the changelog during a
457 This measures the time spent processing the changelog during a
458 bundle operation. This occurs during `hg bundle` and on a server
458 bundle operation. This occurs during `hg bundle` and on a server
459 processing a `getbundle` wire protocol request (handles clones
459 processing a `getbundle` wire protocol request (handles clones
460 and pull requests).
460 and pull requests).
461
461
462 By default, all revisions are added to the changegroup.
462 By default, all revisions are added to the changegroup.
463 """
463 """
464 cl = repo.changelog
464 cl = repo.changelog
465 revs = [cl.lookup(r) for r in repo.revs(rev or 'all()')]
465 revs = [cl.lookup(r) for r in repo.revs(rev or 'all()')]
466 bundler = changegroup.getbundler(version, repo)
466 bundler = changegroup.getbundler(version, repo)
467
467
468 def lookup(node):
468 def lookup(node):
469 # The real bundler reads the revision in order to access the
469 # The real bundler reads the revision in order to access the
470 # manifest node and files list. Do that here.
470 # manifest node and files list. Do that here.
471 cl.read(node)
471 cl.read(node)
472 return node
472 return node
473
473
474 def d():
474 def d():
475 for chunk in bundler.group(revs, cl, lookup):
475 for chunk in bundler.group(revs, cl, lookup):
476 pass
476 pass
477
477
478 timer, fm = gettimer(ui, opts)
478 timer, fm = gettimer(ui, opts)
479 timer(d)
479 timer(d)
480 fm.end()
480 fm.end()
481
481
482 @command('perfdirs', formatteropts)
482 @command('perfdirs', formatteropts)
483 def perfdirs(ui, repo, **opts):
483 def perfdirs(ui, repo, **opts):
484 timer, fm = gettimer(ui, opts)
484 timer, fm = gettimer(ui, opts)
485 dirstate = repo.dirstate
485 dirstate = repo.dirstate
486 'a' in dirstate
486 'a' in dirstate
487 def d():
487 def d():
488 dirstate.dirs()
488 dirstate.dirs()
489 del dirstate._dirs
489 del dirstate._dirs
490 timer(d)
490 timer(d)
491 fm.end()
491 fm.end()
492
492
493 @command('perfdirstate', formatteropts)
493 @command('perfdirstate', formatteropts)
494 def perfdirstate(ui, repo, **opts):
494 def perfdirstate(ui, repo, **opts):
495 timer, fm = gettimer(ui, opts)
495 timer, fm = gettimer(ui, opts)
496 "a" in repo.dirstate
496 "a" in repo.dirstate
497 def d():
497 def d():
498 repo.dirstate.invalidate()
498 repo.dirstate.invalidate()
499 "a" in repo.dirstate
499 "a" in repo.dirstate
500 timer(d)
500 timer(d)
501 fm.end()
501 fm.end()
502
502
503 @command('perfdirstatedirs', formatteropts)
503 @command('perfdirstatedirs', formatteropts)
504 def perfdirstatedirs(ui, repo, **opts):
504 def perfdirstatedirs(ui, repo, **opts):
505 timer, fm = gettimer(ui, opts)
505 timer, fm = gettimer(ui, opts)
506 "a" in repo.dirstate
506 "a" in repo.dirstate
507 def d():
507 def d():
508 "a" in repo.dirstate._dirs
508 "a" in repo.dirstate._dirs
509 del repo.dirstate._dirs
509 del repo.dirstate._dirs
510 timer(d)
510 timer(d)
511 fm.end()
511 fm.end()
512
512
513 @command('perfdirstatefoldmap', formatteropts)
513 @command('perfdirstatefoldmap', formatteropts)
514 def perfdirstatefoldmap(ui, repo, **opts):
514 def perfdirstatefoldmap(ui, repo, **opts):
515 timer, fm = gettimer(ui, opts)
515 timer, fm = gettimer(ui, opts)
516 dirstate = repo.dirstate
516 dirstate = repo.dirstate
517 'a' in dirstate
517 'a' in dirstate
518 def d():
518 def d():
519 dirstate._filefoldmap.get('a')
519 dirstate._filefoldmap.get('a')
520 del dirstate._filefoldmap
520 del dirstate._filefoldmap
521 timer(d)
521 timer(d)
522 fm.end()
522 fm.end()
523
523
524 @command('perfdirfoldmap', formatteropts)
524 @command('perfdirfoldmap', formatteropts)
525 def perfdirfoldmap(ui, repo, **opts):
525 def perfdirfoldmap(ui, repo, **opts):
526 timer, fm = gettimer(ui, opts)
526 timer, fm = gettimer(ui, opts)
527 dirstate = repo.dirstate
527 dirstate = repo.dirstate
528 'a' in dirstate
528 'a' in dirstate
529 def d():
529 def d():
530 dirstate._dirfoldmap.get('a')
530 dirstate._dirfoldmap.get('a')
531 del dirstate._dirfoldmap
531 del dirstate._dirfoldmap
532 del dirstate._dirs
532 del dirstate._dirs
533 timer(d)
533 timer(d)
534 fm.end()
534 fm.end()
535
535
536 @command('perfdirstatewrite', formatteropts)
536 @command('perfdirstatewrite', formatteropts)
537 def perfdirstatewrite(ui, repo, **opts):
537 def perfdirstatewrite(ui, repo, **opts):
538 timer, fm = gettimer(ui, opts)
538 timer, fm = gettimer(ui, opts)
539 ds = repo.dirstate
539 ds = repo.dirstate
540 "a" in ds
540 "a" in ds
541 def d():
541 def d():
542 ds._dirty = True
542 ds._dirty = True
543 ds.write(repo.currenttransaction())
543 ds.write(repo.currenttransaction())
544 timer(d)
544 timer(d)
545 fm.end()
545 fm.end()
546
546
547 @command('perfmergecalculate',
547 @command('perfmergecalculate',
548 [('r', 'rev', '.', 'rev to merge against')] + formatteropts)
548 [('r', 'rev', '.', 'rev to merge against')] + formatteropts)
549 def perfmergecalculate(ui, repo, rev, **opts):
549 def perfmergecalculate(ui, repo, rev, **opts):
550 timer, fm = gettimer(ui, opts)
550 timer, fm = gettimer(ui, opts)
551 wctx = repo[None]
551 wctx = repo[None]
552 rctx = scmutil.revsingle(repo, rev, rev)
552 rctx = scmutil.revsingle(repo, rev, rev)
553 ancestor = wctx.ancestor(rctx)
553 ancestor = wctx.ancestor(rctx)
554 # we don't want working dir files to be stat'd in the benchmark, so prime
554 # we don't want working dir files to be stat'd in the benchmark, so prime
555 # that cache
555 # that cache
556 wctx.dirty()
556 wctx.dirty()
557 def d():
557 def d():
558 # acceptremote is True because we don't want prompts in the middle of
558 # acceptremote is True because we don't want prompts in the middle of
559 # our benchmark
559 # our benchmark
560 merge.calculateupdates(repo, wctx, rctx, [ancestor], False, False,
560 merge.calculateupdates(repo, wctx, rctx, [ancestor], False, False,
561 acceptremote=True, followcopies=True)
561 acceptremote=True, followcopies=True)
562 timer(d)
562 timer(d)
563 fm.end()
563 fm.end()
564
564
565 @command('perfpathcopies', [], "REV REV")
565 @command('perfpathcopies', [], "REV REV")
566 def perfpathcopies(ui, repo, rev1, rev2, **opts):
566 def perfpathcopies(ui, repo, rev1, rev2, **opts):
567 timer, fm = gettimer(ui, opts)
567 timer, fm = gettimer(ui, opts)
568 ctx1 = scmutil.revsingle(repo, rev1, rev1)
568 ctx1 = scmutil.revsingle(repo, rev1, rev1)
569 ctx2 = scmutil.revsingle(repo, rev2, rev2)
569 ctx2 = scmutil.revsingle(repo, rev2, rev2)
570 def d():
570 def d():
571 copies.pathcopies(ctx1, ctx2)
571 copies.pathcopies(ctx1, ctx2)
572 timer(d)
572 timer(d)
573 fm.end()
573 fm.end()
574
574
575 @command('perfmanifest', [], 'REV')
575 @command('perfmanifest', [], 'REV')
576 def perfmanifest(ui, repo, rev, **opts):
576 def perfmanifest(ui, repo, rev, **opts):
577 timer, fm = gettimer(ui, opts)
577 timer, fm = gettimer(ui, opts)
578 ctx = scmutil.revsingle(repo, rev, rev)
578 ctx = scmutil.revsingle(repo, rev, rev)
579 t = ctx.manifestnode()
579 t = ctx.manifestnode()
580 def d():
580 def d():
581 repo.manifestlog.clearcaches()
581 repo.manifestlog.clearcaches()
582 repo.manifestlog[t].read()
582 repo.manifestlog[t].read()
583 timer(d)
583 timer(d)
584 fm.end()
584 fm.end()
585
585
586 @command('perfchangeset', formatteropts)
586 @command('perfchangeset', formatteropts)
587 def perfchangeset(ui, repo, rev, **opts):
587 def perfchangeset(ui, repo, rev, **opts):
588 timer, fm = gettimer(ui, opts)
588 timer, fm = gettimer(ui, opts)
589 n = repo[rev].node()
589 n = repo[rev].node()
590 def d():
590 def d():
591 repo.changelog.read(n)
591 repo.changelog.read(n)
592 #repo.changelog._cache = None
592 #repo.changelog._cache = None
593 timer(d)
593 timer(d)
594 fm.end()
594 fm.end()
595
595
596 @command('perfindex', formatteropts)
596 @command('perfindex', formatteropts)
597 def perfindex(ui, repo, **opts):
597 def perfindex(ui, repo, **opts):
598 import mercurial.revlog
598 import mercurial.revlog
599 timer, fm = gettimer(ui, opts)
599 timer, fm = gettimer(ui, opts)
600 mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
600 mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
601 n = repo["tip"].node()
601 n = repo["tip"].node()
602 svfs = getsvfs(repo)
602 svfs = getsvfs(repo)
603 def d():
603 def d():
604 cl = mercurial.revlog.revlog(svfs, "00changelog.i")
604 cl = mercurial.revlog.revlog(svfs, "00changelog.i")
605 cl.rev(n)
605 cl.rev(n)
606 timer(d)
606 timer(d)
607 fm.end()
607 fm.end()
608
608
609 @command('perfstartup', formatteropts)
609 @command('perfstartup', formatteropts)
610 def perfstartup(ui, repo, **opts):
610 def perfstartup(ui, repo, **opts):
611 timer, fm = gettimer(ui, opts)
611 timer, fm = gettimer(ui, opts)
612 cmd = sys.argv[0]
612 cmd = sys.argv[0]
613 def d():
613 def d():
614 if os.name != 'nt':
614 if os.name != 'nt':
615 os.system("HGRCPATH= %s version -q > /dev/null" % cmd)
615 os.system("HGRCPATH= %s version -q > /dev/null" % cmd)
616 else:
616 else:
617 os.environ['HGRCPATH'] = ''
617 os.environ['HGRCPATH'] = ''
618 os.system("%s version -q > NUL" % cmd)
618 os.system("%s version -q > NUL" % cmd)
619 timer(d)
619 timer(d)
620 fm.end()
620 fm.end()
621
621
622 @command('perfparents', formatteropts)
622 @command('perfparents', formatteropts)
623 def perfparents(ui, repo, **opts):
623 def perfparents(ui, repo, **opts):
624 timer, fm = gettimer(ui, opts)
624 timer, fm = gettimer(ui, opts)
625 # control the number of commits perfparents iterates over
625 # control the number of commits perfparents iterates over
626 # experimental config: perf.parentscount
626 # experimental config: perf.parentscount
627 count = getint(ui, "perf", "parentscount", 1000)
627 count = getint(ui, "perf", "parentscount", 1000)
628 if len(repo.changelog) < count:
628 if len(repo.changelog) < count:
629 raise error.Abort("repo needs %d commits for this test" % count)
629 raise error.Abort("repo needs %d commits for this test" % count)
630 repo = repo.unfiltered()
630 repo = repo.unfiltered()
631 nl = [repo.changelog.node(i) for i in xrange(count)]
631 nl = [repo.changelog.node(i) for i in xrange(count)]
632 def d():
632 def d():
633 for n in nl:
633 for n in nl:
634 repo.changelog.parents(n)
634 repo.changelog.parents(n)
635 timer(d)
635 timer(d)
636 fm.end()
636 fm.end()
637
637
638 @command('perfctxfiles', formatteropts)
638 @command('perfctxfiles', formatteropts)
639 def perfctxfiles(ui, repo, x, **opts):
639 def perfctxfiles(ui, repo, x, **opts):
640 x = int(x)
640 x = int(x)
641 timer, fm = gettimer(ui, opts)
641 timer, fm = gettimer(ui, opts)
642 def d():
642 def d():
643 len(repo[x].files())
643 len(repo[x].files())
644 timer(d)
644 timer(d)
645 fm.end()
645 fm.end()
646
646
647 @command('perfrawfiles', formatteropts)
647 @command('perfrawfiles', formatteropts)
648 def perfrawfiles(ui, repo, x, **opts):
648 def perfrawfiles(ui, repo, x, **opts):
649 x = int(x)
649 x = int(x)
650 timer, fm = gettimer(ui, opts)
650 timer, fm = gettimer(ui, opts)
651 cl = repo.changelog
651 cl = repo.changelog
652 def d():
652 def d():
653 len(cl.read(x)[3])
653 len(cl.read(x)[3])
654 timer(d)
654 timer(d)
655 fm.end()
655 fm.end()
656
656
657 @command('perflookup', formatteropts)
657 @command('perflookup', formatteropts)
658 def perflookup(ui, repo, rev, **opts):
658 def perflookup(ui, repo, rev, **opts):
659 timer, fm = gettimer(ui, opts)
659 timer, fm = gettimer(ui, opts)
660 timer(lambda: len(repo.lookup(rev)))
660 timer(lambda: len(repo.lookup(rev)))
661 fm.end()
661 fm.end()
662
662
663 @command('perfrevrange', formatteropts)
663 @command('perfrevrange', formatteropts)
664 def perfrevrange(ui, repo, *specs, **opts):
664 def perfrevrange(ui, repo, *specs, **opts):
665 timer, fm = gettimer(ui, opts)
665 timer, fm = gettimer(ui, opts)
666 revrange = scmutil.revrange
666 revrange = scmutil.revrange
667 timer(lambda: len(revrange(repo, specs)))
667 timer(lambda: len(revrange(repo, specs)))
668 fm.end()
668 fm.end()
669
669
670 @command('perfnodelookup', formatteropts)
670 @command('perfnodelookup', formatteropts)
671 def perfnodelookup(ui, repo, rev, **opts):
671 def perfnodelookup(ui, repo, rev, **opts):
672 timer, fm = gettimer(ui, opts)
672 timer, fm = gettimer(ui, opts)
673 import mercurial.revlog
673 import mercurial.revlog
674 mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
674 mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
675 n = repo[rev].node()
675 n = repo[rev].node()
676 cl = mercurial.revlog.revlog(getsvfs(repo), "00changelog.i")
676 cl = mercurial.revlog.revlog(getsvfs(repo), "00changelog.i")
677 def d():
677 def d():
678 cl.rev(n)
678 cl.rev(n)
679 clearcaches(cl)
679 clearcaches(cl)
680 timer(d)
680 timer(d)
681 fm.end()
681 fm.end()
682
682
683 @command('perflog',
683 @command('perflog',
684 [('', 'rename', False, 'ask log to follow renames')] + formatteropts)
684 [('', 'rename', False, 'ask log to follow renames')] + formatteropts)
685 def perflog(ui, repo, rev=None, **opts):
685 def perflog(ui, repo, rev=None, **opts):
686 if rev is None:
686 if rev is None:
687 rev=[]
687 rev=[]
688 timer, fm = gettimer(ui, opts)
688 timer, fm = gettimer(ui, opts)
689 ui.pushbuffer()
689 ui.pushbuffer()
690 timer(lambda: commands.log(ui, repo, rev=rev, date='', user='',
690 timer(lambda: commands.log(ui, repo, rev=rev, date='', user='',
691 copies=opts.get('rename')))
691 copies=opts.get('rename')))
692 ui.popbuffer()
692 ui.popbuffer()
693 fm.end()
693 fm.end()
694
694
695 @command('perfmoonwalk', formatteropts)
695 @command('perfmoonwalk', formatteropts)
696 def perfmoonwalk(ui, repo, **opts):
696 def perfmoonwalk(ui, repo, **opts):
697 """benchmark walking the changelog backwards
697 """benchmark walking the changelog backwards
698
698
699 This also loads the changelog data for each revision in the changelog.
699 This also loads the changelog data for each revision in the changelog.
700 """
700 """
701 timer, fm = gettimer(ui, opts)
701 timer, fm = gettimer(ui, opts)
702 def moonwalk():
702 def moonwalk():
703 for i in xrange(len(repo), -1, -1):
703 for i in xrange(len(repo), -1, -1):
704 ctx = repo[i]
704 ctx = repo[i]
705 ctx.branch() # read changelog data (in addition to the index)
705 ctx.branch() # read changelog data (in addition to the index)
706 timer(moonwalk)
706 timer(moonwalk)
707 fm.end()
707 fm.end()
708
708
709 @command('perftemplating', formatteropts)
709 @command('perftemplating', formatteropts)
710 def perftemplating(ui, repo, rev=None, **opts):
710 def perftemplating(ui, repo, rev=None, **opts):
711 if rev is None:
711 if rev is None:
712 rev=[]
712 rev=[]
713 timer, fm = gettimer(ui, opts)
713 timer, fm = gettimer(ui, opts)
714 ui.pushbuffer()
714 ui.pushbuffer()
715 timer(lambda: commands.log(ui, repo, rev=rev, date='', user='',
715 timer(lambda: commands.log(ui, repo, rev=rev, date='', user='',
716 template='{date|shortdate} [{rev}:{node|short}]'
716 template='{date|shortdate} [{rev}:{node|short}]'
717 ' {author|person}: {desc|firstline}\n'))
717 ' {author|person}: {desc|firstline}\n'))
718 ui.popbuffer()
718 ui.popbuffer()
719 fm.end()
719 fm.end()
720
720
721 @command('perfcca', formatteropts)
721 @command('perfcca', formatteropts)
722 def perfcca(ui, repo, **opts):
722 def perfcca(ui, repo, **opts):
723 timer, fm = gettimer(ui, opts)
723 timer, fm = gettimer(ui, opts)
724 timer(lambda: scmutil.casecollisionauditor(ui, False, repo.dirstate))
724 timer(lambda: scmutil.casecollisionauditor(ui, False, repo.dirstate))
725 fm.end()
725 fm.end()
726
726
727 @command('perffncacheload', formatteropts)
727 @command('perffncacheload', formatteropts)
728 def perffncacheload(ui, repo, **opts):
728 def perffncacheload(ui, repo, **opts):
729 timer, fm = gettimer(ui, opts)
729 timer, fm = gettimer(ui, opts)
730 s = repo.store
730 s = repo.store
731 def d():
731 def d():
732 s.fncache._load()
732 s.fncache._load()
733 timer(d)
733 timer(d)
734 fm.end()
734 fm.end()
735
735
736 @command('perffncachewrite', formatteropts)
736 @command('perffncachewrite', formatteropts)
737 def perffncachewrite(ui, repo, **opts):
737 def perffncachewrite(ui, repo, **opts):
738 timer, fm = gettimer(ui, opts)
738 timer, fm = gettimer(ui, opts)
739 s = repo.store
739 s = repo.store
740 s.fncache._load()
740 s.fncache._load()
741 lock = repo.lock()
741 lock = repo.lock()
742 tr = repo.transaction('perffncachewrite')
742 tr = repo.transaction('perffncachewrite')
743 def d():
743 def d():
744 s.fncache._dirty = True
744 s.fncache._dirty = True
745 s.fncache.write(tr)
745 s.fncache.write(tr)
746 timer(d)
746 timer(d)
747 tr.close()
747 tr.close()
748 lock.release()
748 lock.release()
749 fm.end()
749 fm.end()
750
750
751 @command('perffncacheencode', formatteropts)
751 @command('perffncacheencode', formatteropts)
752 def perffncacheencode(ui, repo, **opts):
752 def perffncacheencode(ui, repo, **opts):
753 timer, fm = gettimer(ui, opts)
753 timer, fm = gettimer(ui, opts)
754 s = repo.store
754 s = repo.store
755 s.fncache._load()
755 s.fncache._load()
756 def d():
756 def d():
757 for p in s.fncache.entries:
757 for p in s.fncache.entries:
758 s.encode(p)
758 s.encode(p)
759 timer(d)
759 timer(d)
760 fm.end()
760 fm.end()
761
761
762 @command('perfbdiff', revlogopts + formatteropts + [
762 @command('perfbdiff', revlogopts + formatteropts + [
763 ('', 'count', 1, 'number of revisions to test (when using --startrev)'),
763 ('', 'count', 1, 'number of revisions to test (when using --startrev)'),
764 ('', 'alldata', False, 'test bdiffs for all associated revisions')],
764 ('', 'alldata', False, 'test bdiffs for all associated revisions')],
765 '-c|-m|FILE REV')
765 '-c|-m|FILE REV')
766 def perfbdiff(ui, repo, file_, rev=None, count=None, **opts):
766 def perfbdiff(ui, repo, file_, rev=None, count=None, **opts):
767 """benchmark a bdiff between revisions
767 """benchmark a bdiff between revisions
768
768
769 By default, benchmark a bdiff between its delta parent and itself.
769 By default, benchmark a bdiff between its delta parent and itself.
770
770
771 With ``--count``, benchmark bdiffs between delta parents and self for N
771 With ``--count``, benchmark bdiffs between delta parents and self for N
772 revisions starting at the specified revision.
772 revisions starting at the specified revision.
773
773
774 With ``--alldata``, assume the requested revision is a changeset and
774 With ``--alldata``, assume the requested revision is a changeset and
775 measure bdiffs for all changes related to that changeset (manifest
775 measure bdiffs for all changes related to that changeset (manifest
776 and filelogs).
776 and filelogs).
777 """
777 """
778 if opts['alldata']:
778 if opts['alldata']:
779 opts['changelog'] = True
779 opts['changelog'] = True
780
780
781 if opts.get('changelog') or opts.get('manifest'):
781 if opts.get('changelog') or opts.get('manifest'):
782 file_, rev = None, file_
782 file_, rev = None, file_
783 elif rev is None:
783 elif rev is None:
784 raise error.CommandError('perfbdiff', 'invalid arguments')
784 raise error.CommandError('perfbdiff', 'invalid arguments')
785
785
786 textpairs = []
786 textpairs = []
787
787
788 r = cmdutil.openrevlog(repo, 'perfbdiff', file_, opts)
788 r = cmdutil.openrevlog(repo, 'perfbdiff', file_, opts)
789
789
790 startrev = r.rev(r.lookup(rev))
790 startrev = r.rev(r.lookup(rev))
791 for rev in range(startrev, min(startrev + count, len(r) - 1)):
791 for rev in range(startrev, min(startrev + count, len(r) - 1)):
792 if opts['alldata']:
792 if opts['alldata']:
793 # Load revisions associated with changeset.
793 # Load revisions associated with changeset.
794 ctx = repo[rev]
794 ctx = repo[rev]
795 mtext = repo.manifestlog._revlog.revision(ctx.manifestnode())
795 mtext = repo.manifestlog._revlog.revision(ctx.manifestnode())
796 for pctx in ctx.parents():
796 for pctx in ctx.parents():
797 pman = repo.manifestlog._revlog.revision(pctx.manifestnode())
797 pman = repo.manifestlog._revlog.revision(pctx.manifestnode())
798 textpairs.append((pman, mtext))
798 textpairs.append((pman, mtext))
799
799
800 # Load filelog revisions by iterating manifest delta.
800 # Load filelog revisions by iterating manifest delta.
801 man = ctx.manifest()
801 man = ctx.manifest()
802 pman = ctx.p1().manifest()
802 pman = ctx.p1().manifest()
803 for filename, change in pman.diff(man).items():
803 for filename, change in pman.diff(man).items():
804 fctx = repo.file(filename)
804 fctx = repo.file(filename)
805 f1 = fctx.revision(change[0][0] or -1)
805 f1 = fctx.revision(change[0][0] or -1)
806 f2 = fctx.revision(change[1][0] or -1)
806 f2 = fctx.revision(change[1][0] or -1)
807 textpairs.append((f1, f2))
807 textpairs.append((f1, f2))
808 else:
808 else:
809 dp = r.deltaparent(rev)
809 dp = r.deltaparent(rev)
810 textpairs.append((r.revision(dp), r.revision(rev)))
810 textpairs.append((r.revision(dp), r.revision(rev)))
811
811
812 def d():
812 def d():
813 for pair in textpairs:
813 for pair in textpairs:
814 mdiff.textdiff(*pair)
814 mdiff.textdiff(*pair)
815
815
816 timer, fm = gettimer(ui, opts)
816 timer, fm = gettimer(ui, opts)
817 timer(d)
817 timer(d)
818 fm.end()
818 fm.end()
819
819
820 @command('perfdiffwd', formatteropts)
820 @command('perfdiffwd', formatteropts)
821 def perfdiffwd(ui, repo, **opts):
821 def perfdiffwd(ui, repo, **opts):
822 """Profile diff of working directory changes"""
822 """Profile diff of working directory changes"""
823 timer, fm = gettimer(ui, opts)
823 timer, fm = gettimer(ui, opts)
824 options = {
824 options = {
825 'w': 'ignore_all_space',
825 'w': 'ignore_all_space',
826 'b': 'ignore_space_change',
826 'b': 'ignore_space_change',
827 'B': 'ignore_blank_lines',
827 'B': 'ignore_blank_lines',
828 }
828 }
829
829
830 for diffopt in ('', 'w', 'b', 'B', 'wB'):
830 for diffopt in ('', 'w', 'b', 'B', 'wB'):
831 opts = dict((options[c], '1') for c in diffopt)
831 opts = dict((options[c], '1') for c in diffopt)
832 def d():
832 def d():
833 ui.pushbuffer()
833 ui.pushbuffer()
834 commands.diff(ui, repo, **opts)
834 commands.diff(ui, repo, **opts)
835 ui.popbuffer()
835 ui.popbuffer()
836 title = 'diffopts: %s' % (diffopt and ('-' + diffopt) or 'none')
836 title = 'diffopts: %s' % (diffopt and ('-' + diffopt) or 'none')
837 timer(d, title)
837 timer(d, title)
838 fm.end()
838 fm.end()
839
839
840 @command('perfrevlog', revlogopts + formatteropts +
840 @command('perfrevlog', revlogopts + formatteropts +
841 [('d', 'dist', 100, 'distance between the revisions'),
841 [('d', 'dist', 100, 'distance between the revisions'),
842 ('s', 'startrev', 0, 'revision to start reading at'),
842 ('s', 'startrev', 0, 'revision to start reading at'),
843 ('', 'reverse', False, 'read in reverse')],
843 ('', 'reverse', False, 'read in reverse')],
844 '-c|-m|FILE')
844 '-c|-m|FILE')
845 def perfrevlog(ui, repo, file_=None, startrev=0, reverse=False, **opts):
845 def perfrevlog(ui, repo, file_=None, startrev=0, reverse=False, **opts):
846 """Benchmark reading a series of revisions from a revlog.
846 """Benchmark reading a series of revisions from a revlog.
847
847
848 By default, we read every ``-d/--dist`` revision from 0 to tip of
848 By default, we read every ``-d/--dist`` revision from 0 to tip of
849 the specified revlog.
849 the specified revlog.
850
850
851 The start revision can be defined via ``-s/--startrev``.
851 The start revision can be defined via ``-s/--startrev``.
852 """
852 """
853 _len = getlen(ui)
853 _len = getlen(ui)
854
854
855 def d():
855 def d():
856 r = cmdutil.openrevlog(repo, 'perfrevlog', file_, opts)
856 r = cmdutil.openrevlog(repo, 'perfrevlog', file_, opts)
857
857
858 beginrev = startrev
858 beginrev = startrev
859 endrev = _len(r)
859 endrev = _len(r)
860 dist = opts['dist']
860 dist = opts['dist']
861
861
862 if reverse:
862 if reverse:
863 beginrev, endrev = endrev, beginrev
863 beginrev, endrev = endrev, beginrev
864 dist = -1 * dist
864 dist = -1 * dist
865
865
866 for x in xrange(beginrev, endrev, dist):
866 for x in xrange(beginrev, endrev, dist):
867 r.revision(r.node(x))
867 r.revision(x)
868
868
869 timer, fm = gettimer(ui, opts)
869 timer, fm = gettimer(ui, opts)
870 timer(d)
870 timer(d)
871 fm.end()
871 fm.end()
872
872
873 @command('perfrevlogchunks', revlogopts + formatteropts +
873 @command('perfrevlogchunks', revlogopts + formatteropts +
874 [('e', 'engines', '', 'compression engines to use'),
874 [('e', 'engines', '', 'compression engines to use'),
875 ('s', 'startrev', 0, 'revision to start at')],
875 ('s', 'startrev', 0, 'revision to start at')],
876 '-c|-m|FILE')
876 '-c|-m|FILE')
877 def perfrevlogchunks(ui, repo, file_=None, engines=None, startrev=0, **opts):
877 def perfrevlogchunks(ui, repo, file_=None, engines=None, startrev=0, **opts):
878 """Benchmark operations on revlog chunks.
878 """Benchmark operations on revlog chunks.
879
879
880 Logically, each revlog is a collection of fulltext revisions. However,
880 Logically, each revlog is a collection of fulltext revisions. However,
881 stored within each revlog are "chunks" of possibly compressed data. This
881 stored within each revlog are "chunks" of possibly compressed data. This
882 data needs to be read and decompressed or compressed and written.
882 data needs to be read and decompressed or compressed and written.
883
883
884 This command measures the time it takes to read+decompress and recompress
884 This command measures the time it takes to read+decompress and recompress
885 chunks in a revlog. It effectively isolates I/O and compression performance.
885 chunks in a revlog. It effectively isolates I/O and compression performance.
886 For measurements of higher-level operations like resolving revisions,
886 For measurements of higher-level operations like resolving revisions,
887 see ``perfrevlog`` and ``perfrevlogrevision``.
887 see ``perfrevlog`` and ``perfrevlogrevision``.
888 """
888 """
889 rl = cmdutil.openrevlog(repo, 'perfrevlogchunks', file_, opts)
889 rl = cmdutil.openrevlog(repo, 'perfrevlogchunks', file_, opts)
890
890
891 # _chunkraw was renamed to _getsegmentforrevs.
891 # _chunkraw was renamed to _getsegmentforrevs.
892 try:
892 try:
893 segmentforrevs = rl._getsegmentforrevs
893 segmentforrevs = rl._getsegmentforrevs
894 except AttributeError:
894 except AttributeError:
895 segmentforrevs = rl._chunkraw
895 segmentforrevs = rl._chunkraw
896
896
897 # Verify engines argument.
897 # Verify engines argument.
898 if engines:
898 if engines:
899 engines = set(e.strip() for e in engines.split(','))
899 engines = set(e.strip() for e in engines.split(','))
900 for engine in engines:
900 for engine in engines:
901 try:
901 try:
902 util.compressionengines[engine]
902 util.compressionengines[engine]
903 except KeyError:
903 except KeyError:
904 raise error.Abort('unknown compression engine: %s' % engine)
904 raise error.Abort('unknown compression engine: %s' % engine)
905 else:
905 else:
906 engines = []
906 engines = []
907 for e in util.compengines:
907 for e in util.compengines:
908 engine = util.compengines[e]
908 engine = util.compengines[e]
909 try:
909 try:
910 if engine.available():
910 if engine.available():
911 engine.revlogcompressor().compress('dummy')
911 engine.revlogcompressor().compress('dummy')
912 engines.append(e)
912 engines.append(e)
913 except NotImplementedError:
913 except NotImplementedError:
914 pass
914 pass
915
915
916 revs = list(rl.revs(startrev, len(rl) - 1))
916 revs = list(rl.revs(startrev, len(rl) - 1))
917
917
918 def rlfh(rl):
918 def rlfh(rl):
919 if rl._inline:
919 if rl._inline:
920 return getsvfs(repo)(rl.indexfile)
920 return getsvfs(repo)(rl.indexfile)
921 else:
921 else:
922 return getsvfs(repo)(rl.datafile)
922 return getsvfs(repo)(rl.datafile)
923
923
924 def doread():
924 def doread():
925 rl.clearcaches()
925 rl.clearcaches()
926 for rev in revs:
926 for rev in revs:
927 segmentforrevs(rev, rev)
927 segmentforrevs(rev, rev)
928
928
929 def doreadcachedfh():
929 def doreadcachedfh():
930 rl.clearcaches()
930 rl.clearcaches()
931 fh = rlfh(rl)
931 fh = rlfh(rl)
932 for rev in revs:
932 for rev in revs:
933 segmentforrevs(rev, rev, df=fh)
933 segmentforrevs(rev, rev, df=fh)
934
934
935 def doreadbatch():
935 def doreadbatch():
936 rl.clearcaches()
936 rl.clearcaches()
937 segmentforrevs(revs[0], revs[-1])
937 segmentforrevs(revs[0], revs[-1])
938
938
939 def doreadbatchcachedfh():
939 def doreadbatchcachedfh():
940 rl.clearcaches()
940 rl.clearcaches()
941 fh = rlfh(rl)
941 fh = rlfh(rl)
942 segmentforrevs(revs[0], revs[-1], df=fh)
942 segmentforrevs(revs[0], revs[-1], df=fh)
943
943
944 def dochunk():
944 def dochunk():
945 rl.clearcaches()
945 rl.clearcaches()
946 fh = rlfh(rl)
946 fh = rlfh(rl)
947 for rev in revs:
947 for rev in revs:
948 rl._chunk(rev, df=fh)
948 rl._chunk(rev, df=fh)
949
949
950 chunks = [None]
950 chunks = [None]
951
951
952 def dochunkbatch():
952 def dochunkbatch():
953 rl.clearcaches()
953 rl.clearcaches()
954 fh = rlfh(rl)
954 fh = rlfh(rl)
955 # Save chunks as a side-effect.
955 # Save chunks as a side-effect.
956 chunks[0] = rl._chunks(revs, df=fh)
956 chunks[0] = rl._chunks(revs, df=fh)
957
957
958 def docompress(compressor):
958 def docompress(compressor):
959 rl.clearcaches()
959 rl.clearcaches()
960
960
961 try:
961 try:
962 # Swap in the requested compression engine.
962 # Swap in the requested compression engine.
963 oldcompressor = rl._compressor
963 oldcompressor = rl._compressor
964 rl._compressor = compressor
964 rl._compressor = compressor
965 for chunk in chunks[0]:
965 for chunk in chunks[0]:
966 rl.compress(chunk)
966 rl.compress(chunk)
967 finally:
967 finally:
968 rl._compressor = oldcompressor
968 rl._compressor = oldcompressor
969
969
970 benches = [
970 benches = [
971 (lambda: doread(), 'read'),
971 (lambda: doread(), 'read'),
972 (lambda: doreadcachedfh(), 'read w/ reused fd'),
972 (lambda: doreadcachedfh(), 'read w/ reused fd'),
973 (lambda: doreadbatch(), 'read batch'),
973 (lambda: doreadbatch(), 'read batch'),
974 (lambda: doreadbatchcachedfh(), 'read batch w/ reused fd'),
974 (lambda: doreadbatchcachedfh(), 'read batch w/ reused fd'),
975 (lambda: dochunk(), 'chunk'),
975 (lambda: dochunk(), 'chunk'),
976 (lambda: dochunkbatch(), 'chunk batch'),
976 (lambda: dochunkbatch(), 'chunk batch'),
977 ]
977 ]
978
978
979 for engine in sorted(engines):
979 for engine in sorted(engines):
980 compressor = util.compengines[engine].revlogcompressor()
980 compressor = util.compengines[engine].revlogcompressor()
981 benches.append((functools.partial(docompress, compressor),
981 benches.append((functools.partial(docompress, compressor),
982 'compress w/ %s' % engine))
982 'compress w/ %s' % engine))
983
983
984 for fn, title in benches:
984 for fn, title in benches:
985 timer, fm = gettimer(ui, opts)
985 timer, fm = gettimer(ui, opts)
986 timer(fn, title=title)
986 timer(fn, title=title)
987 fm.end()
987 fm.end()
988
988
989 @command('perfrevlogrevision', revlogopts + formatteropts +
989 @command('perfrevlogrevision', revlogopts + formatteropts +
990 [('', 'cache', False, 'use caches instead of clearing')],
990 [('', 'cache', False, 'use caches instead of clearing')],
991 '-c|-m|FILE REV')
991 '-c|-m|FILE REV')
992 def perfrevlogrevision(ui, repo, file_, rev=None, cache=None, **opts):
992 def perfrevlogrevision(ui, repo, file_, rev=None, cache=None, **opts):
993 """Benchmark obtaining a revlog revision.
993 """Benchmark obtaining a revlog revision.
994
994
995 Obtaining a revlog revision consists of roughly the following steps:
995 Obtaining a revlog revision consists of roughly the following steps:
996
996
997 1. Compute the delta chain
997 1. Compute the delta chain
998 2. Obtain the raw chunks for that delta chain
998 2. Obtain the raw chunks for that delta chain
999 3. Decompress each raw chunk
999 3. Decompress each raw chunk
1000 4. Apply binary patches to obtain fulltext
1000 4. Apply binary patches to obtain fulltext
1001 5. Verify hash of fulltext
1001 5. Verify hash of fulltext
1002
1002
1003 This command measures the time spent in each of these phases.
1003 This command measures the time spent in each of these phases.
1004 """
1004 """
1005 if opts.get('changelog') or opts.get('manifest'):
1005 if opts.get('changelog') or opts.get('manifest'):
1006 file_, rev = None, file_
1006 file_, rev = None, file_
1007 elif rev is None:
1007 elif rev is None:
1008 raise error.CommandError('perfrevlogrevision', 'invalid arguments')
1008 raise error.CommandError('perfrevlogrevision', 'invalid arguments')
1009
1009
1010 r = cmdutil.openrevlog(repo, 'perfrevlogrevision', file_, opts)
1010 r = cmdutil.openrevlog(repo, 'perfrevlogrevision', file_, opts)
1011
1011
1012 # _chunkraw was renamed to _getsegmentforrevs.
1012 # _chunkraw was renamed to _getsegmentforrevs.
1013 try:
1013 try:
1014 segmentforrevs = r._getsegmentforrevs
1014 segmentforrevs = r._getsegmentforrevs
1015 except AttributeError:
1015 except AttributeError:
1016 segmentforrevs = r._chunkraw
1016 segmentforrevs = r._chunkraw
1017
1017
1018 node = r.lookup(rev)
1018 node = r.lookup(rev)
1019 rev = r.rev(node)
1019 rev = r.rev(node)
1020
1020
1021 def getrawchunks(data, chain):
1021 def getrawchunks(data, chain):
1022 start = r.start
1022 start = r.start
1023 length = r.length
1023 length = r.length
1024 inline = r._inline
1024 inline = r._inline
1025 iosize = r._io.size
1025 iosize = r._io.size
1026 buffer = util.buffer
1026 buffer = util.buffer
1027 offset = start(chain[0])
1027 offset = start(chain[0])
1028
1028
1029 chunks = []
1029 chunks = []
1030 ladd = chunks.append
1030 ladd = chunks.append
1031
1031
1032 for rev in chain:
1032 for rev in chain:
1033 chunkstart = start(rev)
1033 chunkstart = start(rev)
1034 if inline:
1034 if inline:
1035 chunkstart += (rev + 1) * iosize
1035 chunkstart += (rev + 1) * iosize
1036 chunklength = length(rev)
1036 chunklength = length(rev)
1037 ladd(buffer(data, chunkstart - offset, chunklength))
1037 ladd(buffer(data, chunkstart - offset, chunklength))
1038
1038
1039 return chunks
1039 return chunks
1040
1040
1041 def dodeltachain(rev):
1041 def dodeltachain(rev):
1042 if not cache:
1042 if not cache:
1043 r.clearcaches()
1043 r.clearcaches()
1044 r._deltachain(rev)
1044 r._deltachain(rev)
1045
1045
1046 def doread(chain):
1046 def doread(chain):
1047 if not cache:
1047 if not cache:
1048 r.clearcaches()
1048 r.clearcaches()
1049 segmentforrevs(chain[0], chain[-1])
1049 segmentforrevs(chain[0], chain[-1])
1050
1050
1051 def dorawchunks(data, chain):
1051 def dorawchunks(data, chain):
1052 if not cache:
1052 if not cache:
1053 r.clearcaches()
1053 r.clearcaches()
1054 getrawchunks(data, chain)
1054 getrawchunks(data, chain)
1055
1055
1056 def dodecompress(chunks):
1056 def dodecompress(chunks):
1057 decomp = r.decompress
1057 decomp = r.decompress
1058 for chunk in chunks:
1058 for chunk in chunks:
1059 decomp(chunk)
1059 decomp(chunk)
1060
1060
1061 def dopatch(text, bins):
1061 def dopatch(text, bins):
1062 if not cache:
1062 if not cache:
1063 r.clearcaches()
1063 r.clearcaches()
1064 mdiff.patches(text, bins)
1064 mdiff.patches(text, bins)
1065
1065
1066 def dohash(text):
1066 def dohash(text):
1067 if not cache:
1067 if not cache:
1068 r.clearcaches()
1068 r.clearcaches()
1069 r.checkhash(text, node, rev=rev)
1069 r.checkhash(text, node, rev=rev)
1070
1070
1071 def dorevision():
1071 def dorevision():
1072 if not cache:
1072 if not cache:
1073 r.clearcaches()
1073 r.clearcaches()
1074 r.revision(node)
1074 r.revision(node)
1075
1075
1076 chain = r._deltachain(rev)[0]
1076 chain = r._deltachain(rev)[0]
1077 data = segmentforrevs(chain[0], chain[-1])[1]
1077 data = segmentforrevs(chain[0], chain[-1])[1]
1078 rawchunks = getrawchunks(data, chain)
1078 rawchunks = getrawchunks(data, chain)
1079 bins = r._chunks(chain)
1079 bins = r._chunks(chain)
1080 text = str(bins[0])
1080 text = str(bins[0])
1081 bins = bins[1:]
1081 bins = bins[1:]
1082 text = mdiff.patches(text, bins)
1082 text = mdiff.patches(text, bins)
1083
1083
1084 benches = [
1084 benches = [
1085 (lambda: dorevision(), 'full'),
1085 (lambda: dorevision(), 'full'),
1086 (lambda: dodeltachain(rev), 'deltachain'),
1086 (lambda: dodeltachain(rev), 'deltachain'),
1087 (lambda: doread(chain), 'read'),
1087 (lambda: doread(chain), 'read'),
1088 (lambda: dorawchunks(data, chain), 'rawchunks'),
1088 (lambda: dorawchunks(data, chain), 'rawchunks'),
1089 (lambda: dodecompress(rawchunks), 'decompress'),
1089 (lambda: dodecompress(rawchunks), 'decompress'),
1090 (lambda: dopatch(text, bins), 'patch'),
1090 (lambda: dopatch(text, bins), 'patch'),
1091 (lambda: dohash(text), 'hash'),
1091 (lambda: dohash(text), 'hash'),
1092 ]
1092 ]
1093
1093
1094 for fn, title in benches:
1094 for fn, title in benches:
1095 timer, fm = gettimer(ui, opts)
1095 timer, fm = gettimer(ui, opts)
1096 timer(fn, title=title)
1096 timer(fn, title=title)
1097 fm.end()
1097 fm.end()
1098
1098
1099 @command('perfrevset',
1099 @command('perfrevset',
1100 [('C', 'clear', False, 'clear volatile cache between each call.'),
1100 [('C', 'clear', False, 'clear volatile cache between each call.'),
1101 ('', 'contexts', False, 'obtain changectx for each revision')]
1101 ('', 'contexts', False, 'obtain changectx for each revision')]
1102 + formatteropts, "REVSET")
1102 + formatteropts, "REVSET")
1103 def perfrevset(ui, repo, expr, clear=False, contexts=False, **opts):
1103 def perfrevset(ui, repo, expr, clear=False, contexts=False, **opts):
1104 """benchmark the execution time of a revset
1104 """benchmark the execution time of a revset
1105
1105
1106 Use the --clean option if need to evaluate the impact of build volatile
1106 Use the --clean option if need to evaluate the impact of build volatile
1107 revisions set cache on the revset execution. Volatile cache hold filtered
1107 revisions set cache on the revset execution. Volatile cache hold filtered
1108 and obsolete related cache."""
1108 and obsolete related cache."""
1109 timer, fm = gettimer(ui, opts)
1109 timer, fm = gettimer(ui, opts)
1110 def d():
1110 def d():
1111 if clear:
1111 if clear:
1112 repo.invalidatevolatilesets()
1112 repo.invalidatevolatilesets()
1113 if contexts:
1113 if contexts:
1114 for ctx in repo.set(expr): pass
1114 for ctx in repo.set(expr): pass
1115 else:
1115 else:
1116 for r in repo.revs(expr): pass
1116 for r in repo.revs(expr): pass
1117 timer(d)
1117 timer(d)
1118 fm.end()
1118 fm.end()
1119
1119
1120 @command('perfvolatilesets', formatteropts)
1120 @command('perfvolatilesets', formatteropts)
1121 def perfvolatilesets(ui, repo, *names, **opts):
1121 def perfvolatilesets(ui, repo, *names, **opts):
1122 """benchmark the computation of various volatile set
1122 """benchmark the computation of various volatile set
1123
1123
1124 Volatile set computes element related to filtering and obsolescence."""
1124 Volatile set computes element related to filtering and obsolescence."""
1125 timer, fm = gettimer(ui, opts)
1125 timer, fm = gettimer(ui, opts)
1126 repo = repo.unfiltered()
1126 repo = repo.unfiltered()
1127
1127
1128 def getobs(name):
1128 def getobs(name):
1129 def d():
1129 def d():
1130 repo.invalidatevolatilesets()
1130 repo.invalidatevolatilesets()
1131 obsolete.getrevs(repo, name)
1131 obsolete.getrevs(repo, name)
1132 return d
1132 return d
1133
1133
1134 allobs = sorted(obsolete.cachefuncs)
1134 allobs = sorted(obsolete.cachefuncs)
1135 if names:
1135 if names:
1136 allobs = [n for n in allobs if n in names]
1136 allobs = [n for n in allobs if n in names]
1137
1137
1138 for name in allobs:
1138 for name in allobs:
1139 timer(getobs(name), title=name)
1139 timer(getobs(name), title=name)
1140
1140
1141 def getfiltered(name):
1141 def getfiltered(name):
1142 def d():
1142 def d():
1143 repo.invalidatevolatilesets()
1143 repo.invalidatevolatilesets()
1144 repoview.filterrevs(repo, name)
1144 repoview.filterrevs(repo, name)
1145 return d
1145 return d
1146
1146
1147 allfilter = sorted(repoview.filtertable)
1147 allfilter = sorted(repoview.filtertable)
1148 if names:
1148 if names:
1149 allfilter = [n for n in allfilter if n in names]
1149 allfilter = [n for n in allfilter if n in names]
1150
1150
1151 for name in allfilter:
1151 for name in allfilter:
1152 timer(getfiltered(name), title=name)
1152 timer(getfiltered(name), title=name)
1153 fm.end()
1153 fm.end()
1154
1154
1155 @command('perfbranchmap',
1155 @command('perfbranchmap',
1156 [('f', 'full', False,
1156 [('f', 'full', False,
1157 'Includes build time of subset'),
1157 'Includes build time of subset'),
1158 ] + formatteropts)
1158 ] + formatteropts)
1159 def perfbranchmap(ui, repo, full=False, **opts):
1159 def perfbranchmap(ui, repo, full=False, **opts):
1160 """benchmark the update of a branchmap
1160 """benchmark the update of a branchmap
1161
1161
1162 This benchmarks the full repo.branchmap() call with read and write disabled
1162 This benchmarks the full repo.branchmap() call with read and write disabled
1163 """
1163 """
1164 timer, fm = gettimer(ui, opts)
1164 timer, fm = gettimer(ui, opts)
1165 def getbranchmap(filtername):
1165 def getbranchmap(filtername):
1166 """generate a benchmark function for the filtername"""
1166 """generate a benchmark function for the filtername"""
1167 if filtername is None:
1167 if filtername is None:
1168 view = repo
1168 view = repo
1169 else:
1169 else:
1170 view = repo.filtered(filtername)
1170 view = repo.filtered(filtername)
1171 def d():
1171 def d():
1172 if full:
1172 if full:
1173 view._branchcaches.clear()
1173 view._branchcaches.clear()
1174 else:
1174 else:
1175 view._branchcaches.pop(filtername, None)
1175 view._branchcaches.pop(filtername, None)
1176 view.branchmap()
1176 view.branchmap()
1177 return d
1177 return d
1178 # add filter in smaller subset to bigger subset
1178 # add filter in smaller subset to bigger subset
1179 possiblefilters = set(repoview.filtertable)
1179 possiblefilters = set(repoview.filtertable)
1180 subsettable = getbranchmapsubsettable()
1180 subsettable = getbranchmapsubsettable()
1181 allfilters = []
1181 allfilters = []
1182 while possiblefilters:
1182 while possiblefilters:
1183 for name in possiblefilters:
1183 for name in possiblefilters:
1184 subset = subsettable.get(name)
1184 subset = subsettable.get(name)
1185 if subset not in possiblefilters:
1185 if subset not in possiblefilters:
1186 break
1186 break
1187 else:
1187 else:
1188 assert False, 'subset cycle %s!' % possiblefilters
1188 assert False, 'subset cycle %s!' % possiblefilters
1189 allfilters.append(name)
1189 allfilters.append(name)
1190 possiblefilters.remove(name)
1190 possiblefilters.remove(name)
1191
1191
1192 # warm the cache
1192 # warm the cache
1193 if not full:
1193 if not full:
1194 for name in allfilters:
1194 for name in allfilters:
1195 repo.filtered(name).branchmap()
1195 repo.filtered(name).branchmap()
1196 # add unfiltered
1196 # add unfiltered
1197 allfilters.append(None)
1197 allfilters.append(None)
1198
1198
1199 branchcacheread = safeattrsetter(branchmap, 'read')
1199 branchcacheread = safeattrsetter(branchmap, 'read')
1200 branchcachewrite = safeattrsetter(branchmap.branchcache, 'write')
1200 branchcachewrite = safeattrsetter(branchmap.branchcache, 'write')
1201 branchcacheread.set(lambda repo: None)
1201 branchcacheread.set(lambda repo: None)
1202 branchcachewrite.set(lambda bc, repo: None)
1202 branchcachewrite.set(lambda bc, repo: None)
1203 try:
1203 try:
1204 for name in allfilters:
1204 for name in allfilters:
1205 timer(getbranchmap(name), title=str(name))
1205 timer(getbranchmap(name), title=str(name))
1206 finally:
1206 finally:
1207 branchcacheread.restore()
1207 branchcacheread.restore()
1208 branchcachewrite.restore()
1208 branchcachewrite.restore()
1209 fm.end()
1209 fm.end()
1210
1210
1211 @command('perfloadmarkers')
1211 @command('perfloadmarkers')
1212 def perfloadmarkers(ui, repo):
1212 def perfloadmarkers(ui, repo):
1213 """benchmark the time to parse the on-disk markers for a repo
1213 """benchmark the time to parse the on-disk markers for a repo
1214
1214
1215 Result is the number of markers in the repo."""
1215 Result is the number of markers in the repo."""
1216 timer, fm = gettimer(ui)
1216 timer, fm = gettimer(ui)
1217 svfs = getsvfs(repo)
1217 svfs = getsvfs(repo)
1218 timer(lambda: len(obsolete.obsstore(svfs)))
1218 timer(lambda: len(obsolete.obsstore(svfs)))
1219 fm.end()
1219 fm.end()
1220
1220
1221 @command('perflrucachedict', formatteropts +
1221 @command('perflrucachedict', formatteropts +
1222 [('', 'size', 4, 'size of cache'),
1222 [('', 'size', 4, 'size of cache'),
1223 ('', 'gets', 10000, 'number of key lookups'),
1223 ('', 'gets', 10000, 'number of key lookups'),
1224 ('', 'sets', 10000, 'number of key sets'),
1224 ('', 'sets', 10000, 'number of key sets'),
1225 ('', 'mixed', 10000, 'number of mixed mode operations'),
1225 ('', 'mixed', 10000, 'number of mixed mode operations'),
1226 ('', 'mixedgetfreq', 50, 'frequency of get vs set ops in mixed mode')],
1226 ('', 'mixedgetfreq', 50, 'frequency of get vs set ops in mixed mode')],
1227 norepo=True)
1227 norepo=True)
1228 def perflrucache(ui, size=4, gets=10000, sets=10000, mixed=10000,
1228 def perflrucache(ui, size=4, gets=10000, sets=10000, mixed=10000,
1229 mixedgetfreq=50, **opts):
1229 mixedgetfreq=50, **opts):
1230 def doinit():
1230 def doinit():
1231 for i in xrange(10000):
1231 for i in xrange(10000):
1232 util.lrucachedict(size)
1232 util.lrucachedict(size)
1233
1233
1234 values = []
1234 values = []
1235 for i in xrange(size):
1235 for i in xrange(size):
1236 values.append(random.randint(0, sys.maxint))
1236 values.append(random.randint(0, sys.maxint))
1237
1237
1238 # Get mode fills the cache and tests raw lookup performance with no
1238 # Get mode fills the cache and tests raw lookup performance with no
1239 # eviction.
1239 # eviction.
1240 getseq = []
1240 getseq = []
1241 for i in xrange(gets):
1241 for i in xrange(gets):
1242 getseq.append(random.choice(values))
1242 getseq.append(random.choice(values))
1243
1243
1244 def dogets():
1244 def dogets():
1245 d = util.lrucachedict(size)
1245 d = util.lrucachedict(size)
1246 for v in values:
1246 for v in values:
1247 d[v] = v
1247 d[v] = v
1248 for key in getseq:
1248 for key in getseq:
1249 value = d[key]
1249 value = d[key]
1250 value # silence pyflakes warning
1250 value # silence pyflakes warning
1251
1251
1252 # Set mode tests insertion speed with cache eviction.
1252 # Set mode tests insertion speed with cache eviction.
1253 setseq = []
1253 setseq = []
1254 for i in xrange(sets):
1254 for i in xrange(sets):
1255 setseq.append(random.randint(0, sys.maxint))
1255 setseq.append(random.randint(0, sys.maxint))
1256
1256
1257 def dosets():
1257 def dosets():
1258 d = util.lrucachedict(size)
1258 d = util.lrucachedict(size)
1259 for v in setseq:
1259 for v in setseq:
1260 d[v] = v
1260 d[v] = v
1261
1261
1262 # Mixed mode randomly performs gets and sets with eviction.
1262 # Mixed mode randomly performs gets and sets with eviction.
1263 mixedops = []
1263 mixedops = []
1264 for i in xrange(mixed):
1264 for i in xrange(mixed):
1265 r = random.randint(0, 100)
1265 r = random.randint(0, 100)
1266 if r < mixedgetfreq:
1266 if r < mixedgetfreq:
1267 op = 0
1267 op = 0
1268 else:
1268 else:
1269 op = 1
1269 op = 1
1270
1270
1271 mixedops.append((op, random.randint(0, size * 2)))
1271 mixedops.append((op, random.randint(0, size * 2)))
1272
1272
1273 def domixed():
1273 def domixed():
1274 d = util.lrucachedict(size)
1274 d = util.lrucachedict(size)
1275
1275
1276 for op, v in mixedops:
1276 for op, v in mixedops:
1277 if op == 0:
1277 if op == 0:
1278 try:
1278 try:
1279 d[v]
1279 d[v]
1280 except KeyError:
1280 except KeyError:
1281 pass
1281 pass
1282 else:
1282 else:
1283 d[v] = v
1283 d[v] = v
1284
1284
1285 benches = [
1285 benches = [
1286 (doinit, 'init'),
1286 (doinit, 'init'),
1287 (dogets, 'gets'),
1287 (dogets, 'gets'),
1288 (dosets, 'sets'),
1288 (dosets, 'sets'),
1289 (domixed, 'mixed')
1289 (domixed, 'mixed')
1290 ]
1290 ]
1291
1291
1292 for fn, title in benches:
1292 for fn, title in benches:
1293 timer, fm = gettimer(ui, opts)
1293 timer, fm = gettimer(ui, opts)
1294 timer(fn, title=title)
1294 timer(fn, title=title)
1295 fm.end()
1295 fm.end()
1296
1296
1297 @command('perfwrite', formatteropts)
1297 @command('perfwrite', formatteropts)
1298 def perfwrite(ui, repo, **opts):
1298 def perfwrite(ui, repo, **opts):
1299 """microbenchmark ui.write
1299 """microbenchmark ui.write
1300 """
1300 """
1301 timer, fm = gettimer(ui, opts)
1301 timer, fm = gettimer(ui, opts)
1302 def write():
1302 def write():
1303 for i in range(100000):
1303 for i in range(100000):
1304 ui.write(('Testing write performance\n'))
1304 ui.write(('Testing write performance\n'))
1305 timer(write)
1305 timer(write)
1306 fm.end()
1306 fm.end()
1307
1307
1308 def uisetup(ui):
1308 def uisetup(ui):
1309 if (util.safehasattr(cmdutil, 'openrevlog') and
1309 if (util.safehasattr(cmdutil, 'openrevlog') and
1310 not util.safehasattr(commands, 'debugrevlogopts')):
1310 not util.safehasattr(commands, 'debugrevlogopts')):
1311 # for "historical portability":
1311 # for "historical portability":
1312 # In this case, Mercurial should be 1.9 (or a79fea6b3e77) -
1312 # In this case, Mercurial should be 1.9 (or a79fea6b3e77) -
1313 # 3.7 (or 5606f7d0d063). Therefore, '--dir' option for
1313 # 3.7 (or 5606f7d0d063). Therefore, '--dir' option for
1314 # openrevlog() should cause failure, because it has been
1314 # openrevlog() should cause failure, because it has been
1315 # available since 3.5 (or 49c583ca48c4).
1315 # available since 3.5 (or 49c583ca48c4).
1316 def openrevlog(orig, repo, cmd, file_, opts):
1316 def openrevlog(orig, repo, cmd, file_, opts):
1317 if opts.get('dir') and not util.safehasattr(repo, 'dirlog'):
1317 if opts.get('dir') and not util.safehasattr(repo, 'dirlog'):
1318 raise error.Abort("This version doesn't support --dir option",
1318 raise error.Abort("This version doesn't support --dir option",
1319 hint="use 3.5 or later")
1319 hint="use 3.5 or later")
1320 return orig(repo, cmd, file_, opts)
1320 return orig(repo, cmd, file_, opts)
1321 extensions.wrapfunction(cmdutil, 'openrevlog', openrevlog)
1321 extensions.wrapfunction(cmdutil, 'openrevlog', openrevlog)
@@ -1,53 +1,49 b''
1 #require test-repo
1 #require test-repo
2
2
3 $ . "$TESTDIR/helpers-testrepo.sh"
3 $ . "$TESTDIR/helpers-testrepo.sh"
4 $ check_code="$TESTDIR"/../contrib/check-code.py
4 $ check_code="$TESTDIR"/../contrib/check-code.py
5 $ cd "$TESTDIR"/..
5 $ cd "$TESTDIR"/..
6
6
7 New errors are not allowed. Warnings are strongly discouraged.
7 New errors are not allowed. Warnings are strongly discouraged.
8 (The writing "no-che?k-code" is for not skipping this file when checking.)
8 (The writing "no-che?k-code" is for not skipping this file when checking.)
9
9
10 $ hg locate -X contrib/python-zstandard -X hgext/fsmonitor/pywatchman |
10 $ hg locate -X contrib/python-zstandard -X hgext/fsmonitor/pywatchman |
11 > sed 's-\\-/-g' | "$check_code" --warnings --per-file=0 - || false
11 > sed 's-\\-/-g' | "$check_code" --warnings --per-file=0 - || false
12 contrib/perf.py:867:
13 > r.revision(r.node(x))
14 don't convert rev to node before passing to revision(nodeorrev)
15 Skipping i18n/polib.py it has no-che?k-code (glob)
12 Skipping i18n/polib.py it has no-che?k-code (glob)
16 Skipping mercurial/httpclient/__init__.py it has no-che?k-code (glob)
13 Skipping mercurial/httpclient/__init__.py it has no-che?k-code (glob)
17 Skipping mercurial/httpclient/_readers.py it has no-che?k-code (glob)
14 Skipping mercurial/httpclient/_readers.py it has no-che?k-code (glob)
18 Skipping mercurial/statprof.py it has no-che?k-code (glob)
15 Skipping mercurial/statprof.py it has no-che?k-code (glob)
19 Skipping tests/badserverext.py it has no-che?k-code (glob)
16 Skipping tests/badserverext.py it has no-che?k-code (glob)
20 [1]
21
17
22 @commands in debugcommands.py should be in alphabetical order.
18 @commands in debugcommands.py should be in alphabetical order.
23
19
24 >>> import re
20 >>> import re
25 >>> commands = []
21 >>> commands = []
26 >>> with open('mercurial/debugcommands.py', 'rb') as fh:
22 >>> with open('mercurial/debugcommands.py', 'rb') as fh:
27 ... for line in fh:
23 ... for line in fh:
28 ... m = re.match("^@command\('([a-z]+)", line)
24 ... m = re.match("^@command\('([a-z]+)", line)
29 ... if m:
25 ... if m:
30 ... commands.append(m.group(1))
26 ... commands.append(m.group(1))
31 >>> scommands = list(sorted(commands))
27 >>> scommands = list(sorted(commands))
32 >>> for i, command in enumerate(scommands):
28 >>> for i, command in enumerate(scommands):
33 ... if command != commands[i]:
29 ... if command != commands[i]:
34 ... print('commands in debugcommands.py not sorted; first differing '
30 ... print('commands in debugcommands.py not sorted; first differing '
35 ... 'command is %s; expected %s' % (commands[i], command))
31 ... 'command is %s; expected %s' % (commands[i], command))
36 ... break
32 ... break
37
33
38 Prevent adding new files in the root directory accidentally.
34 Prevent adding new files in the root directory accidentally.
39
35
40 $ hg files 'glob:*'
36 $ hg files 'glob:*'
41 .editorconfig
37 .editorconfig
42 .hgignore
38 .hgignore
43 .hgsigs
39 .hgsigs
44 .hgtags
40 .hgtags
45 CONTRIBUTING
41 CONTRIBUTING
46 CONTRIBUTORS
42 CONTRIBUTORS
47 COPYING
43 COPYING
48 Makefile
44 Makefile
49 README
45 README
50 hg
46 hg
51 hgeditor
47 hgeditor
52 hgweb.cgi
48 hgweb.cgi
53 setup.py
49 setup.py
@@ -1,171 +1,167 b''
1 #require test-repo
1 #require test-repo
2
2
3 Set vars:
3 Set vars:
4
4
5 $ . "$TESTDIR/helpers-testrepo.sh"
5 $ . "$TESTDIR/helpers-testrepo.sh"
6 $ CONTRIBDIR="$TESTDIR/../contrib"
6 $ CONTRIBDIR="$TESTDIR/../contrib"
7
7
8 Prepare repo:
8 Prepare repo:
9
9
10 $ hg init
10 $ hg init
11
11
12 $ echo this is file a > a
12 $ echo this is file a > a
13 $ hg add a
13 $ hg add a
14 $ hg commit -m first
14 $ hg commit -m first
15
15
16 $ echo adding to file a >> a
16 $ echo adding to file a >> a
17 $ hg commit -m second
17 $ hg commit -m second
18
18
19 $ echo adding more to file a >> a
19 $ echo adding more to file a >> a
20 $ hg commit -m third
20 $ hg commit -m third
21
21
22 $ hg up -r 0
22 $ hg up -r 0
23 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
23 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 $ echo merge-this >> a
24 $ echo merge-this >> a
25 $ hg commit -m merge-able
25 $ hg commit -m merge-able
26 created new head
26 created new head
27
27
28 $ hg up -r 2
28 $ hg up -r 2
29 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
30
30
31 perfstatus
31 perfstatus
32
32
33 $ cat >> $HGRCPATH << EOF
33 $ cat >> $HGRCPATH << EOF
34 > [extensions]
34 > [extensions]
35 > perfstatusext=$CONTRIBDIR/perf.py
35 > perfstatusext=$CONTRIBDIR/perf.py
36 > [perf]
36 > [perf]
37 > presleep=0
37 > presleep=0
38 > stub=on
38 > stub=on
39 > parentscount=1
39 > parentscount=1
40 > EOF
40 > EOF
41 $ hg help perfstatusext
41 $ hg help perfstatusext
42 perfstatusext extension - helper extension to measure performance
42 perfstatusext extension - helper extension to measure performance
43
43
44 list of commands:
44 list of commands:
45
45
46 perfaddremove
46 perfaddremove
47 (no help text available)
47 (no help text available)
48 perfancestors
48 perfancestors
49 (no help text available)
49 (no help text available)
50 perfancestorset
50 perfancestorset
51 (no help text available)
51 (no help text available)
52 perfannotate (no help text available)
52 perfannotate (no help text available)
53 perfbdiff benchmark a bdiff between revisions
53 perfbdiff benchmark a bdiff between revisions
54 perfbranchmap
54 perfbranchmap
55 benchmark the update of a branchmap
55 benchmark the update of a branchmap
56 perfcca (no help text available)
56 perfcca (no help text available)
57 perfchangegroupchangelog
57 perfchangegroupchangelog
58 Benchmark producing a changelog group for a changegroup.
58 Benchmark producing a changelog group for a changegroup.
59 perfchangeset
59 perfchangeset
60 (no help text available)
60 (no help text available)
61 perfctxfiles (no help text available)
61 perfctxfiles (no help text available)
62 perfdiffwd Profile diff of working directory changes
62 perfdiffwd Profile diff of working directory changes
63 perfdirfoldmap
63 perfdirfoldmap
64 (no help text available)
64 (no help text available)
65 perfdirs (no help text available)
65 perfdirs (no help text available)
66 perfdirstate (no help text available)
66 perfdirstate (no help text available)
67 perfdirstatedirs
67 perfdirstatedirs
68 (no help text available)
68 (no help text available)
69 perfdirstatefoldmap
69 perfdirstatefoldmap
70 (no help text available)
70 (no help text available)
71 perfdirstatewrite
71 perfdirstatewrite
72 (no help text available)
72 (no help text available)
73 perffncacheencode
73 perffncacheencode
74 (no help text available)
74 (no help text available)
75 perffncacheload
75 perffncacheload
76 (no help text available)
76 (no help text available)
77 perffncachewrite
77 perffncachewrite
78 (no help text available)
78 (no help text available)
79 perfheads (no help text available)
79 perfheads (no help text available)
80 perfindex (no help text available)
80 perfindex (no help text available)
81 perfloadmarkers
81 perfloadmarkers
82 benchmark the time to parse the on-disk markers for a repo
82 benchmark the time to parse the on-disk markers for a repo
83 perflog (no help text available)
83 perflog (no help text available)
84 perflookup (no help text available)
84 perflookup (no help text available)
85 perflrucachedict
85 perflrucachedict
86 (no help text available)
86 (no help text available)
87 perfmanifest (no help text available)
87 perfmanifest (no help text available)
88 perfmergecalculate
88 perfmergecalculate
89 (no help text available)
89 (no help text available)
90 perfmoonwalk benchmark walking the changelog backwards
90 perfmoonwalk benchmark walking the changelog backwards
91 perfnodelookup
91 perfnodelookup
92 (no help text available)
92 (no help text available)
93 perfparents (no help text available)
93 perfparents (no help text available)
94 perfpathcopies
94 perfpathcopies
95 (no help text available)
95 (no help text available)
96 perfrawfiles (no help text available)
96 perfrawfiles (no help text available)
97 perfrevlog Benchmark reading a series of revisions from a revlog.
97 perfrevlog Benchmark reading a series of revisions from a revlog.
98 perfrevlogchunks
98 perfrevlogchunks
99 Benchmark operations on revlog chunks.
99 Benchmark operations on revlog chunks.
100 perfrevlogrevision
100 perfrevlogrevision
101 Benchmark obtaining a revlog revision.
101 Benchmark obtaining a revlog revision.
102 perfrevrange (no help text available)
102 perfrevrange (no help text available)
103 perfrevset benchmark the execution time of a revset
103 perfrevset benchmark the execution time of a revset
104 perfstartup (no help text available)
104 perfstartup (no help text available)
105 perfstatus (no help text available)
105 perfstatus (no help text available)
106 perftags (no help text available)
106 perftags (no help text available)
107 perftemplating
107 perftemplating
108 (no help text available)
108 (no help text available)
109 perfvolatilesets
109 perfvolatilesets
110 benchmark the computation of various volatile set
110 benchmark the computation of various volatile set
111 perfwalk (no help text available)
111 perfwalk (no help text available)
112 perfwrite microbenchmark ui.write
112 perfwrite microbenchmark ui.write
113
113
114 (use 'hg help -v perfstatusext' to show built-in aliases and global options)
114 (use 'hg help -v perfstatusext' to show built-in aliases and global options)
115 $ hg perfaddremove
115 $ hg perfaddremove
116 $ hg perfancestors
116 $ hg perfancestors
117 $ hg perfancestorset 2
117 $ hg perfancestorset 2
118 $ hg perfannotate a
118 $ hg perfannotate a
119 $ hg perfbdiff -c 1
119 $ hg perfbdiff -c 1
120 $ hg perfbdiff --alldata 1
120 $ hg perfbdiff --alldata 1
121 $ hg perfbranchmap
121 $ hg perfbranchmap
122 $ hg perfcca
122 $ hg perfcca
123 $ hg perfchangegroupchangelog
123 $ hg perfchangegroupchangelog
124 $ hg perfchangeset 2
124 $ hg perfchangeset 2
125 $ hg perfctxfiles 2
125 $ hg perfctxfiles 2
126 $ hg perfdiffwd
126 $ hg perfdiffwd
127 $ hg perfdirfoldmap
127 $ hg perfdirfoldmap
128 $ hg perfdirs
128 $ hg perfdirs
129 $ hg perfdirstate
129 $ hg perfdirstate
130 $ hg perfdirstatedirs
130 $ hg perfdirstatedirs
131 $ hg perfdirstatefoldmap
131 $ hg perfdirstatefoldmap
132 $ hg perfdirstatewrite
132 $ hg perfdirstatewrite
133 $ hg perffncacheencode
133 $ hg perffncacheencode
134 $ hg perffncacheload
134 $ hg perffncacheload
135 $ hg perffncachewrite
135 $ hg perffncachewrite
136 $ hg perfheads
136 $ hg perfheads
137 $ hg perfindex
137 $ hg perfindex
138 $ hg perfloadmarkers
138 $ hg perfloadmarkers
139 $ hg perflog
139 $ hg perflog
140 $ hg perflookup 2
140 $ hg perflookup 2
141 $ hg perflrucache
141 $ hg perflrucache
142 $ hg perfmanifest 2
142 $ hg perfmanifest 2
143 $ hg perfmergecalculate -r 3
143 $ hg perfmergecalculate -r 3
144 $ hg perfmoonwalk
144 $ hg perfmoonwalk
145 $ hg perfnodelookup 2
145 $ hg perfnodelookup 2
146 $ hg perfpathcopies 1 2
146 $ hg perfpathcopies 1 2
147 $ hg perfrawfiles 2
147 $ hg perfrawfiles 2
148 $ hg perfrevlog .hg/store/data/a.i
148 $ hg perfrevlog .hg/store/data/a.i
149 $ hg perfrevlogrevision -m 0
149 $ hg perfrevlogrevision -m 0
150 $ hg perfrevlogchunks -c
150 $ hg perfrevlogchunks -c
151 $ hg perfrevrange
151 $ hg perfrevrange
152 $ hg perfrevset 'all()'
152 $ hg perfrevset 'all()'
153 $ hg perfstartup
153 $ hg perfstartup
154 $ hg perfstatus
154 $ hg perfstatus
155 $ hg perftags
155 $ hg perftags
156 $ hg perftemplating
156 $ hg perftemplating
157 $ hg perfvolatilesets
157 $ hg perfvolatilesets
158 $ hg perfwalk
158 $ hg perfwalk
159 $ hg perfparents
159 $ hg perfparents
160
160
161 Check perf.py for historical portability
161 Check perf.py for historical portability
162
162
163 $ cd "$TESTDIR/.."
163 $ cd "$TESTDIR/.."
164
164
165 $ (hg files -r 1.2 glob:mercurial/*.c glob:mercurial/*.py;
165 $ (hg files -r 1.2 glob:mercurial/*.c glob:mercurial/*.py;
166 > hg files -r tip glob:mercurial/*.c glob:mercurial/*.py) |
166 > hg files -r tip glob:mercurial/*.c glob:mercurial/*.py) |
167 > "$TESTDIR"/check-perf-code.py contrib/perf.py
167 > "$TESTDIR"/check-perf-code.py contrib/perf.py
168 contrib/perf.py:867:
169 > r.revision(r.node(x))
170 don't convert rev to node before passing to revision(nodeorrev)
171 [1]
General Comments 0
You need to be logged in to leave comments. Login now