diff options
Diffstat (limited to 'Lib/timeit.py')
| -rw-r--r--[-rwxr-xr-x] | Lib/timeit.py | 73 | 
1 files changed, 49 insertions, 24 deletions
| diff --git a/Lib/timeit.py b/Lib/timeit.py index 2de88f7271..2770efa35a 100755..100644 --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -207,6 +207,26 @@ class Timer:              r.append(t)          return r +    def autorange(self, callback=None): +        """Return the number of loops so that total time >= 0.2. + +        Calls the timeit method with *number* set to successive powers of +        ten (10, 100, 1000, ...) up to a maximum of one billion, until +        the time taken is at least 0.2 second, or the maximum is reached. +        Returns ``(number, time_taken)``. + +        If *callback* is given and is not None, it will be called after +        each trial with two arguments: ``callback(number, time_taken)``. +        """ +        for i in range(1, 10): +            number = 10**i +            time_taken = self.timeit(number) +            if callback: +                callback(number, time_taken) +            if time_taken >= 0.2: +                break +        return (number, time_taken) +  def timeit(stmt="pass", setup="pass", timer=default_timer,             number=default_number, globals=None):      """Convenience function to create Timer object and call timeit method.""" @@ -295,17 +315,16 @@ def main(args=None, *, _wrap_timer=None):      t = Timer(stmt, setup, timer)      if number == 0:          # determine number so that 0.2 <= total time < 2.0 -        for i in range(1, 10): -            number = 10**i -            try: -                x = t.timeit(number) -            except: -                t.print_exc() -                return 1 -            if verbose: -                print("%d loops -> %.*g secs" % (number, precision, x)) -            if x >= 0.2: -                break +        callback = None +        if verbose: +            def callback(number, time_taken): +                msg = "{num} loops -> {secs:.{prec}g} secs" +                print(msg.format(num=number, secs=time_taken, prec=precision)) +        try: +            number, _ = t.autorange(callback) +        except: +            t.print_exc() +            return 1      try:          r = t.repeat(repeat, number)      except: @@ -317,20 +336,26 @@ def main(args=None, *, _wrap_timer=None):      print("%d loops," % number, end=' ')      usec = best * 1e6 / number      if time_unit is not None: -        print("best of %d: %.*g %s per loop" % (repeat, precision, -                                             usec/units[time_unit], time_unit)) +        scale = units[time_unit]      else: -        if usec < 1000: -            print("best of %d: %.*g usec per loop" % (repeat, precision, usec)) -        else: -            msec = usec / 1000 -            if msec < 1000: -                print("best of %d: %.*g msec per loop" % (repeat, -                                                          precision, msec)) -            else: -                sec = msec / 1000 -                print("best of %d: %.*g sec per loop" % (repeat, -                                                         precision, sec)) +        scales = [(scale, unit) for unit, scale in units.items()] +        scales.sort(reverse=True) +        for scale, time_unit in scales: +            if usec >= scale: +                break +    print("best of %d: %.*g %s per loop" % (repeat, precision, +                                            usec/scale, time_unit)) +    best = min(r) +    usec = best * 1e6 / number +    worst = max(r) +    if worst >= best * 4: +        usec = worst * 1e6 / number +        import warnings +        warnings.warn_explicit( +            "The test results are likely unreliable. The worst\n" +            "time (%.*g %s) was more than four times slower than the best time." % +            (precision, usec/scale, time_unit), +             UserWarning, '', 0)      return None  if __name__ == "__main__": | 
