Patchwork [1,of,2] perf: add a `pre-run` option

login
register
mail settings
Submitter Pierre-Yves David
Date May 22, 2019, 2:46 p.m.
Message ID <8553423d79608bd5d144.1558536370@nodosa.octopoid.net>
Download mbox | patch
Permalink /patch/40181/
State Accepted
Headers show

Comments

Pierre-Yves David - May 22, 2019, 2:46 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@octobus.net>
# Date 1558444086 -7200
#      Tue May 21 15:08:06 2019 +0200
# Node ID 8553423d79608bd5d144456448509bdf98c6df11
# Parent  86f17fc31aa8a0c26c11db6a532293463ee6428a
# EXP-Topic perf-profile
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 8553423d7960
perf: add a `pre-run` option

sometimes, the initial run is necessary to warm some cache that are not relevant
for the current measurement. We add a new `perf.pre-run` option to specify a
number of run of the benchmark logic that will happens before measurement are
taken.

Patch

diff --git a/contrib/perf.py b/contrib/perf.py
--- a/contrib/perf.py
+++ b/contrib/perf.py
@@ -15,6 +15,9 @@  Configurations
 ``presleep``
   number of second to wait before any group of runs (default: 1)
 
+``pre-run``
+  number of run to perform before starting measurement.
+
 ``run-limits``
   Control the number of runs each benchmark will perform. The option value
   should be a list of `<time>-<numberofrun>` pairs. After each run the
@@ -240,6 +243,9 @@  try:
     configitem(b'perf', b'all-timing',
         default=mercurial.configitems.dynamicdefault,
     )
+    configitem(b'perf', b'pre-run',
+        default=mercurial.configitems.dynamicdefault,
+    )
     configitem(b'perf', b'run-limits',
         default=mercurial.configitems.dynamicdefault,
     )
@@ -341,7 +347,9 @@  def gettimer(ui, opts=None):
     if not limits:
         limits = DEFAULTLIMITS
 
-    t = functools.partial(_timer, fm, displayall=displayall, limits=limits)
+    prerun = getint(ui, b"perf", b"pre-run", 0)
+    t = functools.partial(_timer, fm, displayall=displayall, limits=limits,
+                          prerun=prerun)
     return t, fm
 
 def stub_timer(fm, func, setup=None, title=None):
@@ -368,11 +376,15 @@  DEFAULTLIMITS = (
 )
 
 def _timer(fm, func, setup=None, title=None, displayall=False,
-           limits=DEFAULTLIMITS):
+           limits=DEFAULTLIMITS, prerun=0):
     gc.collect()
     results = []
     begin = util.timer()
     count = 0
+    for i in xrange(prerun):
+        if setup is not None:
+            setup()
+        func()
     keepgoing = True
     while keepgoing:
         if setup is not None:
diff --git a/tests/test-contrib-perf.t b/tests/test-contrib-perf.t
--- a/tests/test-contrib-perf.t
+++ b/tests/test-contrib-perf.t
@@ -55,6 +55,9 @@  perfstatus
   "presleep"
     number of second to wait before any group of runs (default: 1)
   
+  "pre-run"
+    number of run to perform before starting measurement.
+  
   "run-limits"
     Control the number of runs each benchmark will perform. The option value
     should be a list of '<time>-<numberofrun>' pairs. After each run the
@@ -327,6 +330,25 @@  detailed output:
    }
   ]
 
+Test pre-run feature
+--------------------
+
+(perf discovery has some spurious output)
+
+  $ hg perfdiscovery . --config perf.stub=no --config perf.run-limits='0.000000001-1' --config perf.pre-run=0
+  ! wall * comb * user * sys * (best of 1) (glob)
+  searching for changes
+  $ hg perfdiscovery . --config perf.stub=no --config perf.run-limits='0.000000001-1' --config perf.pre-run=1
+  ! wall * comb * user * sys * (best of 1) (glob)
+  searching for changes
+  searching for changes
+  $ hg perfdiscovery . --config perf.stub=no --config perf.run-limits='0.000000001-1' --config perf.pre-run=3
+  ! wall * comb * user * sys * (best of 1) (glob)
+  searching for changes
+  searching for changes
+  searching for changes
+  searching for changes
+
 Check perf.py for historical portability
 ----------------------------------------