contrib/perf.py
changeset 45942 89a2afe31e82
parent 45632 7d0e54056586
child 46196 96b73671753a
equal deleted inserted replaced
45941:346af7687c6f 45942:89a2afe31e82
   289         b'all-timing',
   289         b'all-timing',
   290         default=mercurial.configitems.dynamicdefault,
   290         default=mercurial.configitems.dynamicdefault,
   291         experimental=True,
   291         experimental=True,
   292     )
   292     )
   293     configitem(
   293     configitem(
   294         b'perf', b'pre-run', default=mercurial.configitems.dynamicdefault,
   294         b'perf',
       
   295         b'pre-run',
       
   296         default=mercurial.configitems.dynamicdefault,
   295     )
   297     )
   296     configitem(
   298     configitem(
   297         b'perf',
   299         b'perf',
   298         b'profile-benchmark',
   300         b'profile-benchmark',
   299         default=mercurial.configitems.dynamicdefault,
   301         default=mercurial.configitems.dynamicdefault,
   308     pass
   310     pass
   309 except TypeError:
   311 except TypeError:
   310     # compatibility fix for a11fd395e83f
   312     # compatibility fix for a11fd395e83f
   311     # hg version: 5.2
   313     # hg version: 5.2
   312     configitem(
   314     configitem(
   313         b'perf', b'presleep', default=mercurial.configitems.dynamicdefault,
   315         b'perf',
       
   316         b'presleep',
       
   317         default=mercurial.configitems.dynamicdefault,
   314     )
   318     )
   315     configitem(
   319     configitem(
   316         b'perf', b'stub', default=mercurial.configitems.dynamicdefault,
   320         b'perf',
       
   321         b'stub',
       
   322         default=mercurial.configitems.dynamicdefault,
   317     )
   323     )
   318     configitem(
   324     configitem(
   319         b'perf', b'parentscount', default=mercurial.configitems.dynamicdefault,
   325         b'perf',
       
   326         b'parentscount',
       
   327         default=mercurial.configitems.dynamicdefault,
   320     )
   328     )
   321     configitem(
   329     configitem(
   322         b'perf', b'all-timing', default=mercurial.configitems.dynamicdefault,
   330         b'perf',
       
   331         b'all-timing',
       
   332         default=mercurial.configitems.dynamicdefault,
   323     )
   333     )
   324     configitem(
   334     configitem(
   325         b'perf', b'pre-run', default=mercurial.configitems.dynamicdefault,
   335         b'perf',
       
   336         b'pre-run',
       
   337         default=mercurial.configitems.dynamicdefault,
   326     )
   338     )
   327     configitem(
   339     configitem(
   328         b'perf',
   340         b'perf',
   329         b'profile-benchmark',
   341         b'profile-benchmark',
   330         default=mercurial.configitems.dynamicdefault,
   342         default=mercurial.configitems.dynamicdefault,
   331     )
   343     )
   332     configitem(
   344     configitem(
   333         b'perf', b'run-limits', default=mercurial.configitems.dynamicdefault,
   345         b'perf',
       
   346         b'run-limits',
       
   347         default=mercurial.configitems.dynamicdefault,
   334     )
   348     )
   335 
   349 
   336 
   350 
   337 def getlen(ui):
   351 def getlen(ui):
   338     if ui.configbool(b"perf", b"stub", False):
   352     if ui.configbool(b"perf", b"stub", False):
   383         # define formatter locally, because ui.formatter has been
   397         # define formatter locally, because ui.formatter has been
   384         # available since 2.2 (or ae5f92e154d3)
   398         # available since 2.2 (or ae5f92e154d3)
   385         from mercurial import node
   399         from mercurial import node
   386 
   400 
   387         class defaultformatter(object):
   401         class defaultformatter(object):
   388             """Minimized composition of baseformatter and plainformatter
   402             """Minimized composition of baseformatter and plainformatter"""
   389             """
       
   390 
   403 
   391             def __init__(self, ui, topic, opts):
   404             def __init__(self, ui, topic, opts):
   392                 self._ui = ui
   405                 self._ui = ui
   393                 if ui.debugflag:
   406                 if ui.debugflag:
   394                     self.hexfunc = node.hex
   407                     self.hexfunc = node.hex
   656         hint=b"use 2.5 or later",
   669         hint=b"use 2.5 or later",
   657     )
   670     )
   658 
   671 
   659 
   672 
   660 def getsvfs(repo):
   673 def getsvfs(repo):
   661     """Return appropriate object to access files under .hg/store
   674     """Return appropriate object to access files under .hg/store"""
   662     """
       
   663     # for "historical portability":
   675     # for "historical portability":
   664     # repo.svfs has been available since 2.3 (or 7034365089bf)
   676     # repo.svfs has been available since 2.3 (or 7034365089bf)
   665     svfs = getattr(repo, 'svfs', None)
   677     svfs = getattr(repo, 'svfs', None)
   666     if svfs:
   678     if svfs:
   667         return svfs
   679         return svfs
   668     else:
   680     else:
   669         return getattr(repo, 'sopener')
   681         return getattr(repo, 'sopener')
   670 
   682 
   671 
   683 
   672 def getvfs(repo):
   684 def getvfs(repo):
   673     """Return appropriate object to access files under .hg
   685     """Return appropriate object to access files under .hg"""
   674     """
       
   675     # for "historical portability":
   686     # for "historical portability":
   676     # repo.vfs has been available since 2.3 (or 7034365089bf)
   687     # repo.vfs has been available since 2.3 (or 7034365089bf)
   677     vfs = getattr(repo, 'vfs', None)
   688     vfs = getattr(repo, 'vfs', None)
   678     if vfs:
   689     if vfs:
   679         return vfs
   690         return vfs
   680     else:
   691     else:
   681         return getattr(repo, 'opener')
   692         return getattr(repo, 'opener')
   682 
   693 
   683 
   694 
   684 def repocleartagscachefunc(repo):
   695 def repocleartagscachefunc(repo):
   685     """Return the function to clear tags cache according to repo internal API
   696     """Return the function to clear tags cache according to repo internal API"""
   686     """
       
   687     if util.safehasattr(repo, b'_tagscache'):  # since 2.0 (or 9dca7653b525)
   697     if util.safehasattr(repo, b'_tagscache'):  # since 2.0 (or 9dca7653b525)
   688         # in this case, setattr(repo, '_tagscache', None) or so isn't
   698         # in this case, setattr(repo, '_tagscache', None) or so isn't
   689         # correct way to clear tags cache, because existing code paths
   699         # correct way to clear tags cache, because existing code paths
   690         # expect _tagscache to be a structured object.
   700         # expect _tagscache to be a structured object.
   691         def clearcache():
   701         def clearcache():
   845 
   855 
   846 
   856 
   847 @command(
   857 @command(
   848     b'perftags',
   858     b'perftags',
   849     formatteropts
   859     formatteropts
   850     + [(b'', b'clear-revlogs', False, b'refresh changelog and manifest'),],
   860     + [
       
   861         (b'', b'clear-revlogs', False, b'refresh changelog and manifest'),
       
   862     ],
   851 )
   863 )
   852 def perftags(ui, repo, **opts):
   864 def perftags(ui, repo, **opts):
   853     opts = _byteskwargs(opts)
   865     opts = _byteskwargs(opts)
   854     timer, fm = gettimer(ui, opts)
   866     timer, fm = gettimer(ui, opts)
   855     repocleartagscache = repocleartagscachefunc(repo)
   867     repocleartagscache = repocleartagscachefunc(repo)
   898     fm.end()
   910     fm.end()
   899 
   911 
   900 
   912 
   901 @command(b'perfdiscovery', formatteropts, b'PATH')
   913 @command(b'perfdiscovery', formatteropts, b'PATH')
   902 def perfdiscovery(ui, repo, path, **opts):
   914 def perfdiscovery(ui, repo, path, **opts):
   903     """benchmark discovery between local repo and the peer at given path
   915     """benchmark discovery between local repo and the peer at given path"""
   904     """
       
   905     repos = [repo, None]
   916     repos = [repo, None]
   906     timer, fm = gettimer(ui, opts)
   917     timer, fm = gettimer(ui, opts)
   907     path = ui.expandpath(path)
   918     path = ui.expandpath(path)
   908 
   919 
   909     def s():
   920     def s():
   917 
   928 
   918 
   929 
   919 @command(
   930 @command(
   920     b'perfbookmarks',
   931     b'perfbookmarks',
   921     formatteropts
   932     formatteropts
   922     + [(b'', b'clear-revlogs', False, b'refresh changelog and manifest'),],
   933     + [
       
   934         (b'', b'clear-revlogs', False, b'refresh changelog and manifest'),
       
   935     ],
   923 )
   936 )
   924 def perfbookmarks(ui, repo, **opts):
   937 def perfbookmarks(ui, repo, **opts):
   925     """benchmark parsing bookmarks from disk to memory"""
   938     """benchmark parsing bookmarks from disk to memory"""
   926     opts = _byteskwargs(opts)
   939     opts = _byteskwargs(opts)
   927     timer, fm = gettimer(ui, opts)
   940     timer, fm = gettimer(ui, opts)
  1182     fm.end()
  1195     fm.end()
  1183 
  1196 
  1184 
  1197 
  1185 @command(b'perfdirstatedirs', formatteropts)
  1198 @command(b'perfdirstatedirs', formatteropts)
  1186 def perfdirstatedirs(ui, repo, **opts):
  1199 def perfdirstatedirs(ui, repo, **opts):
  1187     """benchmap a 'dirstate.hasdir' call from an empty `dirs` cache
  1200     """benchmap a 'dirstate.hasdir' call from an empty `dirs` cache"""
  1188     """
       
  1189     opts = _byteskwargs(opts)
  1201     opts = _byteskwargs(opts)
  1190     timer, fm = gettimer(ui, opts)
  1202     timer, fm = gettimer(ui, opts)
  1191     repo.dirstate.hasdir(b"a")
  1203     repo.dirstate.hasdir(b"a")
  1192 
  1204 
  1193     def setup():
  1205     def setup():
  1243     fm.end()
  1255     fm.end()
  1244 
  1256 
  1245 
  1257 
  1246 @command(b'perfdirstatewrite', formatteropts)
  1258 @command(b'perfdirstatewrite', formatteropts)
  1247 def perfdirstatewrite(ui, repo, **opts):
  1259 def perfdirstatewrite(ui, repo, **opts):
  1248     """benchmap the time it take to write a dirstate on disk
  1260     """benchmap the time it take to write a dirstate on disk"""
  1249     """
       
  1250     opts = _byteskwargs(opts)
  1261     opts = _byteskwargs(opts)
  1251     timer, fm = gettimer(ui, opts)
  1262     timer, fm = gettimer(ui, opts)
  1252     ds = repo.dirstate
  1263     ds = repo.dirstate
  1253     b"a" in ds
  1264     b"a" in ds
  1254 
  1265 
  1357     fm.end()
  1368     fm.end()
  1358 
  1369 
  1359 
  1370 
  1360 @command(
  1371 @command(
  1361     b'perfphases',
  1372     b'perfphases',
  1362     [(b'', b'full', False, b'include file reading time too'),],
  1373     [
       
  1374         (b'', b'full', False, b'include file reading time too'),
       
  1375     ],
  1363     b"",
  1376     b"",
  1364 )
  1377 )
  1365 def perfphases(ui, repo, **opts):
  1378 def perfphases(ui, repo, **opts):
  1366     """benchmark phasesets computation"""
  1379     """benchmark phasesets computation"""
  1367     opts = _byteskwargs(opts)
  1380     opts = _byteskwargs(opts)
  1837     fm.end()
  1850     fm.end()
  1838 
  1851 
  1839 
  1852 
  1840 @command(
  1853 @command(
  1841     b'perftemplating',
  1854     b'perftemplating',
  1842     [(b'r', b'rev', [], b'revisions to run the template on'),] + formatteropts,
  1855     [
       
  1856         (b'r', b'rev', [], b'revisions to run the template on'),
       
  1857     ]
       
  1858     + formatteropts,
  1843 )
  1859 )
  1844 def perftemplating(ui, repo, testedtemplate=None, **opts):
  1860 def perftemplating(ui, repo, testedtemplate=None, **opts):
  1845     """test the rendering time of a given template"""
  1861     """test the rendering time of a given template"""
  1846     if makelogtemplater is None:
  1862     if makelogtemplater is None:
  1847         raise error.Abort(
  1863         raise error.Abort(
  2191                     b'nbrevs': len(repo.revs('only(%d, %d)', p, b)),
  2207                     b'nbrevs': len(repo.revs('only(%d, %d)', p, b)),
  2192                     b'nbmissingfiles': len(missing),
  2208                     b'nbmissingfiles': len(missing),
  2193                 }
  2209                 }
  2194                 if dostats:
  2210                 if dostats:
  2195                     alldata['nbrevs'].append(
  2211                     alldata['nbrevs'].append(
  2196                         (data['nbrevs'], base.hex(), parent.hex(),)
  2212                         (
       
  2213                             data['nbrevs'],
       
  2214                             base.hex(),
       
  2215                             parent.hex(),
       
  2216                         )
  2197                     )
  2217                     )
  2198                     alldata['nbmissingfiles'].append(
  2218                     alldata['nbmissingfiles'].append(
  2199                         (data['nbmissingfiles'], base.hex(), parent.hex(),)
  2219                         (
       
  2220                             data['nbmissingfiles'],
       
  2221                             base.hex(),
       
  2222                             parent.hex(),
       
  2223                         )
  2200                     )
  2224                     )
  2201                 if dotiming:
  2225                 if dotiming:
  2202                     begin = util.timer()
  2226                     begin = util.timer()
  2203                     renames = copies.pathcopies(base, parent)
  2227                     renames = copies.pathcopies(base, parent)
  2204                     end = util.timer()
  2228                     end = util.timer()
  2205                     # not very stable timing since we did only one run
  2229                     # not very stable timing since we did only one run
  2206                     data['time'] = end - begin
  2230                     data['time'] = end - begin
  2207                     data['nbrenamedfiles'] = len(renames)
  2231                     data['nbrenamedfiles'] = len(renames)
  2208                     if dostats:
  2232                     if dostats:
  2209                         alldata['time'].append(
  2233                         alldata['time'].append(
  2210                             (data['time'], base.hex(), parent.hex(),)
  2234                             (
       
  2235                                 data['time'],
       
  2236                                 base.hex(),
       
  2237                                 parent.hex(),
       
  2238                             )
  2211                         )
  2239                         )
  2212                         alldata['nbrenames'].append(
  2240                         alldata['nbrenames'].append(
  2213                             (data['nbrenamedfiles'], base.hex(), parent.hex(),)
  2241                             (
       
  2242                                 data['nbrenamedfiles'],
       
  2243                                 base.hex(),
       
  2244                                 parent.hex(),
       
  2245                             )
  2214                         )
  2246                         )
  2215                 fm.startitem()
  2247                 fm.startitem()
  2216                 fm.data(**data)
  2248                 fm.data(**data)
  2217                 out = data.copy()
  2249                 out = data.copy()
  2218                 out['source'] = fm.hexfunc(base.node())
  2250                 out['source'] = fm.hexfunc(base.node())
  3319     fm.end()
  3351     fm.end()
  3320 
  3352 
  3321 
  3353 
  3322 @command(
  3354 @command(
  3323     b'perfvolatilesets',
  3355     b'perfvolatilesets',
  3324     [(b'', b'clear-obsstore', False, b'drop obsstore between each call.'),]
  3356     [
       
  3357         (b'', b'clear-obsstore', False, b'drop obsstore between each call.'),
       
  3358     ]
  3325     + formatteropts,
  3359     + formatteropts,
  3326 )
  3360 )
  3327 def perfvolatilesets(ui, repo, *names, **opts):
  3361 def perfvolatilesets(ui, repo, *names, **opts):
  3328     """benchmark the computation of various volatile set
  3362     """benchmark the computation of various volatile set
  3329 
  3363 
  3805         (b'', b'batch-line', None, b'pass whole line to write method at once'),
  3839         (b'', b'batch-line', None, b'pass whole line to write method at once'),
  3806         (b'', b'flush-line', None, b'flush after each line'),
  3840         (b'', b'flush-line', None, b'flush after each line'),
  3807     ],
  3841     ],
  3808 )
  3842 )
  3809 def perfwrite(ui, repo, **opts):
  3843 def perfwrite(ui, repo, **opts):
  3810     """microbenchmark ui.write (and others)
  3844     """microbenchmark ui.write (and others)"""
  3811     """
       
  3812     opts = _byteskwargs(opts)
  3845     opts = _byteskwargs(opts)
  3813 
  3846 
  3814     write = getattr(ui, _sysstr(opts[b'write_method']))
  3847     write = getattr(ui, _sysstr(opts[b'write_method']))
  3815     nlines = int(opts[b'nlines'])
  3848     nlines = int(opts[b'nlines'])
  3816     nitems = int(opts[b'nitems'])
  3849     nitems = int(opts[b'nitems'])