This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Title: timeit accuracy could be better
Type: enhancement Stage: needs patch
Components: Library (Lib) Versions: Python 3.6
Status: closed Resolution: third party
Dependencies: Superseder:
Assigned To: Nosy List: rbcollins, serhiy.storchaka, tim.peters, vstinner
Priority: normal Keywords:

Created on 2015-03-17 22:34 by rbcollins, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (5)
msg238353 - (view) Author: Robert Collins (rbcollins) * (Python committer) Date: 2015-03-17 22:34
In #6422 Haypo suggested making the timeit reports much better. This is a new ticket just for that. See and
msg238361 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2015-03-17 23:29
See also issue21988.
msg238364 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2015-03-17 23:53
Not only I'm too lazy to compute manually the number of loops and repeat, but also I don't trust myself. It's even worse when someone publishs results of a micro-benchmark. I don't trust how the benchmark was calibrated. In my experience, micro-benchmark are polluted by noise in timings, so results are not reliable. calibration is based on time, whereas timeit uses hardcoded constants (loops=1000000, repeat=3) which can be modified on the command line. has 3 main parameters:

- minimum duration of a single run (--min-time): 100 ms by default
- maximum total duration of the benchmark: does its best to respect this duration, but it can be longer: 1 second by default
- minimum repeat: 5 by default

The minimum duration is increased if the clock resolution is bad (1 ms or more). It's the case on Windows for time.clock() on Python 2 for example. Extract of

    min_time = max(self.config.min_time, timer_precision * 100)

The estimation of the number of loops is not reliable, but it's written to be "fast". Since I run a micro-benchmark many times, I don't want to wait too long. It's not a power of 10, but an arbitrary integer number. Usually, when running multiple times, the number of loops is different each time. It's not really a big issue, but it probably makes results more difficult to compare.

My constrain is max_time. The tested function may not have a linear duration (time = time_one_iteration * loops).

Repeat a test at least 5 times is a compromise between the stability of the result and the total duration of the benchmark.

Feel free to reuse my code to enhance
msg268067 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2016-06-09 23:07

I develop a new implementation of timeit which should be more reliable:

* Run 25 processes instead of just 1
* Compute average and standard deviation rather than the minimum
* Don't disable the garbage collector
* Skip the first timing to "warmup" the benchmark

Using the minimum and disable the garbage collector is a bad practice, it is not reliable:

* multiple processes are need to test different random hash functions, since Python hash function is now randomized by default in Python 3
* Linux also randomizes the address space by default (ASLR) and so the exact timing of memory accesses is different in each process

My following blog post "My journey to stable benchmark, part 3 (average)" explains in depth the multiple issues of using the minimum:

My perf module is very yound, it's still a work-in-progress. It should be better than timeit right now. It works on Python 2.7 and 3 (I tested 3.4).

We may pick the best ideas into the timeit module.

See also my article explaining how to tune Linux to reduce the "noise" of the operating system on microbenchmarks:
msg279959 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2016-11-03 01:59
I wrote a whole new project "perf" to fix root issues of this issue. It includes a timeit command. I suggest you to use "perf timeit" rather than "timeit" because perf is more reliable:
Date User Action Args
2022-04-11 14:58:14adminsetgithub: 67881
2016-11-03 01:59:53vstinnersetstatus: open -> closed
resolution: third party
messages: + msg279959
2016-06-10 23:54:52gvanrossumsetnosy: - gvanrossum
2016-06-10 17:06:43rhettingersetnosy: + gvanrossum, tim.peters
2016-06-09 23:07:33vstinnersetmessages: + msg268067
2015-03-17 23:53:27vstinnersetmessages: + msg238364
2015-03-17 23:29:50serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg238361
2015-03-17 22:34:37rbcollinscreate