contrib/perf.py
branchstable
changeset 40404 956ec6f1320d
parent 40349 1524c305377f
child 40529 cf3bef7f162b
equal deleted inserted replaced
40131:535fc8a22365 40404:956ec6f1320d
    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 contextlib
    22 import functools
    23 import functools
    23 import gc
    24 import gc
    24 import os
    25 import os
    25 import random
    26 import random
    26 import struct
    27 import struct
    62     pass
    63     pass
    63 try:
    64 try:
    64     from mercurial import scmutil # since 1.9 (or 8b252e826c68)
    65     from mercurial import scmutil # since 1.9 (or 8b252e826c68)
    65 except ImportError:
    66 except ImportError:
    66     pass
    67     pass
       
    68 
       
    69 def identity(a):
       
    70     return a
       
    71 
    67 try:
    72 try:
    68     from mercurial import pycompat
    73     from mercurial import pycompat
    69     getargspec = pycompat.getargspec  # added to module after 4.5
    74     getargspec = pycompat.getargspec  # added to module after 4.5
       
    75     _byteskwargs = pycompat.byteskwargs  # since 4.1 (or fbc3f73dc802)
       
    76     _sysstr = pycompat.sysstr         # since 4.0 (or 2219f4f82ede)
       
    77     _xrange = pycompat.xrange         # since 4.8 (or 7eba8f83129b)
       
    78     fsencode = pycompat.fsencode      # since 3.9 (or f4a5e0e86a7e)
       
    79     if pycompat.ispy3:
       
    80         _maxint = sys.maxsize  # per py3 docs for replacing maxint
       
    81     else:
       
    82         _maxint = sys.maxint
    70 except (ImportError, AttributeError):
    83 except (ImportError, AttributeError):
    71     import inspect
    84     import inspect
    72     getargspec = inspect.getargspec
    85     getargspec = inspect.getargspec
       
    86     _byteskwargs = identity
       
    87     fsencode = identity               # no py3 support
       
    88     _maxint = sys.maxint              # no py3 support
       
    89     _sysstr = lambda x: x             # no py3 support
       
    90     _xrange = xrange
    73 
    91 
    74 try:
    92 try:
    75     # 4.7+
    93     # 4.7+
    76     queue = pycompat.queue.Queue
    94     queue = pycompat.queue.Queue
    77 except (AttributeError, ImportError):
    95 except (AttributeError, ImportError):
    93 # for "historical portability":
   111 # for "historical portability":
    94 # define util.safehasattr forcibly, because util.safehasattr has been
   112 # define util.safehasattr forcibly, because util.safehasattr has been
    95 # available since 1.9.3 (or 94b200a11cf7)
   113 # available since 1.9.3 (or 94b200a11cf7)
    96 _undefined = object()
   114 _undefined = object()
    97 def safehasattr(thing, attr):
   115 def safehasattr(thing, attr):
    98     return getattr(thing, attr, _undefined) is not _undefined
   116     return getattr(thing, _sysstr(attr), _undefined) is not _undefined
    99 setattr(util, 'safehasattr', safehasattr)
   117 setattr(util, 'safehasattr', safehasattr)
   100 
   118 
   101 # for "historical portability":
   119 # for "historical portability":
   102 # define util.timer forcibly, because util.timer has been available
   120 # define util.timer forcibly, because util.timer has been available
   103 # since ae5d60bb70c9
   121 # since ae5d60bb70c9
   104 if safehasattr(time, 'perf_counter'):
   122 if safehasattr(time, 'perf_counter'):
   105     util.timer = time.perf_counter
   123     util.timer = time.perf_counter
   106 elif os.name == 'nt':
   124 elif os.name == b'nt':
   107     util.timer = time.clock
   125     util.timer = time.clock
   108 else:
   126 else:
   109     util.timer = time.time
   127     util.timer = time.time
   110 
   128 
   111 # for "historical portability":
   129 # for "historical portability":
   121 # because commands.debugrevlogopts has been available since 3.7 (or
   139 # because commands.debugrevlogopts has been available since 3.7 (or
   122 # 5606f7d0d063), even though cmdutil.openrevlog() has been available
   140 # 5606f7d0d063), even though cmdutil.openrevlog() has been available
   123 # since 1.9 (or a79fea6b3e77).
   141 # since 1.9 (or a79fea6b3e77).
   124 revlogopts = getattr(cmdutil, "debugrevlogopts",
   142 revlogopts = getattr(cmdutil, "debugrevlogopts",
   125                      getattr(commands, "debugrevlogopts", [
   143                      getattr(commands, "debugrevlogopts", [
   126         ('c', 'changelog', False, ('open changelog')),
   144         (b'c', b'changelog', False, (b'open changelog')),
   127         ('m', 'manifest', False, ('open manifest')),
   145         (b'm', b'manifest', False, (b'open manifest')),
   128         ('', 'dir', False, ('open directory manifest')),
   146         (b'', b'dir', False, (b'open directory manifest')),
   129         ]))
   147         ]))
   130 
   148 
   131 cmdtable = {}
   149 cmdtable = {}
   132 
   150 
   133 # for "historical portability":
   151 # for "historical portability":
   134 # define parsealiases locally, because cmdutil.parsealiases has been
   152 # define parsealiases locally, because cmdutil.parsealiases has been
   135 # available since 1.5 (or 6252852b4332)
   153 # available since 1.5 (or 6252852b4332)
   136 def parsealiases(cmd):
   154 def parsealiases(cmd):
   137     return cmd.lstrip("^").split("|")
   155     return cmd.split(b"|")
   138 
   156 
   139 if safehasattr(registrar, 'command'):
   157 if safehasattr(registrar, 'command'):
   140     command = registrar.command(cmdtable)
   158     command = registrar.command(cmdtable)
   141 elif safehasattr(cmdutil, 'command'):
   159 elif safehasattr(cmdutil, 'command'):
   142     command = cmdutil.command(cmdtable)
   160     command = cmdutil.command(cmdtable)
   143     if 'norepo' not in getargspec(command).args:
   161     if b'norepo' not in getargspec(command).args:
   144         # for "historical portability":
   162         # for "historical portability":
   145         # wrap original cmdutil.command, because "norepo" option has
   163         # wrap original cmdutil.command, because "norepo" option has
   146         # been available since 3.1 (or 75a96326cecb)
   164         # been available since 3.1 (or 75a96326cecb)
   147         _command = command
   165         _command = command
   148         def command(name, options=(), synopsis=None, norepo=False):
   166         def command(name, options=(), synopsis=None, norepo=False):
   149             if norepo:
   167             if norepo:
   150                 commands.norepo += ' %s' % ' '.join(parsealiases(name))
   168                 commands.norepo += b' %s' % b' '.join(parsealiases(name))
   151             return _command(name, list(options), synopsis)
   169             return _command(name, list(options), synopsis)
   152 else:
   170 else:
   153     # for "historical portability":
   171     # for "historical portability":
   154     # define "@command" annotation locally, because cmdutil.command
   172     # define "@command" annotation locally, because cmdutil.command
   155     # has been available since 1.9 (or 2daa5179e73f)
   173     # has been available since 1.9 (or 2daa5179e73f)
   158             if synopsis:
   176             if synopsis:
   159                 cmdtable[name] = func, list(options), synopsis
   177                 cmdtable[name] = func, list(options), synopsis
   160             else:
   178             else:
   161                 cmdtable[name] = func, list(options)
   179                 cmdtable[name] = func, list(options)
   162             if norepo:
   180             if norepo:
   163                 commands.norepo += ' %s' % ' '.join(parsealiases(name))
   181                 commands.norepo += b' %s' % b' '.join(parsealiases(name))
   164             return func
   182             return func
   165         return decorator
   183         return decorator
   166 
   184 
   167 try:
   185 try:
   168     import mercurial.registrar
   186     import mercurial.registrar
   169     import mercurial.configitems
   187     import mercurial.configitems
   170     configtable = {}
   188     configtable = {}
   171     configitem = mercurial.registrar.configitem(configtable)
   189     configitem = mercurial.registrar.configitem(configtable)
   172     configitem('perf', 'presleep',
   190     configitem(b'perf', b'presleep',
   173         default=mercurial.configitems.dynamicdefault,
   191         default=mercurial.configitems.dynamicdefault,
   174     )
   192     )
   175     configitem('perf', 'stub',
   193     configitem(b'perf', b'stub',
   176         default=mercurial.configitems.dynamicdefault,
   194         default=mercurial.configitems.dynamicdefault,
   177     )
   195     )
   178     configitem('perf', 'parentscount',
   196     configitem(b'perf', b'parentscount',
   179         default=mercurial.configitems.dynamicdefault,
   197         default=mercurial.configitems.dynamicdefault,
   180     )
   198     )
   181     configitem('perf', 'all-timing',
   199     configitem(b'perf', b'all-timing',
   182         default=mercurial.configitems.dynamicdefault,
   200         default=mercurial.configitems.dynamicdefault,
   183     )
   201     )
   184 except (ImportError, AttributeError):
   202 except (ImportError, AttributeError):
   185     pass
   203     pass
   186 
   204 
   187 def getlen(ui):
   205 def getlen(ui):
   188     if ui.configbool("perf", "stub", False):
   206     if ui.configbool(b"perf", b"stub", False):
   189         return lambda x: 1
   207         return lambda x: 1
   190     return len
   208     return len
   191 
   209 
   192 def gettimer(ui, opts=None):
   210 def gettimer(ui, opts=None):
   193     """return a timer function and formatter: (timer, formatter)
   211     """return a timer function and formatter: (timer, formatter)
   195     This function exists to gather the creation of formatter in a single
   213     This function exists to gather the creation of formatter in a single
   196     place instead of duplicating it in all performance commands."""
   214     place instead of duplicating it in all performance commands."""
   197 
   215 
   198     # enforce an idle period before execution to counteract power management
   216     # enforce an idle period before execution to counteract power management
   199     # experimental config: perf.presleep
   217     # experimental config: perf.presleep
   200     time.sleep(getint(ui, "perf", "presleep", 1))
   218     time.sleep(getint(ui, b"perf", b"presleep", 1))
   201 
   219 
   202     if opts is None:
   220     if opts is None:
   203         opts = {}
   221         opts = {}
   204     # redirect all to stderr unless buffer api is in use
   222     # redirect all to stderr unless buffer api is in use
   205     if not ui._buffers:
   223     if not ui._buffers:
   206         ui = ui.copy()
   224         ui = ui.copy()
   207         uifout = safeattrsetter(ui, 'fout', ignoremissing=True)
   225         uifout = safeattrsetter(ui, b'fout', ignoremissing=True)
   208         if uifout:
   226         if uifout:
   209             # for "historical portability":
   227             # for "historical portability":
   210             # ui.fout/ferr have been available since 1.9 (or 4e1ccd4c2b6d)
   228             # ui.fout/ferr have been available since 1.9 (or 4e1ccd4c2b6d)
   211             uifout.set(ui.ferr)
   229             uifout.set(ui.ferr)
   212 
   230 
   213     # get a formatter
   231     # get a formatter
   214     uiformatter = getattr(ui, 'formatter', None)
   232     uiformatter = getattr(ui, 'formatter', None)
   215     if uiformatter:
   233     if uiformatter:
   216         fm = uiformatter('perf', opts)
   234         fm = uiformatter(b'perf', opts)
   217     else:
   235     else:
   218         # for "historical portability":
   236         # for "historical portability":
   219         # define formatter locally, because ui.formatter has been
   237         # define formatter locally, because ui.formatter has been
   220         # available since 2.2 (or ae5f92e154d3)
   238         # available since 2.2 (or ae5f92e154d3)
   221         from mercurial import node
   239         from mercurial import node
   242                     self._ui.write(deftext % fielddata, **opts)
   260                     self._ui.write(deftext % fielddata, **opts)
   243             def plain(self, text, **opts):
   261             def plain(self, text, **opts):
   244                 self._ui.write(text, **opts)
   262                 self._ui.write(text, **opts)
   245             def end(self):
   263             def end(self):
   246                 pass
   264                 pass
   247         fm = defaultformatter(ui, 'perf', opts)
   265         fm = defaultformatter(ui, b'perf', opts)
   248 
   266 
   249     # stub function, runs code only once instead of in a loop
   267     # stub function, runs code only once instead of in a loop
   250     # experimental config: perf.stub
   268     # experimental config: perf.stub
   251     if ui.configbool("perf", "stub", False):
   269     if ui.configbool(b"perf", b"stub", False):
   252         return functools.partial(stub_timer, fm), fm
   270         return functools.partial(stub_timer, fm), fm
   253 
   271 
   254     # experimental config: perf.all-timing
   272     # experimental config: perf.all-timing
   255     displayall = ui.configbool("perf", "all-timing", False)
   273     displayall = ui.configbool(b"perf", b"all-timing", False)
   256     return functools.partial(_timer, fm, displayall=displayall), fm
   274     return functools.partial(_timer, fm, displayall=displayall), fm
   257 
   275 
   258 def stub_timer(fm, func, title=None):
   276 def stub_timer(fm, func, title=None):
   259     func()
   277     func()
       
   278 
       
   279 @contextlib.contextmanager
       
   280 def timeone():
       
   281     r = []
       
   282     ostart = os.times()
       
   283     cstart = util.timer()
       
   284     yield r
       
   285     cstop = util.timer()
       
   286     ostop = os.times()
       
   287     a, b = ostart, ostop
       
   288     r.append((cstop - cstart, b[0] - a[0], b[1]-a[1]))
   260 
   289 
   261 def _timer(fm, func, title=None, displayall=False):
   290 def _timer(fm, func, title=None, displayall=False):
   262     gc.collect()
   291     gc.collect()
   263     results = []
   292     results = []
   264     begin = util.timer()
   293     begin = util.timer()
   265     count = 0
   294     count = 0
   266     while True:
   295     while True:
   267         ostart = os.times()
   296         with timeone() as item:
   268         cstart = util.timer()
   297             r = func()
   269         r = func()
   298         count += 1
       
   299         results.append(item[0])
   270         cstop = util.timer()
   300         cstop = util.timer()
   271         ostop = os.times()
       
   272         count += 1
       
   273         a, b = ostart, ostop
       
   274         results.append((cstop - cstart, b[0] - a[0], b[1]-a[1]))
       
   275         if cstop - begin > 3 and count >= 100:
   301         if cstop - begin > 3 and count >= 100:
   276             break
   302             break
   277         if cstop - begin > 10 and count >= 3:
   303         if cstop - begin > 10 and count >= 3:
   278             break
   304             break
   279 
   305 
       
   306     formatone(fm, results, title=title, result=r,
       
   307               displayall=displayall)
       
   308 
       
   309 def formatone(fm, timings, title=None, result=None, displayall=False):
       
   310 
       
   311     count = len(timings)
       
   312 
   280     fm.startitem()
   313     fm.startitem()
   281 
   314 
   282     if title:
   315     if title:
   283         fm.write('title', '! %s\n', title)
   316         fm.write(b'title', b'! %s\n', title)
   284     if r:
   317     if result:
   285         fm.write('result', '! result: %s\n', r)
   318         fm.write(b'result', b'! result: %s\n', result)
   286     def display(role, entry):
   319     def display(role, entry):
   287         prefix = ''
   320         prefix = b''
   288         if role != 'best':
   321         if role != b'best':
   289             prefix = '%s.' % role
   322             prefix = b'%s.' % role
   290         fm.plain('!')
   323         fm.plain(b'!')
   291         fm.write(prefix + 'wall', ' wall %f', entry[0])
   324         fm.write(prefix + b'wall', b' wall %f', entry[0])
   292         fm.write(prefix + 'comb', ' comb %f', entry[1] + entry[2])
   325         fm.write(prefix + b'comb', b' comb %f', entry[1] + entry[2])
   293         fm.write(prefix + 'user', ' user %f', entry[1])
   326         fm.write(prefix + b'user', b' user %f', entry[1])
   294         fm.write(prefix + 'sys',  ' sys %f', entry[2])
   327         fm.write(prefix + b'sys',  b' sys %f', entry[2])
   295         fm.write(prefix + 'count',  ' (%s of %d)', role, count)
   328         fm.write(prefix + b'count',  b' (%s of %%d)' % role, count)
   296         fm.plain('\n')
   329         fm.plain(b'\n')
   297     results.sort()
   330     timings.sort()
   298     min_val = results[0]
   331     min_val = timings[0]
   299     display('best', min_val)
   332     display(b'best', min_val)
   300     if displayall:
   333     if displayall:
   301         max_val = results[-1]
   334         max_val = timings[-1]
   302         display('max', max_val)
   335         display(b'max', max_val)
   303         avg = tuple([sum(x) / count for x in zip(*results)])
   336         avg = tuple([sum(x) / count for x in zip(*timings)])
   304         display('avg', avg)
   337         display(b'avg', avg)
   305         median = results[len(results) // 2]
   338         median = timings[len(timings) // 2]
   306         display('median', median)
   339         display(b'median', median)
   307 
   340 
   308 # utilities for historical portability
   341 # utilities for historical portability
   309 
   342 
   310 def getint(ui, section, name, default):
   343 def getint(ui, section, name, default):
   311     # for "historical portability":
   344     # for "historical portability":
   314     if v is None:
   347     if v is None:
   315         return default
   348         return default
   316     try:
   349     try:
   317         return int(v)
   350         return int(v)
   318     except ValueError:
   351     except ValueError:
   319         raise error.ConfigError(("%s.%s is not an integer ('%s')")
   352         raise error.ConfigError((b"%s.%s is not an integer ('%s')")
   320                                 % (section, name, v))
   353                                 % (section, name, v))
   321 
   354 
   322 def safeattrsetter(obj, name, ignoremissing=False):
   355 def safeattrsetter(obj, name, ignoremissing=False):
   323     """Ensure that 'obj' has 'name' attribute before subsequent setattr
   356     """Ensure that 'obj' has 'name' attribute before subsequent setattr
   324 
   357 
   335     versions.
   368     versions.
   336     """
   369     """
   337     if not util.safehasattr(obj, name):
   370     if not util.safehasattr(obj, name):
   338         if ignoremissing:
   371         if ignoremissing:
   339             return None
   372             return None
   340         raise error.Abort(("missing attribute %s of %s might break assumption"
   373         raise error.Abort((b"missing attribute %s of %s might break assumption"
   341                            " of performance measurement") % (name, obj))
   374                            b" of performance measurement") % (name, obj))
   342 
   375 
   343     origvalue = getattr(obj, name)
   376     origvalue = getattr(obj, _sysstr(name))
   344     class attrutil(object):
   377     class attrutil(object):
   345         def set(self, newvalue):
   378         def set(self, newvalue):
   346             setattr(obj, name, newvalue)
   379             setattr(obj, _sysstr(name), newvalue)
   347         def restore(self):
   380         def restore(self):
   348             setattr(obj, name, origvalue)
   381             setattr(obj, _sysstr(name), origvalue)
   349 
   382 
   350     return attrutil()
   383     return attrutil()
   351 
   384 
   352 # utilities to examine each internal API changes
   385 # utilities to examine each internal API changes
   353 
   386 
   362             return subsettable
   395             return subsettable
   363 
   396 
   364     # bisecting in bcee63733aad::59a9f18d4587 can reach here (both
   397     # bisecting in bcee63733aad::59a9f18d4587 can reach here (both
   365     # branchmap and repoview modules exist, but subsettable attribute
   398     # branchmap and repoview modules exist, but subsettable attribute
   366     # doesn't)
   399     # doesn't)
   367     raise error.Abort(("perfbranchmap not available with this Mercurial"),
   400     raise error.Abort((b"perfbranchmap not available with this Mercurial"),
   368                       hint="use 2.5 or later")
   401                       hint=b"use 2.5 or later")
   369 
   402 
   370 def getsvfs(repo):
   403 def getsvfs(repo):
   371     """Return appropriate object to access files under .hg/store
   404     """Return appropriate object to access files under .hg/store
   372     """
   405     """
   373     # for "historical portability":
   406     # for "historical portability":
   390         return getattr(repo, 'opener')
   423         return getattr(repo, 'opener')
   391 
   424 
   392 def repocleartagscachefunc(repo):
   425 def repocleartagscachefunc(repo):
   393     """Return the function to clear tags cache according to repo internal API
   426     """Return the function to clear tags cache according to repo internal API
   394     """
   427     """
   395     if util.safehasattr(repo, '_tagscache'): # since 2.0 (or 9dca7653b525)
   428     if util.safehasattr(repo, b'_tagscache'): # since 2.0 (or 9dca7653b525)
   396         # in this case, setattr(repo, '_tagscache', None) or so isn't
   429         # in this case, setattr(repo, '_tagscache', None) or so isn't
   397         # correct way to clear tags cache, because existing code paths
   430         # correct way to clear tags cache, because existing code paths
   398         # expect _tagscache to be a structured object.
   431         # expect _tagscache to be a structured object.
   399         def clearcache():
   432         def clearcache():
   400             # _tagscache has been filteredpropertycache since 2.5 (or
   433             # _tagscache has been filteredpropertycache since 2.5 (or
   401             # 98c867ac1330), and delattr() can't work in such case
   434             # 98c867ac1330), and delattr() can't work in such case
   402             if '_tagscache' in vars(repo):
   435             if b'_tagscache' in vars(repo):
   403                 del repo.__dict__['_tagscache']
   436                 del repo.__dict__[b'_tagscache']
   404         return clearcache
   437         return clearcache
   405 
   438 
   406     repotags = safeattrsetter(repo, '_tags', ignoremissing=True)
   439     repotags = safeattrsetter(repo, b'_tags', ignoremissing=True)
   407     if repotags: # since 1.4 (or 5614a628d173)
   440     if repotags: # since 1.4 (or 5614a628d173)
   408         return lambda : repotags.set(None)
   441         return lambda : repotags.set(None)
   409 
   442 
   410     repotagscache = safeattrsetter(repo, 'tagscache', ignoremissing=True)
   443     repotagscache = safeattrsetter(repo, b'tagscache', ignoremissing=True)
   411     if repotagscache: # since 0.6 (or d7df759d0e97)
   444     if repotagscache: # since 0.6 (or d7df759d0e97)
   412         return lambda : repotagscache.set(None)
   445         return lambda : repotagscache.set(None)
   413 
   446 
   414     # Mercurial earlier than 0.6 (or d7df759d0e97) logically reaches
   447     # Mercurial earlier than 0.6 (or d7df759d0e97) logically reaches
   415     # this point, but it isn't so problematic, because:
   448     # this point, but it isn't so problematic, because:
   416     # - repo.tags of such Mercurial isn't "callable", and repo.tags()
   449     # - repo.tags of such Mercurial isn't "callable", and repo.tags()
   417     #   in perftags() causes failure soon
   450     #   in perftags() causes failure soon
   418     # - perf.py itself has been available since 1.1 (or eb240755386d)
   451     # - perf.py itself has been available since 1.1 (or eb240755386d)
   419     raise error.Abort(("tags API of this hg command is unknown"))
   452     raise error.Abort((b"tags API of this hg command is unknown"))
   420 
   453 
   421 # utilities to clear cache
   454 # utilities to clear cache
   422 
   455 
   423 def clearfilecache(repo, attrname):
   456 def clearfilecache(repo, attrname):
   424     unfi = repo.unfiltered()
   457     unfi = repo.unfiltered()
   426         delattr(unfi, attrname)
   459         delattr(unfi, attrname)
   427     unfi._filecache.pop(attrname, None)
   460     unfi._filecache.pop(attrname, None)
   428 
   461 
   429 # perf commands
   462 # perf commands
   430 
   463 
   431 @command('perfwalk', formatteropts)
   464 @command(b'perfwalk', formatteropts)
   432 def perfwalk(ui, repo, *pats, **opts):
   465 def perfwalk(ui, repo, *pats, **opts):
       
   466     opts = _byteskwargs(opts)
   433     timer, fm = gettimer(ui, opts)
   467     timer, fm = gettimer(ui, opts)
   434     m = scmutil.match(repo[None], pats, {})
   468     m = scmutil.match(repo[None], pats, {})
   435     timer(lambda: len(list(repo.dirstate.walk(m, subrepos=[], unknown=True,
   469     timer(lambda: len(list(repo.dirstate.walk(m, subrepos=[], unknown=True,
   436                                               ignored=False))))
   470                                               ignored=False))))
   437     fm.end()
   471     fm.end()
   438 
   472 
   439 @command('perfannotate', formatteropts)
   473 @command(b'perfannotate', formatteropts)
   440 def perfannotate(ui, repo, f, **opts):
   474 def perfannotate(ui, repo, f, **opts):
   441     timer, fm = gettimer(ui, opts)
   475     opts = _byteskwargs(opts)
   442     fc = repo['.'][f]
   476     timer, fm = gettimer(ui, opts)
       
   477     fc = repo[b'.'][f]
   443     timer(lambda: len(fc.annotate(True)))
   478     timer(lambda: len(fc.annotate(True)))
   444     fm.end()
   479     fm.end()
   445 
   480 
   446 @command('perfstatus',
   481 @command(b'perfstatus',
   447          [('u', 'unknown', False,
   482          [(b'u', b'unknown', False,
   448            'ask status to look for unknown files')] + formatteropts)
   483            b'ask status to look for unknown files')] + formatteropts)
   449 def perfstatus(ui, repo, **opts):
   484 def perfstatus(ui, repo, **opts):
       
   485     opts = _byteskwargs(opts)
   450     #m = match.always(repo.root, repo.getcwd())
   486     #m = match.always(repo.root, repo.getcwd())
   451     #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False,
   487     #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False,
   452     #                                                False))))
   488     #                                                False))))
   453     timer, fm = gettimer(ui, opts)
   489     timer, fm = gettimer(ui, opts)
   454     timer(lambda: sum(map(len, repo.status(unknown=opts['unknown']))))
   490     timer(lambda: sum(map(len, repo.status(unknown=opts[b'unknown']))))
   455     fm.end()
   491     fm.end()
   456 
   492 
   457 @command('perfaddremove', formatteropts)
   493 @command(b'perfaddremove', formatteropts)
   458 def perfaddremove(ui, repo, **opts):
   494 def perfaddremove(ui, repo, **opts):
       
   495     opts = _byteskwargs(opts)
   459     timer, fm = gettimer(ui, opts)
   496     timer, fm = gettimer(ui, opts)
   460     try:
   497     try:
   461         oldquiet = repo.ui.quiet
   498         oldquiet = repo.ui.quiet
   462         repo.ui.quiet = True
   499         repo.ui.quiet = True
   463         matcher = scmutil.match(repo[None])
   500         matcher = scmutil.match(repo[None])
   464         opts['dry_run'] = True
   501         opts[b'dry_run'] = True
   465         timer(lambda: scmutil.addremove(repo, matcher, "", opts))
   502         timer(lambda: scmutil.addremove(repo, matcher, b"", opts))
   466     finally:
   503     finally:
   467         repo.ui.quiet = oldquiet
   504         repo.ui.quiet = oldquiet
   468         fm.end()
   505         fm.end()
   469 
   506 
   470 def clearcaches(cl):
   507 def clearcaches(cl):
   471     # behave somewhat consistently across internal API changes
   508     # behave somewhat consistently across internal API changes
   472     if util.safehasattr(cl, 'clearcaches'):
   509     if util.safehasattr(cl, b'clearcaches'):
   473         cl.clearcaches()
   510         cl.clearcaches()
   474     elif util.safehasattr(cl, '_nodecache'):
   511     elif util.safehasattr(cl, b'_nodecache'):
   475         from mercurial.node import nullid, nullrev
   512         from mercurial.node import nullid, nullrev
   476         cl._nodecache = {nullid: nullrev}
   513         cl._nodecache = {nullid: nullrev}
   477         cl._nodepos = None
   514         cl._nodepos = None
   478 
   515 
   479 @command('perfheads', formatteropts)
   516 @command(b'perfheads', formatteropts)
   480 def perfheads(ui, repo, **opts):
   517 def perfheads(ui, repo, **opts):
       
   518     opts = _byteskwargs(opts)
   481     timer, fm = gettimer(ui, opts)
   519     timer, fm = gettimer(ui, opts)
   482     cl = repo.changelog
   520     cl = repo.changelog
   483     def d():
   521     def d():
   484         len(cl.headrevs())
   522         len(cl.headrevs())
   485         clearcaches(cl)
   523         clearcaches(cl)
   486     timer(d)
   524     timer(d)
   487     fm.end()
   525     fm.end()
   488 
   526 
   489 @command('perftags', formatteropts)
   527 @command(b'perftags', formatteropts)
   490 def perftags(ui, repo, **opts):
   528 def perftags(ui, repo, **opts):
   491     import mercurial.changelog
   529     import mercurial.changelog
   492     import mercurial.manifest
   530     import mercurial.manifest
       
   531 
       
   532     opts = _byteskwargs(opts)
   493     timer, fm = gettimer(ui, opts)
   533     timer, fm = gettimer(ui, opts)
   494     svfs = getsvfs(repo)
   534     svfs = getsvfs(repo)
   495     repocleartagscache = repocleartagscachefunc(repo)
   535     repocleartagscache = repocleartagscachefunc(repo)
   496     def t():
   536     def t():
   497         repo.changelog = mercurial.changelog.changelog(svfs)
   537         repo.changelog = mercurial.changelog.changelog(svfs)
   498         repo.manifestlog = mercurial.manifest.manifestlog(svfs, repo)
   538         rootmanifest = mercurial.manifest.manifestrevlog(svfs)
       
   539         repo.manifestlog = mercurial.manifest.manifestlog(svfs, repo,
       
   540                                                           rootmanifest)
   499         repocleartagscache()
   541         repocleartagscache()
   500         return len(repo.tags())
   542         return len(repo.tags())
   501     timer(t)
   543     timer(t)
   502     fm.end()
   544     fm.end()
   503 
   545 
   504 @command('perfancestors', formatteropts)
   546 @command(b'perfancestors', formatteropts)
   505 def perfancestors(ui, repo, **opts):
   547 def perfancestors(ui, repo, **opts):
       
   548     opts = _byteskwargs(opts)
   506     timer, fm = gettimer(ui, opts)
   549     timer, fm = gettimer(ui, opts)
   507     heads = repo.changelog.headrevs()
   550     heads = repo.changelog.headrevs()
   508     def d():
   551     def d():
   509         for a in repo.changelog.ancestors(heads):
   552         for a in repo.changelog.ancestors(heads):
   510             pass
   553             pass
   511     timer(d)
   554     timer(d)
   512     fm.end()
   555     fm.end()
   513 
   556 
   514 @command('perfancestorset', formatteropts)
   557 @command(b'perfancestorset', formatteropts)
   515 def perfancestorset(ui, repo, revset, **opts):
   558 def perfancestorset(ui, repo, revset, **opts):
       
   559     opts = _byteskwargs(opts)
   516     timer, fm = gettimer(ui, opts)
   560     timer, fm = gettimer(ui, opts)
   517     revs = repo.revs(revset)
   561     revs = repo.revs(revset)
   518     heads = repo.changelog.headrevs()
   562     heads = repo.changelog.headrevs()
   519     def d():
   563     def d():
   520         s = repo.changelog.ancestors(heads)
   564         s = repo.changelog.ancestors(heads)
   521         for rev in revs:
   565         for rev in revs:
   522             rev in s
   566             rev in s
   523     timer(d)
   567     timer(d)
   524     fm.end()
   568     fm.end()
   525 
   569 
   526 @command('perfbookmarks', formatteropts)
   570 @command(b'perfbookmarks', formatteropts)
   527 def perfbookmarks(ui, repo, **opts):
   571 def perfbookmarks(ui, repo, **opts):
   528     """benchmark parsing bookmarks from disk to memory"""
   572     """benchmark parsing bookmarks from disk to memory"""
   529     timer, fm = gettimer(ui, opts)
   573     opts = _byteskwargs(opts)
   530     def d():
   574     timer, fm = gettimer(ui, opts)
   531         clearfilecache(repo, '_bookmarks')
   575     def d():
       
   576         clearfilecache(repo, b'_bookmarks')
   532         repo._bookmarks
   577         repo._bookmarks
   533     timer(d)
   578     timer(d)
   534     fm.end()
   579     fm.end()
   535 
   580 
   536 @command('perfbundleread', formatteropts, 'BUNDLE')
   581 @command(b'perfbundleread', formatteropts, b'BUNDLE')
   537 def perfbundleread(ui, repo, bundlepath, **opts):
   582 def perfbundleread(ui, repo, bundlepath, **opts):
   538     """Benchmark reading of bundle files.
   583     """Benchmark reading of bundle files.
   539 
   584 
   540     This command is meant to isolate the I/O part of bundle reading as
   585     This command is meant to isolate the I/O part of bundle reading as
   541     much as possible.
   586     much as possible.
   544         bundle2,
   589         bundle2,
   545         exchange,
   590         exchange,
   546         streamclone,
   591         streamclone,
   547     )
   592     )
   548 
   593 
       
   594     opts = _byteskwargs(opts)
       
   595 
   549     def makebench(fn):
   596     def makebench(fn):
   550         def run():
   597         def run():
   551             with open(bundlepath, 'rb') as fh:
   598             with open(bundlepath, b'rb') as fh:
   552                 bundle = exchange.readbundle(ui, fh, bundlepath)
   599                 bundle = exchange.readbundle(ui, fh, bundlepath)
   553                 fn(bundle)
   600                 fn(bundle)
   554 
   601 
   555         return run
   602         return run
   556 
   603 
   557     def makereadnbytes(size):
   604     def makereadnbytes(size):
   558         def run():
   605         def run():
   559             with open(bundlepath, 'rb') as fh:
   606             with open(bundlepath, b'rb') as fh:
   560                 bundle = exchange.readbundle(ui, fh, bundlepath)
   607                 bundle = exchange.readbundle(ui, fh, bundlepath)
   561                 while bundle.read(size):
   608                 while bundle.read(size):
   562                     pass
   609                     pass
   563 
   610 
   564         return run
   611         return run
   565 
   612 
   566     def makestdioread(size):
   613     def makestdioread(size):
   567         def run():
   614         def run():
   568             with open(bundlepath, 'rb') as fh:
   615             with open(bundlepath, b'rb') as fh:
   569                 while fh.read(size):
   616                 while fh.read(size):
   570                     pass
   617                     pass
   571 
   618 
   572         return run
   619         return run
   573 
   620 
   599         for part in bundle.iterparts(seekable=True):
   646         for part in bundle.iterparts(seekable=True):
   600             part.seek(0, os.SEEK_END)
   647             part.seek(0, os.SEEK_END)
   601 
   648 
   602     def makepartreadnbytes(size):
   649     def makepartreadnbytes(size):
   603         def run():
   650         def run():
   604             with open(bundlepath, 'rb') as fh:
   651             with open(bundlepath, b'rb') as fh:
   605                 bundle = exchange.readbundle(ui, fh, bundlepath)
   652                 bundle = exchange.readbundle(ui, fh, bundlepath)
   606                 for part in bundle.iterparts():
   653                 for part in bundle.iterparts():
   607                     while part.read(size):
   654                     while part.read(size):
   608                         pass
   655                         pass
   609 
   656 
   610         return run
   657         return run
   611 
   658 
   612     benches = [
   659     benches = [
   613         (makestdioread(8192), 'read(8k)'),
   660         (makestdioread(8192), b'read(8k)'),
   614         (makestdioread(16384), 'read(16k)'),
   661         (makestdioread(16384), b'read(16k)'),
   615         (makestdioread(32768), 'read(32k)'),
   662         (makestdioread(32768), b'read(32k)'),
   616         (makestdioread(131072), 'read(128k)'),
   663         (makestdioread(131072), b'read(128k)'),
   617     ]
   664     ]
   618 
   665 
   619     with open(bundlepath, 'rb') as fh:
   666     with open(bundlepath, b'rb') as fh:
   620         bundle = exchange.readbundle(ui, fh, bundlepath)
   667         bundle = exchange.readbundle(ui, fh, bundlepath)
   621 
   668 
   622         if isinstance(bundle, changegroup.cg1unpacker):
   669         if isinstance(bundle, changegroup.cg1unpacker):
   623             benches.extend([
   670             benches.extend([
   624                 (makebench(deltaiter), 'cg1 deltaiter()'),
   671                 (makebench(deltaiter), b'cg1 deltaiter()'),
   625                 (makebench(iterchunks), 'cg1 getchunks()'),
   672                 (makebench(iterchunks), b'cg1 getchunks()'),
   626                 (makereadnbytes(8192), 'cg1 read(8k)'),
   673                 (makereadnbytes(8192), b'cg1 read(8k)'),
   627                 (makereadnbytes(16384), 'cg1 read(16k)'),
   674                 (makereadnbytes(16384), b'cg1 read(16k)'),
   628                 (makereadnbytes(32768), 'cg1 read(32k)'),
   675                 (makereadnbytes(32768), b'cg1 read(32k)'),
   629                 (makereadnbytes(131072), 'cg1 read(128k)'),
   676                 (makereadnbytes(131072), b'cg1 read(128k)'),
   630             ])
   677             ])
   631         elif isinstance(bundle, bundle2.unbundle20):
   678         elif isinstance(bundle, bundle2.unbundle20):
   632             benches.extend([
   679             benches.extend([
   633                 (makebench(forwardchunks), 'bundle2 forwardchunks()'),
   680                 (makebench(forwardchunks), b'bundle2 forwardchunks()'),
   634                 (makebench(iterparts), 'bundle2 iterparts()'),
   681                 (makebench(iterparts), b'bundle2 iterparts()'),
   635                 (makebench(iterpartsseekable), 'bundle2 iterparts() seekable'),
   682                 (makebench(iterpartsseekable), b'bundle2 iterparts() seekable'),
   636                 (makebench(seek), 'bundle2 part seek()'),
   683                 (makebench(seek), b'bundle2 part seek()'),
   637                 (makepartreadnbytes(8192), 'bundle2 part read(8k)'),
   684                 (makepartreadnbytes(8192), b'bundle2 part read(8k)'),
   638                 (makepartreadnbytes(16384), 'bundle2 part read(16k)'),
   685                 (makepartreadnbytes(16384), b'bundle2 part read(16k)'),
   639                 (makepartreadnbytes(32768), 'bundle2 part read(32k)'),
   686                 (makepartreadnbytes(32768), b'bundle2 part read(32k)'),
   640                 (makepartreadnbytes(131072), 'bundle2 part read(128k)'),
   687                 (makepartreadnbytes(131072), b'bundle2 part read(128k)'),
   641             ])
   688             ])
   642         elif isinstance(bundle, streamclone.streamcloneapplier):
   689         elif isinstance(bundle, streamclone.streamcloneapplier):
   643             raise error.Abort('stream clone bundles not supported')
   690             raise error.Abort(b'stream clone bundles not supported')
   644         else:
   691         else:
   645             raise error.Abort('unhandled bundle type: %s' % type(bundle))
   692             raise error.Abort(b'unhandled bundle type: %s' % type(bundle))
   646 
   693 
   647     for fn, title in benches:
   694     for fn, title in benches:
   648         timer, fm = gettimer(ui, opts)
   695         timer, fm = gettimer(ui, opts)
   649         timer(fn, title=title)
   696         timer(fn, title=title)
   650         fm.end()
   697         fm.end()
   651 
   698 
   652 @command('perfchangegroupchangelog', formatteropts +
   699 @command(b'perfchangegroupchangelog', formatteropts +
   653          [('', 'version', '02', 'changegroup version'),
   700          [(b'', b'version', b'02', b'changegroup version'),
   654           ('r', 'rev', '', 'revisions to add to changegroup')])
   701           (b'r', b'rev', b'', b'revisions to add to changegroup')])
   655 def perfchangegroupchangelog(ui, repo, version='02', rev=None, **opts):
   702 def perfchangegroupchangelog(ui, repo, version=b'02', rev=None, **opts):
   656     """Benchmark producing a changelog group for a changegroup.
   703     """Benchmark producing a changelog group for a changegroup.
   657 
   704 
   658     This measures the time spent processing the changelog during a
   705     This measures the time spent processing the changelog during a
   659     bundle operation. This occurs during `hg bundle` and on a server
   706     bundle operation. This occurs during `hg bundle` and on a server
   660     processing a `getbundle` wire protocol request (handles clones
   707     processing a `getbundle` wire protocol request (handles clones
   661     and pull requests).
   708     and pull requests).
   662 
   709 
   663     By default, all revisions are added to the changegroup.
   710     By default, all revisions are added to the changegroup.
   664     """
   711     """
       
   712     opts = _byteskwargs(opts)
   665     cl = repo.changelog
   713     cl = repo.changelog
   666     revs = [cl.lookup(r) for r in repo.revs(rev or 'all()')]
   714     nodes = [cl.lookup(r) for r in repo.revs(rev or b'all()')]
   667     bundler = changegroup.getbundler(version, repo)
   715     bundler = changegroup.getbundler(version, repo)
   668 
   716 
   669     def lookup(node):
   717     def d():
   670         # The real bundler reads the revision in order to access the
   718         state, chunks = bundler._generatechangelog(cl, nodes)
   671         # manifest node and files list. Do that here.
   719         for chunk in chunks:
   672         cl.read(node)
       
   673         return node
       
   674 
       
   675     def d():
       
   676         for chunk in bundler.group(revs, cl, lookup):
       
   677             pass
   720             pass
   678 
   721 
   679     timer, fm = gettimer(ui, opts)
   722     timer, fm = gettimer(ui, opts)
   680     timer(d)
   723 
   681     fm.end()
   724     # Terminal printing can interfere with timing. So disable it.
   682 
   725     with ui.configoverride({(b'progress', b'disable'): True}):
   683 @command('perfdirs', formatteropts)
   726         timer(d)
       
   727 
       
   728     fm.end()
       
   729 
       
   730 @command(b'perfdirs', formatteropts)
   684 def perfdirs(ui, repo, **opts):
   731 def perfdirs(ui, repo, **opts):
       
   732     opts = _byteskwargs(opts)
   685     timer, fm = gettimer(ui, opts)
   733     timer, fm = gettimer(ui, opts)
   686     dirstate = repo.dirstate
   734     dirstate = repo.dirstate
   687     'a' in dirstate
   735     b'a' in dirstate
   688     def d():
   736     def d():
   689         dirstate.hasdir('a')
   737         dirstate.hasdir(b'a')
   690         del dirstate._map._dirs
   738         del dirstate._map._dirs
   691     timer(d)
   739     timer(d)
   692     fm.end()
   740     fm.end()
   693 
   741 
   694 @command('perfdirstate', formatteropts)
   742 @command(b'perfdirstate', formatteropts)
   695 def perfdirstate(ui, repo, **opts):
   743 def perfdirstate(ui, repo, **opts):
   696     timer, fm = gettimer(ui, opts)
   744     opts = _byteskwargs(opts)
   697     "a" in repo.dirstate
   745     timer, fm = gettimer(ui, opts)
       
   746     b"a" in repo.dirstate
   698     def d():
   747     def d():
   699         repo.dirstate.invalidate()
   748         repo.dirstate.invalidate()
   700         "a" in repo.dirstate
   749         b"a" in repo.dirstate
   701     timer(d)
   750     timer(d)
   702     fm.end()
   751     fm.end()
   703 
   752 
   704 @command('perfdirstatedirs', formatteropts)
   753 @command(b'perfdirstatedirs', formatteropts)
   705 def perfdirstatedirs(ui, repo, **opts):
   754 def perfdirstatedirs(ui, repo, **opts):
   706     timer, fm = gettimer(ui, opts)
   755     opts = _byteskwargs(opts)
   707     "a" in repo.dirstate
   756     timer, fm = gettimer(ui, opts)
   708     def d():
   757     b"a" in repo.dirstate
   709         repo.dirstate.hasdir("a")
   758     def d():
       
   759         repo.dirstate.hasdir(b"a")
   710         del repo.dirstate._map._dirs
   760         del repo.dirstate._map._dirs
   711     timer(d)
   761     timer(d)
   712     fm.end()
   762     fm.end()
   713 
   763 
   714 @command('perfdirstatefoldmap', formatteropts)
   764 @command(b'perfdirstatefoldmap', formatteropts)
   715 def perfdirstatefoldmap(ui, repo, **opts):
   765 def perfdirstatefoldmap(ui, repo, **opts):
       
   766     opts = _byteskwargs(opts)
   716     timer, fm = gettimer(ui, opts)
   767     timer, fm = gettimer(ui, opts)
   717     dirstate = repo.dirstate
   768     dirstate = repo.dirstate
   718     'a' in dirstate
   769     b'a' in dirstate
   719     def d():
   770     def d():
   720         dirstate._map.filefoldmap.get('a')
   771         dirstate._map.filefoldmap.get(b'a')
   721         del dirstate._map.filefoldmap
   772         del dirstate._map.filefoldmap
   722     timer(d)
   773     timer(d)
   723     fm.end()
   774     fm.end()
   724 
   775 
   725 @command('perfdirfoldmap', formatteropts)
   776 @command(b'perfdirfoldmap', formatteropts)
   726 def perfdirfoldmap(ui, repo, **opts):
   777 def perfdirfoldmap(ui, repo, **opts):
       
   778     opts = _byteskwargs(opts)
   727     timer, fm = gettimer(ui, opts)
   779     timer, fm = gettimer(ui, opts)
   728     dirstate = repo.dirstate
   780     dirstate = repo.dirstate
   729     'a' in dirstate
   781     b'a' in dirstate
   730     def d():
   782     def d():
   731         dirstate._map.dirfoldmap.get('a')
   783         dirstate._map.dirfoldmap.get(b'a')
   732         del dirstate._map.dirfoldmap
   784         del dirstate._map.dirfoldmap
   733         del dirstate._map._dirs
   785         del dirstate._map._dirs
   734     timer(d)
   786     timer(d)
   735     fm.end()
   787     fm.end()
   736 
   788 
   737 @command('perfdirstatewrite', formatteropts)
   789 @command(b'perfdirstatewrite', formatteropts)
   738 def perfdirstatewrite(ui, repo, **opts):
   790 def perfdirstatewrite(ui, repo, **opts):
       
   791     opts = _byteskwargs(opts)
   739     timer, fm = gettimer(ui, opts)
   792     timer, fm = gettimer(ui, opts)
   740     ds = repo.dirstate
   793     ds = repo.dirstate
   741     "a" in ds
   794     b"a" in ds
   742     def d():
   795     def d():
   743         ds._dirty = True
   796         ds._dirty = True
   744         ds.write(repo.currenttransaction())
   797         ds.write(repo.currenttransaction())
   745     timer(d)
   798     timer(d)
   746     fm.end()
   799     fm.end()
   747 
   800 
   748 @command('perfmergecalculate',
   801 @command(b'perfmergecalculate',
   749          [('r', 'rev', '.', 'rev to merge against')] + formatteropts)
   802          [(b'r', b'rev', b'.', b'rev to merge against')] + formatteropts)
   750 def perfmergecalculate(ui, repo, rev, **opts):
   803 def perfmergecalculate(ui, repo, rev, **opts):
       
   804     opts = _byteskwargs(opts)
   751     timer, fm = gettimer(ui, opts)
   805     timer, fm = gettimer(ui, opts)
   752     wctx = repo[None]
   806     wctx = repo[None]
   753     rctx = scmutil.revsingle(repo, rev, rev)
   807     rctx = scmutil.revsingle(repo, rev, rev)
   754     ancestor = wctx.ancestor(rctx)
   808     ancestor = wctx.ancestor(rctx)
   755     # we don't want working dir files to be stat'd in the benchmark, so prime
   809     # we don't want working dir files to be stat'd in the benchmark, so prime
   761         merge.calculateupdates(repo, wctx, rctx, [ancestor], False, False,
   815         merge.calculateupdates(repo, wctx, rctx, [ancestor], False, False,
   762                                acceptremote=True, followcopies=True)
   816                                acceptremote=True, followcopies=True)
   763     timer(d)
   817     timer(d)
   764     fm.end()
   818     fm.end()
   765 
   819 
   766 @command('perfpathcopies', [], "REV REV")
   820 @command(b'perfpathcopies', [], b"REV REV")
   767 def perfpathcopies(ui, repo, rev1, rev2, **opts):
   821 def perfpathcopies(ui, repo, rev1, rev2, **opts):
       
   822     opts = _byteskwargs(opts)
   768     timer, fm = gettimer(ui, opts)
   823     timer, fm = gettimer(ui, opts)
   769     ctx1 = scmutil.revsingle(repo, rev1, rev1)
   824     ctx1 = scmutil.revsingle(repo, rev1, rev1)
   770     ctx2 = scmutil.revsingle(repo, rev2, rev2)
   825     ctx2 = scmutil.revsingle(repo, rev2, rev2)
   771     def d():
   826     def d():
   772         copies.pathcopies(ctx1, ctx2)
   827         copies.pathcopies(ctx1, ctx2)
   773     timer(d)
   828     timer(d)
   774     fm.end()
   829     fm.end()
   775 
   830 
   776 @command('perfphases',
   831 @command(b'perfphases',
   777          [('', 'full', False, 'include file reading time too'),
   832          [(b'', b'full', False, b'include file reading time too'),
   778          ], "")
   833           ], b"")
   779 def perfphases(ui, repo, **opts):
   834 def perfphases(ui, repo, **opts):
   780     """benchmark phasesets computation"""
   835     """benchmark phasesets computation"""
       
   836     opts = _byteskwargs(opts)
   781     timer, fm = gettimer(ui, opts)
   837     timer, fm = gettimer(ui, opts)
   782     _phases = repo._phasecache
   838     _phases = repo._phasecache
   783     full = opts.get('full')
   839     full = opts.get(b'full')
   784     def d():
   840     def d():
   785         phases = _phases
   841         phases = _phases
   786         if full:
   842         if full:
   787             clearfilecache(repo, '_phasecache')
   843             clearfilecache(repo, b'_phasecache')
   788             phases = repo._phasecache
   844             phases = repo._phasecache
   789         phases.invalidate()
   845         phases.invalidate()
   790         phases.loadphaserevs(repo)
   846         phases.loadphaserevs(repo)
   791     timer(d)
   847     timer(d)
   792     fm.end()
   848     fm.end()
   793 
   849 
   794 @command('perfphasesremote',
   850 @command(b'perfphasesremote',
   795          [], "[DEST]")
   851          [], b"[DEST]")
   796 def perfphasesremote(ui, repo, dest=None, **opts):
   852 def perfphasesremote(ui, repo, dest=None, **opts):
   797     """benchmark time needed to analyse phases of the remote server"""
   853     """benchmark time needed to analyse phases of the remote server"""
   798     from mercurial.node import (
   854     from mercurial.node import (
   799         bin,
   855         bin,
   800     )
   856     )
   801     from mercurial import (
   857     from mercurial import (
   802         exchange,
   858         exchange,
   803         hg,
   859         hg,
   804         phases,
   860         phases,
   805     )
   861     )
   806     timer, fm = gettimer(ui, opts)
   862     opts = _byteskwargs(opts)
   807 
   863     timer, fm = gettimer(ui, opts)
   808     path = ui.paths.getpath(dest, default=('default-push', 'default'))
   864 
       
   865     path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
   809     if not path:
   866     if not path:
   810         raise error.Abort(('default repository not configured!'),
   867         raise error.Abort((b'default repository not configured!'),
   811                          hint=("see 'hg help config.paths'"))
   868                           hint=(b"see 'hg help config.paths'"))
   812     dest = path.pushloc or path.loc
   869     dest = path.pushloc or path.loc
   813     branches = (path.branch, opts.get('branch') or [])
   870     branches = (path.branch, opts.get(b'branch') or [])
   814     ui.status(('analysing phase of %s\n') % util.hidepassword(dest))
   871     ui.status((b'analysing phase of %s\n') % util.hidepassword(dest))
   815     revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
   872     revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get(b'rev'))
   816     other = hg.peer(repo, opts, dest)
   873     other = hg.peer(repo, opts, dest)
   817 
   874 
   818     # easier to perform discovery through the operation
   875     # easier to perform discovery through the operation
   819     op = exchange.pushoperation(repo, other)
   876     op = exchange.pushoperation(repo, other)
   820     exchange._pushdiscoverychangeset(op)
   877     exchange._pushdiscoverychangeset(op)
   821 
   878 
   822     remotesubset = op.fallbackheads
   879     remotesubset = op.fallbackheads
   823 
   880 
   824     with other.commandexecutor() as e:
   881     with other.commandexecutor() as e:
   825         remotephases = e.callcommand('listkeys',
   882         remotephases = e.callcommand(b'listkeys',
   826                        {'namespace': 'phases'}).result()
   883                        {b'namespace': b'phases'}).result()
   827     del other
   884     del other
   828     publishing = remotephases.get('publishing', False)
   885     publishing = remotephases.get(b'publishing', False)
   829     if publishing:
   886     if publishing:
   830         ui.status(('publishing: yes\n'))
   887         ui.status((b'publishing: yes\n'))
   831     else:
   888     else:
   832         ui.status(('publishing: no\n'))
   889         ui.status((b'publishing: no\n'))
   833 
   890 
   834     nodemap = repo.changelog.nodemap
   891     nodemap = repo.changelog.nodemap
   835     nonpublishroots = 0
   892     nonpublishroots = 0
   836     for nhex, phase in remotephases.iteritems():
   893     for nhex, phase in remotephases.iteritems():
   837         if nhex == 'publishing': # ignore data related to publish option
   894         if nhex == b'publishing': # ignore data related to publish option
   838             continue
   895             continue
   839         node = bin(nhex)
   896         node = bin(nhex)
   840         if node in nodemap and int(phase):
   897         if node in nodemap and int(phase):
   841             nonpublishroots += 1
   898             nonpublishroots += 1
   842     ui.status(('number of roots: %d\n') % len(remotephases))
   899     ui.status((b'number of roots: %d\n') % len(remotephases))
   843     ui.status(('number of known non public roots: %d\n') % nonpublishroots)
   900     ui.status((b'number of known non public roots: %d\n') % nonpublishroots)
   844     def d():
   901     def d():
   845         phases.remotephasessummary(repo,
   902         phases.remotephasessummary(repo,
   846                                    remotesubset,
   903                                    remotesubset,
   847                                    remotephases)
   904                                    remotephases)
   848     timer(d)
   905     timer(d)
   849     fm.end()
   906     fm.end()
   850 
   907 
   851 @command('perfmanifest', [], 'REV')
   908 @command(b'perfmanifest',[
   852 def perfmanifest(ui, repo, rev, **opts):
   909             (b'm', b'manifest-rev', False, b'Look up a manifest node revision'),
       
   910             (b'', b'clear-disk', False, b'clear on-disk caches too'),
       
   911          ] + formatteropts, b'REV|NODE')
       
   912 def perfmanifest(ui, repo, rev, manifest_rev=False, clear_disk=False, **opts):
   853     """benchmark the time to read a manifest from disk and return a usable
   913     """benchmark the time to read a manifest from disk and return a usable
   854     dict-like object
   914     dict-like object
   855 
   915 
   856     Manifest caches are cleared before retrieval."""
   916     Manifest caches are cleared before retrieval."""
   857     timer, fm = gettimer(ui, opts)
   917     opts = _byteskwargs(opts)
   858     ctx = scmutil.revsingle(repo, rev, rev)
   918     timer, fm = gettimer(ui, opts)
   859     t = ctx.manifestnode()
   919     if not manifest_rev:
   860     def d():
   920         ctx = scmutil.revsingle(repo, rev, rev)
   861         repo.manifestlog.clearcaches()
   921         t = ctx.manifestnode()
       
   922     else:
       
   923         from mercurial.node import bin
       
   924 
       
   925         if len(rev) == 40:
       
   926             t = bin(rev)
       
   927         else:
       
   928             try:
       
   929                 rev = int(rev)
       
   930 
       
   931                 if util.safehasattr(repo.manifestlog, b'getstorage'):
       
   932                     t = repo.manifestlog.getstorage(b'').node(rev)
       
   933                 else:
       
   934                     t = repo.manifestlog._revlog.lookup(rev)
       
   935             except ValueError:
       
   936                 raise error.Abort(b'manifest revision must be integer or full '
       
   937                                   b'node')
       
   938     def d():
       
   939         repo.manifestlog.clearcaches(clear_persisted_data=clear_disk)
   862         repo.manifestlog[t].read()
   940         repo.manifestlog[t].read()
   863     timer(d)
   941     timer(d)
   864     fm.end()
   942     fm.end()
   865 
   943 
   866 @command('perfchangeset', formatteropts)
   944 @command(b'perfchangeset', formatteropts)
   867 def perfchangeset(ui, repo, rev, **opts):
   945 def perfchangeset(ui, repo, rev, **opts):
       
   946     opts = _byteskwargs(opts)
   868     timer, fm = gettimer(ui, opts)
   947     timer, fm = gettimer(ui, opts)
   869     n = scmutil.revsingle(repo, rev).node()
   948     n = scmutil.revsingle(repo, rev).node()
   870     def d():
   949     def d():
   871         repo.changelog.read(n)
   950         repo.changelog.read(n)
   872         #repo.changelog._cache = None
   951         #repo.changelog._cache = None
   873     timer(d)
   952     timer(d)
   874     fm.end()
   953     fm.end()
   875 
   954 
   876 @command('perfindex', formatteropts)
   955 @command(b'perfindex', formatteropts)
   877 def perfindex(ui, repo, **opts):
   956 def perfindex(ui, repo, **opts):
   878     import mercurial.revlog
   957     import mercurial.revlog
       
   958     opts = _byteskwargs(opts)
   879     timer, fm = gettimer(ui, opts)
   959     timer, fm = gettimer(ui, opts)
   880     mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
   960     mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
   881     n = repo["tip"].node()
   961     n = repo[b"tip"].node()
   882     svfs = getsvfs(repo)
   962     svfs = getsvfs(repo)
   883     def d():
   963     def d():
   884         cl = mercurial.revlog.revlog(svfs, "00changelog.i")
   964         cl = mercurial.revlog.revlog(svfs, b"00changelog.i")
   885         cl.rev(n)
   965         cl.rev(n)
   886     timer(d)
   966     timer(d)
   887     fm.end()
   967     fm.end()
   888 
   968 
   889 @command('perfstartup', formatteropts)
   969 @command(b'perfstartup', formatteropts)
   890 def perfstartup(ui, repo, **opts):
   970 def perfstartup(ui, repo, **opts):
   891     timer, fm = gettimer(ui, opts)
   971     opts = _byteskwargs(opts)
   892     cmd = sys.argv[0]
   972     timer, fm = gettimer(ui, opts)
   893     def d():
   973     def d():
   894         if os.name != 'nt':
   974         if os.name != r'nt':
   895             os.system("HGRCPATH= %s version -q > /dev/null" % cmd)
   975             os.system(b"HGRCPATH= %s version -q > /dev/null" %
       
   976                       fsencode(sys.argv[0]))
   896         else:
   977         else:
   897             os.environ['HGRCPATH'] = ' '
   978             os.environ[r'HGRCPATH'] = r' '
   898             os.system("%s version -q > NUL" % cmd)
   979             os.system(r"%s version -q > NUL" % sys.argv[0])
   899     timer(d)
   980     timer(d)
   900     fm.end()
   981     fm.end()
   901 
   982 
   902 @command('perfparents', formatteropts)
   983 @command(b'perfparents', formatteropts)
   903 def perfparents(ui, repo, **opts):
   984 def perfparents(ui, repo, **opts):
       
   985     opts = _byteskwargs(opts)
   904     timer, fm = gettimer(ui, opts)
   986     timer, fm = gettimer(ui, opts)
   905     # control the number of commits perfparents iterates over
   987     # control the number of commits perfparents iterates over
   906     # experimental config: perf.parentscount
   988     # experimental config: perf.parentscount
   907     count = getint(ui, "perf", "parentscount", 1000)
   989     count = getint(ui, b"perf", b"parentscount", 1000)
   908     if len(repo.changelog) < count:
   990     if len(repo.changelog) < count:
   909         raise error.Abort("repo needs %d commits for this test" % count)
   991         raise error.Abort(b"repo needs %d commits for this test" % count)
   910     repo = repo.unfiltered()
   992     repo = repo.unfiltered()
   911     nl = [repo.changelog.node(i) for i in xrange(count)]
   993     nl = [repo.changelog.node(i) for i in _xrange(count)]
   912     def d():
   994     def d():
   913         for n in nl:
   995         for n in nl:
   914             repo.changelog.parents(n)
   996             repo.changelog.parents(n)
   915     timer(d)
   997     timer(d)
   916     fm.end()
   998     fm.end()
   917 
   999 
   918 @command('perfctxfiles', formatteropts)
  1000 @command(b'perfctxfiles', formatteropts)
   919 def perfctxfiles(ui, repo, x, **opts):
  1001 def perfctxfiles(ui, repo, x, **opts):
       
  1002     opts = _byteskwargs(opts)
   920     x = int(x)
  1003     x = int(x)
   921     timer, fm = gettimer(ui, opts)
  1004     timer, fm = gettimer(ui, opts)
   922     def d():
  1005     def d():
   923         len(repo[x].files())
  1006         len(repo[x].files())
   924     timer(d)
  1007     timer(d)
   925     fm.end()
  1008     fm.end()
   926 
  1009 
   927 @command('perfrawfiles', formatteropts)
  1010 @command(b'perfrawfiles', formatteropts)
   928 def perfrawfiles(ui, repo, x, **opts):
  1011 def perfrawfiles(ui, repo, x, **opts):
       
  1012     opts = _byteskwargs(opts)
   929     x = int(x)
  1013     x = int(x)
   930     timer, fm = gettimer(ui, opts)
  1014     timer, fm = gettimer(ui, opts)
   931     cl = repo.changelog
  1015     cl = repo.changelog
   932     def d():
  1016     def d():
   933         len(cl.read(x)[3])
  1017         len(cl.read(x)[3])
   934     timer(d)
  1018     timer(d)
   935     fm.end()
  1019     fm.end()
   936 
  1020 
   937 @command('perflookup', formatteropts)
  1021 @command(b'perflookup', formatteropts)
   938 def perflookup(ui, repo, rev, **opts):
  1022 def perflookup(ui, repo, rev, **opts):
       
  1023     opts = _byteskwargs(opts)
   939     timer, fm = gettimer(ui, opts)
  1024     timer, fm = gettimer(ui, opts)
   940     timer(lambda: len(repo.lookup(rev)))
  1025     timer(lambda: len(repo.lookup(rev)))
   941     fm.end()
  1026     fm.end()
   942 
  1027 
   943 @command('perfrevrange', formatteropts)
  1028 @command(b'perflinelogedits',
       
  1029          [(b'n', b'edits', 10000, b'number of edits'),
       
  1030           (b'', b'max-hunk-lines', 10, b'max lines in a hunk'),
       
  1031           ], norepo=True)
       
  1032 def perflinelogedits(ui, **opts):
       
  1033     from mercurial import linelog
       
  1034 
       
  1035     opts = _byteskwargs(opts)
       
  1036 
       
  1037     edits = opts[b'edits']
       
  1038     maxhunklines = opts[b'max_hunk_lines']
       
  1039 
       
  1040     maxb1 = 100000
       
  1041     random.seed(0)
       
  1042     randint = random.randint
       
  1043     currentlines = 0
       
  1044     arglist = []
       
  1045     for rev in _xrange(edits):
       
  1046         a1 = randint(0, currentlines)
       
  1047         a2 = randint(a1, min(currentlines, a1 + maxhunklines))
       
  1048         b1 = randint(0, maxb1)
       
  1049         b2 = randint(b1, b1 + maxhunklines)
       
  1050         currentlines += (b2 - b1) - (a2 - a1)
       
  1051         arglist.append((rev, a1, a2, b1, b2))
       
  1052 
       
  1053     def d():
       
  1054         ll = linelog.linelog()
       
  1055         for args in arglist:
       
  1056             ll.replacelines(*args)
       
  1057 
       
  1058     timer, fm = gettimer(ui, opts)
       
  1059     timer(d)
       
  1060     fm.end()
       
  1061 
       
  1062 @command(b'perfrevrange', formatteropts)
   944 def perfrevrange(ui, repo, *specs, **opts):
  1063 def perfrevrange(ui, repo, *specs, **opts):
       
  1064     opts = _byteskwargs(opts)
   945     timer, fm = gettimer(ui, opts)
  1065     timer, fm = gettimer(ui, opts)
   946     revrange = scmutil.revrange
  1066     revrange = scmutil.revrange
   947     timer(lambda: len(revrange(repo, specs)))
  1067     timer(lambda: len(revrange(repo, specs)))
   948     fm.end()
  1068     fm.end()
   949 
  1069 
   950 @command('perfnodelookup', formatteropts)
  1070 @command(b'perfnodelookup', formatteropts)
   951 def perfnodelookup(ui, repo, rev, **opts):
  1071 def perfnodelookup(ui, repo, rev, **opts):
       
  1072     opts = _byteskwargs(opts)
   952     timer, fm = gettimer(ui, opts)
  1073     timer, fm = gettimer(ui, opts)
   953     import mercurial.revlog
  1074     import mercurial.revlog
   954     mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
  1075     mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg
   955     n = scmutil.revsingle(repo, rev).node()
  1076     n = scmutil.revsingle(repo, rev).node()
   956     cl = mercurial.revlog.revlog(getsvfs(repo), "00changelog.i")
  1077     cl = mercurial.revlog.revlog(getsvfs(repo), b"00changelog.i")
   957     def d():
  1078     def d():
   958         cl.rev(n)
  1079         cl.rev(n)
   959         clearcaches(cl)
  1080         clearcaches(cl)
   960     timer(d)
  1081     timer(d)
   961     fm.end()
  1082     fm.end()
   962 
  1083 
   963 @command('perflog',
  1084 @command(b'perflog',
   964          [('', 'rename', False, 'ask log to follow renames')] + formatteropts)
  1085          [(b'', b'rename', False, b'ask log to follow renames')
       
  1086          ] + formatteropts)
   965 def perflog(ui, repo, rev=None, **opts):
  1087 def perflog(ui, repo, rev=None, **opts):
       
  1088     opts = _byteskwargs(opts)
   966     if rev is None:
  1089     if rev is None:
   967         rev=[]
  1090         rev=[]
   968     timer, fm = gettimer(ui, opts)
  1091     timer, fm = gettimer(ui, opts)
   969     ui.pushbuffer()
  1092     ui.pushbuffer()
   970     timer(lambda: commands.log(ui, repo, rev=rev, date='', user='',
  1093     timer(lambda: commands.log(ui, repo, rev=rev, date=b'', user=b'',
   971                                copies=opts.get('rename')))
  1094                                copies=opts.get(b'rename')))
   972     ui.popbuffer()
  1095     ui.popbuffer()
   973     fm.end()
  1096     fm.end()
   974 
  1097 
   975 @command('perfmoonwalk', formatteropts)
  1098 @command(b'perfmoonwalk', formatteropts)
   976 def perfmoonwalk(ui, repo, **opts):
  1099 def perfmoonwalk(ui, repo, **opts):
   977     """benchmark walking the changelog backwards
  1100     """benchmark walking the changelog backwards
   978 
  1101 
   979     This also loads the changelog data for each revision in the changelog.
  1102     This also loads the changelog data for each revision in the changelog.
   980     """
  1103     """
       
  1104     opts = _byteskwargs(opts)
   981     timer, fm = gettimer(ui, opts)
  1105     timer, fm = gettimer(ui, opts)
   982     def moonwalk():
  1106     def moonwalk():
   983         for i in xrange(len(repo), -1, -1):
  1107         for i in repo.changelog.revs(start=(len(repo) - 1), stop=-1):
   984             ctx = repo[i]
  1108             ctx = repo[i]
   985             ctx.branch() # read changelog data (in addition to the index)
  1109             ctx.branch() # read changelog data (in addition to the index)
   986     timer(moonwalk)
  1110     timer(moonwalk)
   987     fm.end()
  1111     fm.end()
   988 
  1112 
   989 @command('perftemplating',
  1113 @command(b'perftemplating',
   990          [('r', 'rev', [], 'revisions to run the template on'),
  1114          [(b'r', b'rev', [], b'revisions to run the template on'),
   991          ] + formatteropts)
  1115           ] + formatteropts)
   992 def perftemplating(ui, repo, testedtemplate=None, **opts):
  1116 def perftemplating(ui, repo, testedtemplate=None, **opts):
   993     """test the rendering time of a given template"""
  1117     """test the rendering time of a given template"""
   994     if makelogtemplater is None:
  1118     if makelogtemplater is None:
   995         raise error.Abort(("perftemplating not available with this Mercurial"),
  1119         raise error.Abort((b"perftemplating not available with this Mercurial"),
   996                           hint="use 4.3 or later")
  1120                           hint=b"use 4.3 or later")
       
  1121 
       
  1122     opts = _byteskwargs(opts)
   997 
  1123 
   998     nullui = ui.copy()
  1124     nullui = ui.copy()
   999     nullui.fout = open(os.devnull, 'wb')
  1125     nullui.fout = open(os.devnull, r'wb')
  1000     nullui.disablepager()
  1126     nullui.disablepager()
  1001     revs = opts.get('rev')
  1127     revs = opts.get(b'rev')
  1002     if not revs:
  1128     if not revs:
  1003         revs = ['all()']
  1129         revs = [b'all()']
  1004     revs = list(scmutil.revrange(repo, revs))
  1130     revs = list(scmutil.revrange(repo, revs))
  1005 
  1131 
  1006     defaulttemplate = ('{date|shortdate} [{rev}:{node|short}]'
  1132     defaulttemplate = (b'{date|shortdate} [{rev}:{node|short}]'
  1007                        ' {author|person}: {desc|firstline}\n')
  1133                        b' {author|person}: {desc|firstline}\n')
  1008     if testedtemplate is None:
  1134     if testedtemplate is None:
  1009         testedtemplate = defaulttemplate
  1135         testedtemplate = defaulttemplate
  1010     displayer = makelogtemplater(nullui, repo, testedtemplate)
  1136     displayer = makelogtemplater(nullui, repo, testedtemplate)
  1011     def format():
  1137     def format():
  1012         for r in revs:
  1138         for r in revs:
  1016 
  1142 
  1017     timer, fm = gettimer(ui, opts)
  1143     timer, fm = gettimer(ui, opts)
  1018     timer(format)
  1144     timer(format)
  1019     fm.end()
  1145     fm.end()
  1020 
  1146 
  1021 @command('perfcca', formatteropts)
  1147 @command(b'perfcca', formatteropts)
  1022 def perfcca(ui, repo, **opts):
  1148 def perfcca(ui, repo, **opts):
       
  1149     opts = _byteskwargs(opts)
  1023     timer, fm = gettimer(ui, opts)
  1150     timer, fm = gettimer(ui, opts)
  1024     timer(lambda: scmutil.casecollisionauditor(ui, False, repo.dirstate))
  1151     timer(lambda: scmutil.casecollisionauditor(ui, False, repo.dirstate))
  1025     fm.end()
  1152     fm.end()
  1026 
  1153 
  1027 @command('perffncacheload', formatteropts)
  1154 @command(b'perffncacheload', formatteropts)
  1028 def perffncacheload(ui, repo, **opts):
  1155 def perffncacheload(ui, repo, **opts):
       
  1156     opts = _byteskwargs(opts)
  1029     timer, fm = gettimer(ui, opts)
  1157     timer, fm = gettimer(ui, opts)
  1030     s = repo.store
  1158     s = repo.store
  1031     def d():
  1159     def d():
  1032         s.fncache._load()
  1160         s.fncache._load()
  1033     timer(d)
  1161     timer(d)
  1034     fm.end()
  1162     fm.end()
  1035 
  1163 
  1036 @command('perffncachewrite', formatteropts)
  1164 @command(b'perffncachewrite', formatteropts)
  1037 def perffncachewrite(ui, repo, **opts):
  1165 def perffncachewrite(ui, repo, **opts):
       
  1166     opts = _byteskwargs(opts)
  1038     timer, fm = gettimer(ui, opts)
  1167     timer, fm = gettimer(ui, opts)
  1039     s = repo.store
  1168     s = repo.store
  1040     lock = repo.lock()
  1169     lock = repo.lock()
  1041     s.fncache._load()
  1170     s.fncache._load()
  1042     tr = repo.transaction('perffncachewrite')
  1171     tr = repo.transaction(b'perffncachewrite')
  1043     tr.addbackup('fncache')
  1172     tr.addbackup(b'fncache')
  1044     def d():
  1173     def d():
  1045         s.fncache._dirty = True
  1174         s.fncache._dirty = True
  1046         s.fncache.write(tr)
  1175         s.fncache.write(tr)
  1047     timer(d)
  1176     timer(d)
  1048     tr.close()
  1177     tr.close()
  1049     lock.release()
  1178     lock.release()
  1050     fm.end()
  1179     fm.end()
  1051 
  1180 
  1052 @command('perffncacheencode', formatteropts)
  1181 @command(b'perffncacheencode', formatteropts)
  1053 def perffncacheencode(ui, repo, **opts):
  1182 def perffncacheencode(ui, repo, **opts):
       
  1183     opts = _byteskwargs(opts)
  1054     timer, fm = gettimer(ui, opts)
  1184     timer, fm = gettimer(ui, opts)
  1055     s = repo.store
  1185     s = repo.store
  1056     s.fncache._load()
  1186     s.fncache._load()
  1057     def d():
  1187     def d():
  1058         for p in s.fncache.entries:
  1188         for p in s.fncache.entries:
  1074             pair = q.get()
  1204             pair = q.get()
  1075         q.task_done() # for the None one
  1205         q.task_done() # for the None one
  1076         with ready:
  1206         with ready:
  1077             ready.wait()
  1207             ready.wait()
  1078 
  1208 
  1079 @command('perfbdiff', revlogopts + formatteropts + [
  1209 def _manifestrevision(repo, mnode):
  1080     ('', 'count', 1, 'number of revisions to test (when using --startrev)'),
  1210     ml = repo.manifestlog
  1081     ('', 'alldata', False, 'test bdiffs for all associated revisions'),
  1211 
  1082     ('', 'threads', 0, 'number of thread to use (disable with 0)'),
  1212     if util.safehasattr(ml, b'getstorage'):
  1083     ('', 'blocks', False, 'test computing diffs into blocks'),
  1213         store = ml.getstorage(b'')
  1084     ('', 'xdiff', False, 'use xdiff algorithm'),
  1214     else:
       
  1215         store = ml._revlog
       
  1216 
       
  1217     return store.revision(mnode)
       
  1218 
       
  1219 @command(b'perfbdiff', revlogopts + formatteropts + [
       
  1220     (b'', b'count', 1, b'number of revisions to test (when using --startrev)'),
       
  1221     (b'', b'alldata', False, b'test bdiffs for all associated revisions'),
       
  1222     (b'', b'threads', 0, b'number of thread to use (disable with 0)'),
       
  1223     (b'', b'blocks', False, b'test computing diffs into blocks'),
       
  1224     (b'', b'xdiff', False, b'use xdiff algorithm'),
  1085     ],
  1225     ],
  1086 
  1226 
  1087     '-c|-m|FILE REV')
  1227     b'-c|-m|FILE REV')
  1088 def perfbdiff(ui, repo, file_, rev=None, count=None, threads=0, **opts):
  1228 def perfbdiff(ui, repo, file_, rev=None, count=None, threads=0, **opts):
  1089     """benchmark a bdiff between revisions
  1229     """benchmark a bdiff between revisions
  1090 
  1230 
  1091     By default, benchmark a bdiff between its delta parent and itself.
  1231     By default, benchmark a bdiff between its delta parent and itself.
  1092 
  1232 
  1095 
  1235 
  1096     With ``--alldata``, assume the requested revision is a changeset and
  1236     With ``--alldata``, assume the requested revision is a changeset and
  1097     measure bdiffs for all changes related to that changeset (manifest
  1237     measure bdiffs for all changes related to that changeset (manifest
  1098     and filelogs).
  1238     and filelogs).
  1099     """
  1239     """
  1100     opts = pycompat.byteskwargs(opts)
  1240     opts = _byteskwargs(opts)
  1101 
  1241 
  1102     if opts['xdiff'] and not opts['blocks']:
  1242     if opts[b'xdiff'] and not opts[b'blocks']:
  1103         raise error.CommandError('perfbdiff', '--xdiff requires --blocks')
  1243         raise error.CommandError(b'perfbdiff', b'--xdiff requires --blocks')
  1104 
  1244 
  1105     if opts['alldata']:
  1245     if opts[b'alldata']:
  1106         opts['changelog'] = True
  1246         opts[b'changelog'] = True
  1107 
  1247 
  1108     if opts.get('changelog') or opts.get('manifest'):
  1248     if opts.get(b'changelog') or opts.get(b'manifest'):
  1109         file_, rev = None, file_
  1249         file_, rev = None, file_
  1110     elif rev is None:
  1250     elif rev is None:
  1111         raise error.CommandError('perfbdiff', 'invalid arguments')
  1251         raise error.CommandError(b'perfbdiff', b'invalid arguments')
  1112 
  1252 
  1113     blocks = opts['blocks']
  1253     blocks = opts[b'blocks']
  1114     xdiff = opts['xdiff']
  1254     xdiff = opts[b'xdiff']
  1115     textpairs = []
  1255     textpairs = []
  1116 
  1256 
  1117     r = cmdutil.openrevlog(repo, 'perfbdiff', file_, opts)
  1257     r = cmdutil.openrevlog(repo, b'perfbdiff', file_, opts)
  1118 
  1258 
  1119     startrev = r.rev(r.lookup(rev))
  1259     startrev = r.rev(r.lookup(rev))
  1120     for rev in range(startrev, min(startrev + count, len(r) - 1)):
  1260     for rev in range(startrev, min(startrev + count, len(r) - 1)):
  1121         if opts['alldata']:
  1261         if opts[b'alldata']:
  1122             # Load revisions associated with changeset.
  1262             # Load revisions associated with changeset.
  1123             ctx = repo[rev]
  1263             ctx = repo[rev]
  1124             mtext = repo.manifestlog._revlog.revision(ctx.manifestnode())
  1264             mtext = _manifestrevision(repo, ctx.manifestnode())
  1125             for pctx in ctx.parents():
  1265             for pctx in ctx.parents():
  1126                 pman = repo.manifestlog._revlog.revision(pctx.manifestnode())
  1266                 pman = _manifestrevision(repo, pctx.manifestnode())
  1127                 textpairs.append((pman, mtext))
  1267                 textpairs.append((pman, mtext))
  1128 
  1268 
  1129             # Load filelog revisions by iterating manifest delta.
  1269             # Load filelog revisions by iterating manifest delta.
  1130             man = ctx.manifest()
  1270             man = ctx.manifest()
  1131             pman = ctx.p1().manifest()
  1271             pman = ctx.p1().manifest()
  1148                     mdiff.bdiff.blocks(*pair)
  1288                     mdiff.bdiff.blocks(*pair)
  1149                 else:
  1289                 else:
  1150                     mdiff.textdiff(*pair)
  1290                     mdiff.textdiff(*pair)
  1151     else:
  1291     else:
  1152         q = queue()
  1292         q = queue()
  1153         for i in xrange(threads):
  1293         for i in _xrange(threads):
  1154             q.put(None)
  1294             q.put(None)
  1155         ready = threading.Condition()
  1295         ready = threading.Condition()
  1156         done = threading.Event()
  1296         done = threading.Event()
  1157         for i in xrange(threads):
  1297         for i in _xrange(threads):
  1158             threading.Thread(target=_bdiffworker,
  1298             threading.Thread(target=_bdiffworker,
  1159                              args=(q, blocks, xdiff, ready, done)).start()
  1299                              args=(q, blocks, xdiff, ready, done)).start()
  1160         q.join()
  1300         q.join()
  1161         def d():
  1301         def d():
  1162             for pair in textpairs:
  1302             for pair in textpairs:
  1163                 q.put(pair)
  1303                 q.put(pair)
  1164             for i in xrange(threads):
  1304             for i in _xrange(threads):
  1165                 q.put(None)
  1305                 q.put(None)
  1166             with ready:
  1306             with ready:
  1167                 ready.notify_all()
  1307                 ready.notify_all()
  1168             q.join()
  1308             q.join()
  1169     timer, fm = gettimer(ui, opts)
  1309     timer, fm = gettimer(ui, opts)
  1170     timer(d)
  1310     timer(d)
  1171     fm.end()
  1311     fm.end()
  1172 
  1312 
  1173     if withthreads:
  1313     if withthreads:
  1174         done.set()
  1314         done.set()
  1175         for i in xrange(threads):
  1315         for i in _xrange(threads):
  1176             q.put(None)
  1316             q.put(None)
  1177         with ready:
  1317         with ready:
  1178             ready.notify_all()
  1318             ready.notify_all()
  1179 
  1319 
  1180 @command('perfunidiff', revlogopts + formatteropts + [
  1320 @command(b'perfunidiff', revlogopts + formatteropts + [
  1181     ('', 'count', 1, 'number of revisions to test (when using --startrev)'),
  1321     (b'', b'count', 1, b'number of revisions to test (when using --startrev)'),
  1182     ('', 'alldata', False, 'test unidiffs for all associated revisions'),
  1322     (b'', b'alldata', False, b'test unidiffs for all associated revisions'),
  1183     ], '-c|-m|FILE REV')
  1323     ], b'-c|-m|FILE REV')
  1184 def perfunidiff(ui, repo, file_, rev=None, count=None, **opts):
  1324 def perfunidiff(ui, repo, file_, rev=None, count=None, **opts):
  1185     """benchmark a unified diff between revisions
  1325     """benchmark a unified diff between revisions
  1186 
  1326 
  1187     This doesn't include any copy tracing - it's just a unified diff
  1327     This doesn't include any copy tracing - it's just a unified diff
  1188     of the texts.
  1328     of the texts.
  1194 
  1334 
  1195     With ``--alldata``, assume the requested revision is a changeset and
  1335     With ``--alldata``, assume the requested revision is a changeset and
  1196     measure diffs for all changes related to that changeset (manifest
  1336     measure diffs for all changes related to that changeset (manifest
  1197     and filelogs).
  1337     and filelogs).
  1198     """
  1338     """
  1199     if opts['alldata']:
  1339     opts = _byteskwargs(opts)
  1200         opts['changelog'] = True
  1340     if opts[b'alldata']:
  1201 
  1341         opts[b'changelog'] = True
  1202     if opts.get('changelog') or opts.get('manifest'):
  1342 
       
  1343     if opts.get(b'changelog') or opts.get(b'manifest'):
  1203         file_, rev = None, file_
  1344         file_, rev = None, file_
  1204     elif rev is None:
  1345     elif rev is None:
  1205         raise error.CommandError('perfunidiff', 'invalid arguments')
  1346         raise error.CommandError(b'perfunidiff', b'invalid arguments')
  1206 
  1347 
  1207     textpairs = []
  1348     textpairs = []
  1208 
  1349 
  1209     r = cmdutil.openrevlog(repo, 'perfunidiff', file_, opts)
  1350     r = cmdutil.openrevlog(repo, b'perfunidiff', file_, opts)
  1210 
  1351 
  1211     startrev = r.rev(r.lookup(rev))
  1352     startrev = r.rev(r.lookup(rev))
  1212     for rev in range(startrev, min(startrev + count, len(r) - 1)):
  1353     for rev in range(startrev, min(startrev + count, len(r) - 1)):
  1213         if opts['alldata']:
  1354         if opts[b'alldata']:
  1214             # Load revisions associated with changeset.
  1355             # Load revisions associated with changeset.
  1215             ctx = repo[rev]
  1356             ctx = repo[rev]
  1216             mtext = repo.manifestlog._revlog.revision(ctx.manifestnode())
  1357             mtext = _manifestrevision(repo, ctx.manifestnode())
  1217             for pctx in ctx.parents():
  1358             for pctx in ctx.parents():
  1218                 pman = repo.manifestlog._revlog.revision(pctx.manifestnode())
  1359                 pman = _manifestrevision(repo, pctx.manifestnode())
  1219                 textpairs.append((pman, mtext))
  1360                 textpairs.append((pman, mtext))
  1220 
  1361 
  1221             # Load filelog revisions by iterating manifest delta.
  1362             # Load filelog revisions by iterating manifest delta.
  1222             man = ctx.manifest()
  1363             man = ctx.manifest()
  1223             pman = ctx.p1().manifest()
  1364             pman = ctx.p1().manifest()
  1232 
  1373 
  1233     def d():
  1374     def d():
  1234         for left, right in textpairs:
  1375         for left, right in textpairs:
  1235             # The date strings don't matter, so we pass empty strings.
  1376             # The date strings don't matter, so we pass empty strings.
  1236             headerlines, hunks = mdiff.unidiff(
  1377             headerlines, hunks = mdiff.unidiff(
  1237                 left, '', right, '', 'left', 'right', binary=False)
  1378                 left, b'', right, b'', b'left', b'right', binary=False)
  1238             # consume iterators in roughly the way patch.py does
  1379             # consume iterators in roughly the way patch.py does
  1239             b'\n'.join(headerlines)
  1380             b'\n'.join(headerlines)
  1240             b''.join(sum((list(hlines) for hrange, hlines in hunks), []))
  1381             b''.join(sum((list(hlines) for hrange, hlines in hunks), []))
  1241     timer, fm = gettimer(ui, opts)
  1382     timer, fm = gettimer(ui, opts)
  1242     timer(d)
  1383     timer(d)
  1243     fm.end()
  1384     fm.end()
  1244 
  1385 
  1245 @command('perfdiffwd', formatteropts)
  1386 @command(b'perfdiffwd', formatteropts)
  1246 def perfdiffwd(ui, repo, **opts):
  1387 def perfdiffwd(ui, repo, **opts):
  1247     """Profile diff of working directory changes"""
  1388     """Profile diff of working directory changes"""
       
  1389     opts = _byteskwargs(opts)
  1248     timer, fm = gettimer(ui, opts)
  1390     timer, fm = gettimer(ui, opts)
  1249     options = {
  1391     options = {
  1250         'w': 'ignore_all_space',
  1392         'w': 'ignore_all_space',
  1251         'b': 'ignore_space_change',
  1393         'b': 'ignore_space_change',
  1252         'B': 'ignore_blank_lines',
  1394         'B': 'ignore_blank_lines',
  1253         }
  1395         }
  1254 
  1396 
  1255     for diffopt in ('', 'w', 'b', 'B', 'wB'):
  1397     for diffopt in ('', 'w', 'b', 'B', 'wB'):
  1256         opts = dict((options[c], '1') for c in diffopt)
  1398         opts = dict((options[c], b'1') for c in diffopt)
  1257         def d():
  1399         def d():
  1258             ui.pushbuffer()
  1400             ui.pushbuffer()
  1259             commands.diff(ui, repo, **opts)
  1401             commands.diff(ui, repo, **opts)
  1260             ui.popbuffer()
  1402             ui.popbuffer()
  1261         title = 'diffopts: %s' % (diffopt and ('-' + diffopt) or 'none')
  1403         diffopt = diffopt.encode('ascii')
       
  1404         title = b'diffopts: %s' % (diffopt and (b'-' + diffopt) or b'none')
  1262         timer(d, title)
  1405         timer(d, title)
  1263     fm.end()
  1406     fm.end()
  1264 
  1407 
  1265 @command('perfrevlogindex', revlogopts + formatteropts,
  1408 @command(b'perfrevlogindex', revlogopts + formatteropts,
  1266          '-c|-m|FILE')
  1409          b'-c|-m|FILE')
  1267 def perfrevlogindex(ui, repo, file_=None, **opts):
  1410 def perfrevlogindex(ui, repo, file_=None, **opts):
  1268     """Benchmark operations against a revlog index.
  1411     """Benchmark operations against a revlog index.
  1269 
  1412 
  1270     This tests constructing a revlog instance, reading index data,
  1413     This tests constructing a revlog instance, reading index data,
  1271     parsing index data, and performing various operations related to
  1414     parsing index data, and performing various operations related to
  1272     index data.
  1415     index data.
  1273     """
  1416     """
  1274 
  1417 
  1275     rl = cmdutil.openrevlog(repo, 'perfrevlogindex', file_, opts)
  1418     opts = _byteskwargs(opts)
       
  1419 
       
  1420     rl = cmdutil.openrevlog(repo, b'perfrevlogindex', file_, opts)
  1276 
  1421 
  1277     opener = getattr(rl, 'opener')  # trick linter
  1422     opener = getattr(rl, 'opener')  # trick linter
  1278     indexfile = rl.indexfile
  1423     indexfile = rl.indexfile
  1279     data = opener.read(indexfile)
  1424     data = opener.read(indexfile)
  1280 
  1425 
  1281     header = struct.unpack('>I', data[0:4])[0]
  1426     header = struct.unpack(b'>I', data[0:4])[0]
  1282     version = header & 0xFFFF
  1427     version = header & 0xFFFF
  1283     if version == 1:
  1428     if version == 1:
  1284         revlogio = revlog.revlogio()
  1429         revlogio = revlog.revlogio()
  1285         inline = header & (1 << 16)
  1430         inline = header & (1 << 16)
  1286     else:
  1431     else:
  1287         raise error.Abort(('unsupported revlog version: %d') % version)
  1432         raise error.Abort((b'unsupported revlog version: %d') % version)
  1288 
  1433 
  1289     rllen = len(rl)
  1434     rllen = len(rl)
  1290 
  1435 
  1291     node0 = rl.node(0)
  1436     node0 = rl.node(0)
  1292     node25 = rl.node(rllen // 4)
  1437     node25 = rl.node(rllen // 4)
  1342                     nodemap[node]
  1487                     nodemap[node]
  1343                 except error.RevlogError:
  1488                 except error.RevlogError:
  1344                     pass
  1489                     pass
  1345 
  1490 
  1346     benches = [
  1491     benches = [
  1347         (constructor, 'revlog constructor'),
  1492         (constructor, b'revlog constructor'),
  1348         (read, 'read'),
  1493         (read, b'read'),
  1349         (parseindex, 'create index object'),
  1494         (parseindex, b'create index object'),
  1350         (lambda: getentry(0), 'retrieve index entry for rev 0'),
  1495         (lambda: getentry(0), b'retrieve index entry for rev 0'),
  1351         (lambda: resolvenode('a' * 20), 'look up missing node'),
  1496         (lambda: resolvenode(b'a' * 20), b'look up missing node'),
  1352         (lambda: resolvenode(node0), 'look up node at rev 0'),
  1497         (lambda: resolvenode(node0), b'look up node at rev 0'),
  1353         (lambda: resolvenode(node25), 'look up node at 1/4 len'),
  1498         (lambda: resolvenode(node25), b'look up node at 1/4 len'),
  1354         (lambda: resolvenode(node50), 'look up node at 1/2 len'),
  1499         (lambda: resolvenode(node50), b'look up node at 1/2 len'),
  1355         (lambda: resolvenode(node75), 'look up node at 3/4 len'),
  1500         (lambda: resolvenode(node75), b'look up node at 3/4 len'),
  1356         (lambda: resolvenode(node100), 'look up node at tip'),
  1501         (lambda: resolvenode(node100), b'look up node at tip'),
  1357         # 2x variation is to measure caching impact.
  1502         # 2x variation is to measure caching impact.
  1358         (lambda: resolvenodes(allnodes),
  1503         (lambda: resolvenodes(allnodes),
  1359          'look up all nodes (forward)'),
  1504          b'look up all nodes (forward)'),
  1360         (lambda: resolvenodes(allnodes, 2),
  1505         (lambda: resolvenodes(allnodes, 2),
  1361          'look up all nodes 2x (forward)'),
  1506          b'look up all nodes 2x (forward)'),
  1362         (lambda: resolvenodes(allnodesrev),
  1507         (lambda: resolvenodes(allnodesrev),
  1363          'look up all nodes (reverse)'),
  1508          b'look up all nodes (reverse)'),
  1364         (lambda: resolvenodes(allnodesrev, 2),
  1509         (lambda: resolvenodes(allnodesrev, 2),
  1365          'look up all nodes 2x (reverse)'),
  1510          b'look up all nodes 2x (reverse)'),
  1366         (lambda: getentries(allrevs),
  1511         (lambda: getentries(allrevs),
  1367          'retrieve all index entries (forward)'),
  1512          b'retrieve all index entries (forward)'),
  1368         (lambda: getentries(allrevs, 2),
  1513         (lambda: getentries(allrevs, 2),
  1369          'retrieve all index entries 2x (forward)'),
  1514          b'retrieve all index entries 2x (forward)'),
  1370         (lambda: getentries(allrevsrev),
  1515         (lambda: getentries(allrevsrev),
  1371          'retrieve all index entries (reverse)'),
  1516          b'retrieve all index entries (reverse)'),
  1372         (lambda: getentries(allrevsrev, 2),
  1517         (lambda: getentries(allrevsrev, 2),
  1373          'retrieve all index entries 2x (reverse)'),
  1518          b'retrieve all index entries 2x (reverse)'),
  1374     ]
  1519     ]
  1375 
  1520 
  1376     for fn, title in benches:
  1521     for fn, title in benches:
  1377         timer, fm = gettimer(ui, opts)
  1522         timer, fm = gettimer(ui, opts)
  1378         timer(fn, title=title)
  1523         timer(fn, title=title)
  1379         fm.end()
  1524         fm.end()
  1380 
  1525 
  1381 @command('perfrevlogrevisions', revlogopts + formatteropts +
  1526 @command(b'perfrevlogrevisions', revlogopts + formatteropts +
  1382          [('d', 'dist', 100, 'distance between the revisions'),
  1527          [(b'd', b'dist', 100, b'distance between the revisions'),
  1383           ('s', 'startrev', 0, 'revision to start reading at'),
  1528           (b's', b'startrev', 0, b'revision to start reading at'),
  1384           ('', 'reverse', False, 'read in reverse')],
  1529           (b'', b'reverse', False, b'read in reverse')],
  1385          '-c|-m|FILE')
  1530          b'-c|-m|FILE')
  1386 def perfrevlogrevisions(ui, repo, file_=None, startrev=0, reverse=False,
  1531 def perfrevlogrevisions(ui, repo, file_=None, startrev=0, reverse=False,
  1387                         **opts):
  1532                         **opts):
  1388     """Benchmark reading a series of revisions from a revlog.
  1533     """Benchmark reading a series of revisions from a revlog.
  1389 
  1534 
  1390     By default, we read every ``-d/--dist`` revision from 0 to tip of
  1535     By default, we read every ``-d/--dist`` revision from 0 to tip of
  1391     the specified revlog.
  1536     the specified revlog.
  1392 
  1537 
  1393     The start revision can be defined via ``-s/--startrev``.
  1538     The start revision can be defined via ``-s/--startrev``.
  1394     """
  1539     """
  1395     rl = cmdutil.openrevlog(repo, 'perfrevlogrevisions', file_, opts)
  1540     opts = _byteskwargs(opts)
       
  1541 
       
  1542     rl = cmdutil.openrevlog(repo, b'perfrevlogrevisions', file_, opts)
  1396     rllen = getlen(ui)(rl)
  1543     rllen = getlen(ui)(rl)
       
  1544 
       
  1545     if startrev < 0:
       
  1546         startrev = rllen + startrev
  1397 
  1547 
  1398     def d():
  1548     def d():
  1399         rl.clearcaches()
  1549         rl.clearcaches()
  1400 
  1550 
  1401         beginrev = startrev
  1551         beginrev = startrev
  1402         endrev = rllen
  1552         endrev = rllen
  1403         dist = opts['dist']
  1553         dist = opts[b'dist']
  1404 
  1554 
  1405         if reverse:
  1555         if reverse:
  1406             beginrev, endrev = endrev, beginrev
  1556             beginrev, endrev = endrev, beginrev
  1407             dist = -1 * dist
  1557             dist = -1 * dist
  1408 
  1558 
  1409         for x in xrange(beginrev, endrev, dist):
  1559         for x in _xrange(beginrev, endrev, dist):
  1410             # Old revisions don't support passing int.
  1560             # Old revisions don't support passing int.
  1411             n = rl.node(x)
  1561             n = rl.node(x)
  1412             rl.revision(n)
  1562             rl.revision(n)
  1413 
  1563 
  1414     timer, fm = gettimer(ui, opts)
  1564     timer, fm = gettimer(ui, opts)
  1415     timer(d)
  1565     timer(d)
  1416     fm.end()
  1566     fm.end()
  1417 
  1567 
  1418 @command('perfrevlogchunks', revlogopts + formatteropts +
  1568 @command(b'perfrevlogchunks', revlogopts + formatteropts +
  1419          [('e', 'engines', '', 'compression engines to use'),
  1569          [(b'e', b'engines', b'', b'compression engines to use'),
  1420           ('s', 'startrev', 0, 'revision to start at')],
  1570           (b's', b'startrev', 0, b'revision to start at')],
  1421          '-c|-m|FILE')
  1571          b'-c|-m|FILE')
  1422 def perfrevlogchunks(ui, repo, file_=None, engines=None, startrev=0, **opts):
  1572 def perfrevlogchunks(ui, repo, file_=None, engines=None, startrev=0, **opts):
  1423     """Benchmark operations on revlog chunks.
  1573     """Benchmark operations on revlog chunks.
  1424 
  1574 
  1425     Logically, each revlog is a collection of fulltext revisions. However,
  1575     Logically, each revlog is a collection of fulltext revisions. However,
  1426     stored within each revlog are "chunks" of possibly compressed data. This
  1576     stored within each revlog are "chunks" of possibly compressed data. This
  1429     This command measures the time it takes to read+decompress and recompress
  1579     This command measures the time it takes to read+decompress and recompress
  1430     chunks in a revlog. It effectively isolates I/O and compression performance.
  1580     chunks in a revlog. It effectively isolates I/O and compression performance.
  1431     For measurements of higher-level operations like resolving revisions,
  1581     For measurements of higher-level operations like resolving revisions,
  1432     see ``perfrevlogrevisions`` and ``perfrevlogrevision``.
  1582     see ``perfrevlogrevisions`` and ``perfrevlogrevision``.
  1433     """
  1583     """
  1434     rl = cmdutil.openrevlog(repo, 'perfrevlogchunks', file_, opts)
  1584     opts = _byteskwargs(opts)
       
  1585 
       
  1586     rl = cmdutil.openrevlog(repo, b'perfrevlogchunks', file_, opts)
  1435 
  1587 
  1436     # _chunkraw was renamed to _getsegmentforrevs.
  1588     # _chunkraw was renamed to _getsegmentforrevs.
  1437     try:
  1589     try:
  1438         segmentforrevs = rl._getsegmentforrevs
  1590         segmentforrevs = rl._getsegmentforrevs
  1439     except AttributeError:
  1591     except AttributeError:
  1440         segmentforrevs = rl._chunkraw
  1592         segmentforrevs = rl._chunkraw
  1441 
  1593 
  1442     # Verify engines argument.
  1594     # Verify engines argument.
  1443     if engines:
  1595     if engines:
  1444         engines = set(e.strip() for e in engines.split(','))
  1596         engines = set(e.strip() for e in engines.split(b','))
  1445         for engine in engines:
  1597         for engine in engines:
  1446             try:
  1598             try:
  1447                 util.compressionengines[engine]
  1599                 util.compressionengines[engine]
  1448             except KeyError:
  1600             except KeyError:
  1449                 raise error.Abort('unknown compression engine: %s' % engine)
  1601                 raise error.Abort(b'unknown compression engine: %s' % engine)
  1450     else:
  1602     else:
  1451         engines = []
  1603         engines = []
  1452         for e in util.compengines:
  1604         for e in util.compengines:
  1453             engine = util.compengines[e]
  1605             engine = util.compengines[e]
  1454             try:
  1606             try:
  1455                 if engine.available():
  1607                 if engine.available():
  1456                     engine.revlogcompressor().compress('dummy')
  1608                     engine.revlogcompressor().compress(b'dummy')
  1457                     engines.append(e)
  1609                     engines.append(e)
  1458             except NotImplementedError:
  1610             except NotImplementedError:
  1459                 pass
  1611                 pass
  1460 
  1612 
  1461     revs = list(rl.revs(startrev, len(rl) - 1))
  1613     revs = list(rl.revs(startrev, len(rl) - 1))
  1511                 rl.compress(chunk)
  1663                 rl.compress(chunk)
  1512         finally:
  1664         finally:
  1513             rl._compressor = oldcompressor
  1665             rl._compressor = oldcompressor
  1514 
  1666 
  1515     benches = [
  1667     benches = [
  1516         (lambda: doread(), 'read'),
  1668         (lambda: doread(), b'read'),
  1517         (lambda: doreadcachedfh(), 'read w/ reused fd'),
  1669         (lambda: doreadcachedfh(), b'read w/ reused fd'),
  1518         (lambda: doreadbatch(), 'read batch'),
  1670         (lambda: doreadbatch(), b'read batch'),
  1519         (lambda: doreadbatchcachedfh(), 'read batch w/ reused fd'),
  1671         (lambda: doreadbatchcachedfh(), b'read batch w/ reused fd'),
  1520         (lambda: dochunk(), 'chunk'),
  1672         (lambda: dochunk(), b'chunk'),
  1521         (lambda: dochunkbatch(), 'chunk batch'),
  1673         (lambda: dochunkbatch(), b'chunk batch'),
  1522     ]
  1674     ]
  1523 
  1675 
  1524     for engine in sorted(engines):
  1676     for engine in sorted(engines):
  1525         compressor = util.compengines[engine].revlogcompressor()
  1677         compressor = util.compengines[engine].revlogcompressor()
  1526         benches.append((functools.partial(docompress, compressor),
  1678         benches.append((functools.partial(docompress, compressor),
  1527                         'compress w/ %s' % engine))
  1679                         b'compress w/ %s' % engine))
  1528 
  1680 
  1529     for fn, title in benches:
  1681     for fn, title in benches:
  1530         timer, fm = gettimer(ui, opts)
  1682         timer, fm = gettimer(ui, opts)
  1531         timer(fn, title=title)
  1683         timer(fn, title=title)
  1532         fm.end()
  1684         fm.end()
  1533 
  1685 
  1534 @command('perfrevlogrevision', revlogopts + formatteropts +
  1686 @command(b'perfrevlogrevision', revlogopts + formatteropts +
  1535          [('', 'cache', False, 'use caches instead of clearing')],
  1687          [(b'', b'cache', False, b'use caches instead of clearing')],
  1536          '-c|-m|FILE REV')
  1688          b'-c|-m|FILE REV')
  1537 def perfrevlogrevision(ui, repo, file_, rev=None, cache=None, **opts):
  1689 def perfrevlogrevision(ui, repo, file_, rev=None, cache=None, **opts):
  1538     """Benchmark obtaining a revlog revision.
  1690     """Benchmark obtaining a revlog revision.
  1539 
  1691 
  1540     Obtaining a revlog revision consists of roughly the following steps:
  1692     Obtaining a revlog revision consists of roughly the following steps:
  1541 
  1693 
  1545     4. Apply binary patches to obtain fulltext
  1697     4. Apply binary patches to obtain fulltext
  1546     5. Verify hash of fulltext
  1698     5. Verify hash of fulltext
  1547 
  1699 
  1548     This command measures the time spent in each of these phases.
  1700     This command measures the time spent in each of these phases.
  1549     """
  1701     """
  1550     if opts.get('changelog') or opts.get('manifest'):
  1702     opts = _byteskwargs(opts)
       
  1703 
       
  1704     if opts.get(b'changelog') or opts.get(b'manifest'):
  1551         file_, rev = None, file_
  1705         file_, rev = None, file_
  1552     elif rev is None:
  1706     elif rev is None:
  1553         raise error.CommandError('perfrevlogrevision', 'invalid arguments')
  1707         raise error.CommandError(b'perfrevlogrevision', b'invalid arguments')
  1554 
  1708 
  1555     r = cmdutil.openrevlog(repo, 'perfrevlogrevision', file_, opts)
  1709     r = cmdutil.openrevlog(repo, b'perfrevlogrevision', file_, opts)
  1556 
  1710 
  1557     # _chunkraw was renamed to _getsegmentforrevs.
  1711     # _chunkraw was renamed to _getsegmentforrevs.
  1558     try:
  1712     try:
  1559         segmentforrevs = r._getsegmentforrevs
  1713         segmentforrevs = r._getsegmentforrevs
  1560     except AttributeError:
  1714     except AttributeError:
  1620 
  1774 
  1621     chain = r._deltachain(rev)[0]
  1775     chain = r._deltachain(rev)[0]
  1622     data = segmentforrevs(chain[0], chain[-1])[1]
  1776     data = segmentforrevs(chain[0], chain[-1])[1]
  1623     rawchunks = getrawchunks(data, chain)
  1777     rawchunks = getrawchunks(data, chain)
  1624     bins = r._chunks(chain)
  1778     bins = r._chunks(chain)
  1625     text = str(bins[0])
  1779     text = bytes(bins[0])
  1626     bins = bins[1:]
  1780     bins = bins[1:]
  1627     text = mdiff.patches(text, bins)
  1781     text = mdiff.patches(text, bins)
  1628 
  1782 
  1629     benches = [
  1783     benches = [
  1630         (lambda: dorevision(), 'full'),
  1784         (lambda: dorevision(), b'full'),
  1631         (lambda: dodeltachain(rev), 'deltachain'),
  1785         (lambda: dodeltachain(rev), b'deltachain'),
  1632         (lambda: doread(chain), 'read'),
  1786         (lambda: doread(chain), b'read'),
  1633         (lambda: dorawchunks(data, chain), 'rawchunks'),
  1787         (lambda: dorawchunks(data, chain), b'rawchunks'),
  1634         (lambda: dodecompress(rawchunks), 'decompress'),
  1788         (lambda: dodecompress(rawchunks), b'decompress'),
  1635         (lambda: dopatch(text, bins), 'patch'),
  1789         (lambda: dopatch(text, bins), b'patch'),
  1636         (lambda: dohash(text), 'hash'),
  1790         (lambda: dohash(text), b'hash'),
  1637     ]
  1791     ]
  1638 
  1792 
  1639     for fn, title in benches:
  1793     for fn, title in benches:
  1640         timer, fm = gettimer(ui, opts)
  1794         timer, fm = gettimer(ui, opts)
  1641         timer(fn, title=title)
  1795         timer(fn, title=title)
  1642         fm.end()
  1796         fm.end()
  1643 
  1797 
  1644 @command('perfrevset',
  1798 @command(b'perfrevset',
  1645          [('C', 'clear', False, 'clear volatile cache between each call.'),
  1799          [(b'C', b'clear', False, b'clear volatile cache between each call.'),
  1646           ('', 'contexts', False, 'obtain changectx for each revision')]
  1800           (b'', b'contexts', False, b'obtain changectx for each revision')]
  1647          + formatteropts, "REVSET")
  1801          + formatteropts, b"REVSET")
  1648 def perfrevset(ui, repo, expr, clear=False, contexts=False, **opts):
  1802 def perfrevset(ui, repo, expr, clear=False, contexts=False, **opts):
  1649     """benchmark the execution time of a revset
  1803     """benchmark the execution time of a revset
  1650 
  1804 
  1651     Use the --clean option if need to evaluate the impact of build volatile
  1805     Use the --clean option if need to evaluate the impact of build volatile
  1652     revisions set cache on the revset execution. Volatile cache hold filtered
  1806     revisions set cache on the revset execution. Volatile cache hold filtered
  1653     and obsolete related cache."""
  1807     and obsolete related cache."""
       
  1808     opts = _byteskwargs(opts)
       
  1809 
  1654     timer, fm = gettimer(ui, opts)
  1810     timer, fm = gettimer(ui, opts)
  1655     def d():
  1811     def d():
  1656         if clear:
  1812         if clear:
  1657             repo.invalidatevolatilesets()
  1813             repo.invalidatevolatilesets()
  1658         if contexts:
  1814         if contexts:
  1660         else:
  1816         else:
  1661             for r in repo.revs(expr): pass
  1817             for r in repo.revs(expr): pass
  1662     timer(d)
  1818     timer(d)
  1663     fm.end()
  1819     fm.end()
  1664 
  1820 
  1665 @command('perfvolatilesets',
  1821 @command(b'perfvolatilesets',
  1666          [('', 'clear-obsstore', False, 'drop obsstore between each call.'),
  1822          [(b'', b'clear-obsstore', False, b'drop obsstore between each call.'),
  1667          ] + formatteropts)
  1823           ] + formatteropts)
  1668 def perfvolatilesets(ui, repo, *names, **opts):
  1824 def perfvolatilesets(ui, repo, *names, **opts):
  1669     """benchmark the computation of various volatile set
  1825     """benchmark the computation of various volatile set
  1670 
  1826 
  1671     Volatile set computes element related to filtering and obsolescence."""
  1827     Volatile set computes element related to filtering and obsolescence."""
       
  1828     opts = _byteskwargs(opts)
  1672     timer, fm = gettimer(ui, opts)
  1829     timer, fm = gettimer(ui, opts)
  1673     repo = repo.unfiltered()
  1830     repo = repo.unfiltered()
  1674 
  1831 
  1675     def getobs(name):
  1832     def getobs(name):
  1676         def d():
  1833         def d():
  1677             repo.invalidatevolatilesets()
  1834             repo.invalidatevolatilesets()
  1678             if opts['clear_obsstore']:
  1835             if opts[b'clear_obsstore']:
  1679                 clearfilecache(repo, 'obsstore')
  1836                 clearfilecache(repo, b'obsstore')
  1680             obsolete.getrevs(repo, name)
  1837             obsolete.getrevs(repo, name)
  1681         return d
  1838         return d
  1682 
  1839 
  1683     allobs = sorted(obsolete.cachefuncs)
  1840     allobs = sorted(obsolete.cachefuncs)
  1684     if names:
  1841     if names:
  1688         timer(getobs(name), title=name)
  1845         timer(getobs(name), title=name)
  1689 
  1846 
  1690     def getfiltered(name):
  1847     def getfiltered(name):
  1691         def d():
  1848         def d():
  1692             repo.invalidatevolatilesets()
  1849             repo.invalidatevolatilesets()
  1693             if opts['clear_obsstore']:
  1850             if opts[b'clear_obsstore']:
  1694                 clearfilecache(repo, 'obsstore')
  1851                 clearfilecache(repo, b'obsstore')
  1695             repoview.filterrevs(repo, name)
  1852             repoview.filterrevs(repo, name)
  1696         return d
  1853         return d
  1697 
  1854 
  1698     allfilter = sorted(repoview.filtertable)
  1855     allfilter = sorted(repoview.filtertable)
  1699     if names:
  1856     if names:
  1701 
  1858 
  1702     for name in allfilter:
  1859     for name in allfilter:
  1703         timer(getfiltered(name), title=name)
  1860         timer(getfiltered(name), title=name)
  1704     fm.end()
  1861     fm.end()
  1705 
  1862 
  1706 @command('perfbranchmap',
  1863 @command(b'perfbranchmap',
  1707          [('f', 'full', False,
  1864          [(b'f', b'full', False,
  1708            'Includes build time of subset'),
  1865            b'Includes build time of subset'),
  1709           ('', 'clear-revbranch', False,
  1866           (b'', b'clear-revbranch', False,
  1710            'purge the revbranch cache between computation'),
  1867            b'purge the revbranch cache between computation'),
  1711          ] + formatteropts)
  1868           ] + formatteropts)
  1712 def perfbranchmap(ui, repo, *filternames, **opts):
  1869 def perfbranchmap(ui, repo, *filternames, **opts):
  1713     """benchmark the update of a branchmap
  1870     """benchmark the update of a branchmap
  1714 
  1871 
  1715     This benchmarks the full repo.branchmap() call with read and write disabled
  1872     This benchmarks the full repo.branchmap() call with read and write disabled
  1716     """
  1873     """
  1717     full = opts.get("full", False)
  1874     opts = _byteskwargs(opts)
  1718     clear_revbranch = opts.get("clear_revbranch", False)
  1875     full = opts.get(b"full", False)
       
  1876     clear_revbranch = opts.get(b"clear_revbranch", False)
  1719     timer, fm = gettimer(ui, opts)
  1877     timer, fm = gettimer(ui, opts)
  1720     def getbranchmap(filtername):
  1878     def getbranchmap(filtername):
  1721         """generate a benchmark function for the filtername"""
  1879         """generate a benchmark function for the filtername"""
  1722         if filtername is None:
  1880         if filtername is None:
  1723             view = repo
  1881             view = repo
  1742         for name in possiblefilters:
  1900         for name in possiblefilters:
  1743             subset = subsettable.get(name)
  1901             subset = subsettable.get(name)
  1744             if subset not in possiblefilters:
  1902             if subset not in possiblefilters:
  1745                 break
  1903                 break
  1746         else:
  1904         else:
  1747             assert False, 'subset cycle %s!' % possiblefilters
  1905             assert False, b'subset cycle %s!' % possiblefilters
  1748         allfilters.append(name)
  1906         allfilters.append(name)
  1749         possiblefilters.remove(name)
  1907         possiblefilters.remove(name)
  1750 
  1908 
  1751     # warm the cache
  1909     # warm the cache
  1752     if not full:
  1910     if not full:
  1753         for name in allfilters:
  1911         for name in allfilters:
  1754             repo.filtered(name).branchmap()
  1912             repo.filtered(name).branchmap()
  1755     if not filternames or 'unfiltered' in filternames:
  1913     if not filternames or b'unfiltered' in filternames:
  1756         # add unfiltered
  1914         # add unfiltered
  1757         allfilters.append(None)
  1915         allfilters.append(None)
  1758 
  1916 
  1759     branchcacheread = safeattrsetter(branchmap, 'read')
  1917     branchcacheread = safeattrsetter(branchmap, b'read')
  1760     branchcachewrite = safeattrsetter(branchmap.branchcache, 'write')
  1918     branchcachewrite = safeattrsetter(branchmap.branchcache, b'write')
  1761     branchcacheread.set(lambda repo: None)
  1919     branchcacheread.set(lambda repo: None)
  1762     branchcachewrite.set(lambda bc, repo: None)
  1920     branchcachewrite.set(lambda bc, repo: None)
  1763     try:
  1921     try:
  1764         for name in allfilters:
  1922         for name in allfilters:
  1765             printname = name
  1923             printname = name
  1766             if name is None:
  1924             if name is None:
  1767                 printname = 'unfiltered'
  1925                 printname = b'unfiltered'
  1768             timer(getbranchmap(name), title=str(printname))
  1926             timer(getbranchmap(name), title=str(printname))
  1769     finally:
  1927     finally:
  1770         branchcacheread.restore()
  1928         branchcacheread.restore()
  1771         branchcachewrite.restore()
  1929         branchcachewrite.restore()
  1772     fm.end()
  1930     fm.end()
  1773 
  1931 
  1774 @command('perfloadmarkers')
  1932 @command(b'perfbranchmapload', [
       
  1933      (b'f', b'filter', b'', b'Specify repoview filter'),
       
  1934      (b'', b'list', False, b'List brachmap filter caches'),
       
  1935     ] + formatteropts)
       
  1936 def perfbranchmapread(ui, repo, filter=b'', list=False, **opts):
       
  1937     """benchmark reading the branchmap"""
       
  1938     opts = _byteskwargs(opts)
       
  1939 
       
  1940     if list:
       
  1941         for name, kind, st in repo.cachevfs.readdir(stat=True):
       
  1942             if name.startswith(b'branch2'):
       
  1943                 filtername = name.partition(b'-')[2] or b'unfiltered'
       
  1944                 ui.status(b'%s - %s\n'
       
  1945                           % (filtername, util.bytecount(st.st_size)))
       
  1946         return
       
  1947     if filter:
       
  1948         repo = repoview.repoview(repo, filter)
       
  1949     else:
       
  1950         repo = repo.unfiltered()
       
  1951     # try once without timer, the filter may not be cached
       
  1952     if branchmap.read(repo) is None:
       
  1953         raise error.Abort(b'No brachmap cached for %s repo'
       
  1954                           % (filter or b'unfiltered'))
       
  1955     timer, fm = gettimer(ui, opts)
       
  1956     timer(lambda: branchmap.read(repo) and None)
       
  1957     fm.end()
       
  1958 
       
  1959 @command(b'perfloadmarkers')
  1775 def perfloadmarkers(ui, repo):
  1960 def perfloadmarkers(ui, repo):
  1776     """benchmark the time to parse the on-disk markers for a repo
  1961     """benchmark the time to parse the on-disk markers for a repo
  1777 
  1962 
  1778     Result is the number of markers in the repo."""
  1963     Result is the number of markers in the repo."""
  1779     timer, fm = gettimer(ui)
  1964     timer, fm = gettimer(ui)
  1780     svfs = getsvfs(repo)
  1965     svfs = getsvfs(repo)
  1781     timer(lambda: len(obsolete.obsstore(svfs)))
  1966     timer(lambda: len(obsolete.obsstore(svfs)))
  1782     fm.end()
  1967     fm.end()
  1783 
  1968 
  1784 @command('perflrucachedict', formatteropts +
  1969 @command(b'perflrucachedict', formatteropts +
  1785     [('', 'size', 4, 'size of cache'),
  1970     [(b'', b'costlimit', 0, b'maximum total cost of items in cache'),
  1786      ('', 'gets', 10000, 'number of key lookups'),
  1971      (b'', b'mincost', 0, b'smallest cost of items in cache'),
  1787      ('', 'sets', 10000, 'number of key sets'),
  1972      (b'', b'maxcost', 100, b'maximum cost of items in cache'),
  1788      ('', 'mixed', 10000, 'number of mixed mode operations'),
  1973      (b'', b'size', 4, b'size of cache'),
  1789      ('', 'mixedgetfreq', 50, 'frequency of get vs set ops in mixed mode')],
  1974      (b'', b'gets', 10000, b'number of key lookups'),
       
  1975      (b'', b'sets', 10000, b'number of key sets'),
       
  1976      (b'', b'mixed', 10000, b'number of mixed mode operations'),
       
  1977      (b'', b'mixedgetfreq', 50, b'frequency of get vs set ops in mixed mode')],
  1790     norepo=True)
  1978     norepo=True)
  1791 def perflrucache(ui, size=4, gets=10000, sets=10000, mixed=10000,
  1979 def perflrucache(ui, mincost=0, maxcost=100, costlimit=0, size=4,
  1792                  mixedgetfreq=50, **opts):
  1980                  gets=10000, sets=10000, mixed=10000, mixedgetfreq=50, **opts):
       
  1981     opts = _byteskwargs(opts)
       
  1982 
  1793     def doinit():
  1983     def doinit():
  1794         for i in xrange(10000):
  1984         for i in _xrange(10000):
  1795             util.lrucachedict(size)
  1985             util.lrucachedict(size)
  1796 
  1986 
       
  1987     costrange = list(range(mincost, maxcost + 1))
       
  1988 
  1797     values = []
  1989     values = []
  1798     for i in xrange(size):
  1990     for i in _xrange(size):
  1799         values.append(random.randint(0, sys.maxint))
  1991         values.append(random.randint(0, _maxint))
  1800 
  1992 
  1801     # Get mode fills the cache and tests raw lookup performance with no
  1993     # Get mode fills the cache and tests raw lookup performance with no
  1802     # eviction.
  1994     # eviction.
  1803     getseq = []
  1995     getseq = []
  1804     for i in xrange(gets):
  1996     for i in _xrange(gets):
  1805         getseq.append(random.choice(values))
  1997         getseq.append(random.choice(values))
  1806 
  1998 
  1807     def dogets():
  1999     def dogets():
  1808         d = util.lrucachedict(size)
  2000         d = util.lrucachedict(size)
  1809         for v in values:
  2001         for v in values:
  1810             d[v] = v
  2002             d[v] = v
  1811         for key in getseq:
  2003         for key in getseq:
  1812             value = d[key]
  2004             value = d[key]
  1813             value # silence pyflakes warning
  2005             value # silence pyflakes warning
  1814 
  2006 
       
  2007     def dogetscost():
       
  2008         d = util.lrucachedict(size, maxcost=costlimit)
       
  2009         for i, v in enumerate(values):
       
  2010             d.insert(v, v, cost=costs[i])
       
  2011         for key in getseq:
       
  2012             try:
       
  2013                 value = d[key]
       
  2014                 value # silence pyflakes warning
       
  2015             except KeyError:
       
  2016                 pass
       
  2017 
  1815     # Set mode tests insertion speed with cache eviction.
  2018     # Set mode tests insertion speed with cache eviction.
  1816     setseq = []
  2019     setseq = []
  1817     for i in xrange(sets):
  2020     costs = []
  1818         setseq.append(random.randint(0, sys.maxint))
  2021     for i in _xrange(sets):
       
  2022         setseq.append(random.randint(0, _maxint))
       
  2023         costs.append(random.choice(costrange))
       
  2024 
       
  2025     def doinserts():
       
  2026         d = util.lrucachedict(size)
       
  2027         for v in setseq:
       
  2028             d.insert(v, v)
       
  2029 
       
  2030     def doinsertscost():
       
  2031         d = util.lrucachedict(size, maxcost=costlimit)
       
  2032         for i, v in enumerate(setseq):
       
  2033             d.insert(v, v, cost=costs[i])
  1819 
  2034 
  1820     def dosets():
  2035     def dosets():
  1821         d = util.lrucachedict(size)
  2036         d = util.lrucachedict(size)
  1822         for v in setseq:
  2037         for v in setseq:
  1823             d[v] = v
  2038             d[v] = v
  1824 
  2039 
  1825     # Mixed mode randomly performs gets and sets with eviction.
  2040     # Mixed mode randomly performs gets and sets with eviction.
  1826     mixedops = []
  2041     mixedops = []
  1827     for i in xrange(mixed):
  2042     for i in _xrange(mixed):
  1828         r = random.randint(0, 100)
  2043         r = random.randint(0, 100)
  1829         if r < mixedgetfreq:
  2044         if r < mixedgetfreq:
  1830             op = 0
  2045             op = 0
  1831         else:
  2046         else:
  1832             op = 1
  2047             op = 1
  1833 
  2048 
  1834         mixedops.append((op, random.randint(0, size * 2)))
  2049         mixedops.append((op,
       
  2050                          random.randint(0, size * 2),
       
  2051                          random.choice(costrange)))
  1835 
  2052 
  1836     def domixed():
  2053     def domixed():
  1837         d = util.lrucachedict(size)
  2054         d = util.lrucachedict(size)
  1838 
  2055 
  1839         for op, v in mixedops:
  2056         for op, v, cost in mixedops:
  1840             if op == 0:
  2057             if op == 0:
  1841                 try:
  2058                 try:
  1842                     d[v]
  2059                     d[v]
  1843                 except KeyError:
  2060                 except KeyError:
  1844                     pass
  2061                     pass
  1845             else:
  2062             else:
  1846                 d[v] = v
  2063                 d[v] = v
  1847 
  2064 
       
  2065     def domixedcost():
       
  2066         d = util.lrucachedict(size, maxcost=costlimit)
       
  2067 
       
  2068         for op, v, cost in mixedops:
       
  2069             if op == 0:
       
  2070                 try:
       
  2071                     d[v]
       
  2072                 except KeyError:
       
  2073                     pass
       
  2074             else:
       
  2075                 d.insert(v, v, cost=cost)
       
  2076 
  1848     benches = [
  2077     benches = [
  1849         (doinit, 'init'),
  2078         (doinit, b'init'),
  1850         (dogets, 'gets'),
       
  1851         (dosets, 'sets'),
       
  1852         (domixed, 'mixed')
       
  1853     ]
  2079     ]
       
  2080 
       
  2081     if costlimit:
       
  2082         benches.extend([
       
  2083             (dogetscost, b'gets w/ cost limit'),
       
  2084             (doinsertscost, b'inserts w/ cost limit'),
       
  2085             (domixedcost, b'mixed w/ cost limit'),
       
  2086         ])
       
  2087     else:
       
  2088         benches.extend([
       
  2089             (dogets, b'gets'),
       
  2090             (doinserts, b'inserts'),
       
  2091             (dosets, b'sets'),
       
  2092             (domixed, b'mixed')
       
  2093         ])
  1854 
  2094 
  1855     for fn, title in benches:
  2095     for fn, title in benches:
  1856         timer, fm = gettimer(ui, opts)
  2096         timer, fm = gettimer(ui, opts)
  1857         timer(fn, title=title)
  2097         timer(fn, title=title)
  1858         fm.end()
  2098         fm.end()
  1859 
  2099 
  1860 @command('perfwrite', formatteropts)
  2100 @command(b'perfwrite', formatteropts)
  1861 def perfwrite(ui, repo, **opts):
  2101 def perfwrite(ui, repo, **opts):
  1862     """microbenchmark ui.write
  2102     """microbenchmark ui.write
  1863     """
  2103     """
       
  2104     opts = _byteskwargs(opts)
       
  2105 
  1864     timer, fm = gettimer(ui, opts)
  2106     timer, fm = gettimer(ui, opts)
  1865     def write():
  2107     def write():
  1866         for i in range(100000):
  2108         for i in range(100000):
  1867             ui.write(('Testing write performance\n'))
  2109             ui.write((b'Testing write performance\n'))
  1868     timer(write)
  2110     timer(write)
  1869     fm.end()
  2111     fm.end()
  1870 
  2112 
  1871 def uisetup(ui):
  2113 def uisetup(ui):
  1872     if (util.safehasattr(cmdutil, 'openrevlog') and
  2114     if (util.safehasattr(cmdutil, b'openrevlog') and
  1873         not util.safehasattr(commands, 'debugrevlogopts')):
  2115         not util.safehasattr(commands, b'debugrevlogopts')):
  1874         # for "historical portability":
  2116         # for "historical portability":
  1875         # In this case, Mercurial should be 1.9 (or a79fea6b3e77) -
  2117         # In this case, Mercurial should be 1.9 (or a79fea6b3e77) -
  1876         # 3.7 (or 5606f7d0d063). Therefore, '--dir' option for
  2118         # 3.7 (or 5606f7d0d063). Therefore, '--dir' option for
  1877         # openrevlog() should cause failure, because it has been
  2119         # openrevlog() should cause failure, because it has been
  1878         # available since 3.5 (or 49c583ca48c4).
  2120         # available since 3.5 (or 49c583ca48c4).
  1879         def openrevlog(orig, repo, cmd, file_, opts):
  2121         def openrevlog(orig, repo, cmd, file_, opts):
  1880             if opts.get('dir') and not util.safehasattr(repo, 'dirlog'):
  2122             if opts.get(b'dir') and not util.safehasattr(repo, b'dirlog'):
  1881                 raise error.Abort("This version doesn't support --dir option",
  2123                 raise error.Abort(b"This version doesn't support --dir option",
  1882                                   hint="use 3.5 or later")
  2124                                   hint=b"use 3.5 or later")
  1883             return orig(repo, cmd, file_, opts)
  2125             return orig(repo, cmd, file_, opts)
  1884         extensions.wrapfunction(cmdutil, 'openrevlog', openrevlog)
  2126         extensions.wrapfunction(cmdutil, b'openrevlog', openrevlog)