[Python-checkins] peps: PEP 418: Add time.perf_counter(), time.process_time(), deprecate time.clock()
victor.stinner
python-checkins at python.org
Thu Apr 12 13:40:36 CEST 2012
http://hg.python.org/peps/rev/fb41f0b2e1bd
changeset: 4231:fb41f0b2e1bd
user: Victor Stinner <victor.stinner at gmail.com>
date: Thu Apr 12 13:38:06 2012 +0200
summary:
PEP 418: Add time.perf_counter(), time.process_time(), deprecate time.clock()
Reorder also sections.
files:
pep-0418.txt | 300 ++++++++++++++++++++++++--------------
1 files changed, 187 insertions(+), 113 deletions(-)
diff --git a/pep-0418.txt b/pep-0418.txt
--- a/pep-0418.txt
+++ b/pep-0418.txt
@@ -1,5 +1,5 @@
PEP: 418
-Title: Add a monotonic time functions
+Title: Add monotonic time, performance counter and process time functions
Version: $Revision$
Last-Modified: $Date$
Author: Jim Jewett <jimjjewett at gmail.com>, Victor Stinner <victor.stinner at gmail.com>
@@ -13,7 +13,8 @@
Abstract
========
-Add time.monotonic() and time.get_clock_info(name) functions to Python 3.3.
+Add time.get_clock_info(name), time.monotonic(), time.perf_counter() and
+time.process_time() functions to Python 3.3.
Rationale
@@ -25,62 +26,74 @@
automatically by NTP. A monotonic clock should be used instead to not be
affected by system clock updates.
-Clocks:
+To measure the performance of a function, time.clock() can be used but it
+is very different on Windows and on Unix. On Windows, time.clock() includes
+time elapsed during sleep, whereas it does not on Unix. time.clock() precision
+is very good on Windows, but very bad on Unix. A new time.perf_counter() should
+be used instead to always get the most precise performance counter with a
+portable behaviour.
- * time.time(): system clock
- * time.monotonic(): monotonic clock
+To measure CPU time, Python does not provide directly a portable function.
+time.clock() can be used on Unix, but it has a bad precision.
+resource.getrusage() can also be used on Unix, but it requires to get fields of
+a structure and compute the sum of time spend in kernel space and user space.
+A new time.process_time() function is portable counter, always measure CPU time
+(don't include time elapsed during sleep), and has the best available
+precision.
+Each operating system implements clocks and performance counters differently,
+and it is useful to know exactly which function is used and some properties of
+the clock like its resolution and its precision. A new time.get_clock_info()
+function gives access to all available information of each Python time
+function.
-Functions
-=========
+New functions:
-To fulfill the use cases, the functions' properties are:
+ * time.monotonic(): timeout and scheduling, not affected by system clock
+ updates
+ * time.perf_counter(): benchmarking, most precise clock for short period
+ * time.process_time(): profiling, CPU time of the process
-* time.time(): system clock, "wall clock".
-* time.monotonic(): monotonic clock
-* time.get_clock_info(name): get information on the specified time function
+time.clock() is deprecated by this PEP because it is not portable:
+time.perf_counter() or time.process_time() should be used instead, depending
+on your requirements.
-time.time()
------------
+Python functions
+================
-The system time is the "wall clock". It can be set manually by the
-system administrator or automatically by a NTP daemon. It can jump
-backward and forward. It is not monotonic.
+New functions
+-------------
-It is available on all platforms and cannot fail.
+time.get_clock_info(name)
+^^^^^^^^^^^^^^^^^^^^^^^^^
-Pseudo-code [#pseudo]_::
+Get information on the specified clock. Supported clocks:
- if os.name == "nt":
- def time():
- return _time.GetSystemTimeAsFileTime()
- else:
- def time():
- if hasattr(time, "clock_gettime"):
- try:
- # resolution = 1 nanosecond
- return time.clock_gettime(time.CLOCK_REALTIME)
- except OSError:
- # CLOCK_REALTIME is not supported (unlikely)
- pass
- if hasattr(_time, "gettimeofday"):
- try:
- # resolution = 1 microsecond
- return _time.gettimeofday()
- except OSError:
- # gettimeofday() should not fail
- pass
- if hasattr(_time, "ftime"):
- # resolution = 1 millisecond
- return _time.ftime()
- else:
- # resolution = 1 second
- return _time.time()
+ * "clock": time.clock()
+ * "monotonic": time.monotonic()
+ * "perf_counter": time.perf_counter()
+ * "process_time": time.process_time()
+ * "time": time.time()
+
+Return a dictionary with the following keys:
+
+ * Mandatory keys:
+
+ * "function" (str): name of the underlying operating system function.
+ Examples: "QueryPerformanceCounter()", "clock_gettime(CLOCK_REALTIME)".
+ * "resolution" (float): resolution in seconds of the clock
+ * "is_monotonic" (bool): True if the clock cannot go backward
+
+ * Optional keys:
+
+ * "precision" (float): precision in seconds of the clock
+ * "is_adjusted" (bool): True if the clock can be adjusted (e.g. by a NTP
+ daemon)
time.monotonic()
-----------------
+^^^^^^^^^^^^^^^^
Monotonic clock, cannot go backward. It is not affected by system clock
updates. The reference point of the returned value is undefined so only the
@@ -138,8 +151,117 @@
running for more than 49 days.
+time.perf_counter()
+^^^^^^^^^^^^^^^^^^^
+
+Performance counter used for benchmarking. It is monotonic, cannot go backward.
+It does include time elapsed during sleep. The reference point of the returned
+value is undefined so only the difference between consecutive calls is valid
+and is number of seconds.
+
+Pseudo-code::
+
+ def perf_counter():
+ if perf_counter.use_performance_counter:
+ if perf_counter.perf_frequency is None:
+ try:
+ perf_counter.perf_frequency = float(_time.QueryPerformanceFrequency())
+ except OSError:
+ # QueryPerformanceFrequency() fails if the installed
+ # hardware does not support a high-resolution performance
+ # counter
+ perf_counter.use_performance_counter = False
+ else:
+ return _time.QueryPerformanceCounter() / perf_counter.perf_frequency
+ else:
+ return _time.QueryPerformanceCounter() / perf_counter.perf_frequency
+ if perf_counter.use_monotonic:
+ # Monotonic clock is preferred over system clock
+ try:
+ return time.monotonic()
+ except OSError:
+ perf_counter.use_monotonic = False
+ return time.time()
+ perf_counter.use_performance_counter = (os.name == 'nt')
+ if perf_counter.use_performance_counter:
+ perf_counter.perf_frequency = None
+ perf_counter.use_monotonic = hasattr(time, 'monotonic')
+
+
+time.process_time()
+^^^^^^^^^^^^^^^^^^^
+
+Process time used for profiling: some of kernel and user-space CPU
+time. It does not include time elapsed during sleep. The reference point of
+the returned value is undefined so only the difference between consecutive
+calls is valid.
+
+Pseudo-code::
+
+ if os.name == 'nt':
+ def process_time():
+ handle = win32process.GetCurrentProcess()
+ process_times = win32process.GetProcessTimes(handle)
+ return (process_times['UserTime'] + process_times['KernelTime']) * 1e-7
+ elif (hasattr(time, 'clock_gettime')
+ and hasattr(time, 'CLOCK_PROCESS_CPUTIME_ID')):
+ def process_time():
+ return time.clock_gettime(time.CLOCK_PROCESS_CPUTIME_ID)
+ else:
+ try:
+ import resource
+ except ImportError:
+ def process_time():
+ return _time.clock()
+ else:
+ def process_time():
+ usage = resource.getrusage(resource.RUSAGE_SELF)
+ return usage[0] + usage[1]
+
+
+Existing functions
+------------------
+
+time.time()
+^^^^^^^^^^^
+
+The system time is the "wall clock". It can be set manually by the
+system administrator or automatically by a NTP daemon. It can jump
+backward and forward. It is not monotonic.
+
+It is available on all platforms and cannot fail.
+
+Pseudo-code [#pseudo]_::
+
+ if os.name == "nt":
+ def time():
+ return _time.GetSystemTimeAsFileTime()
+ else:
+ def time():
+ if hasattr(time, "clock_gettime"):
+ try:
+ # resolution = 1 nanosecond
+ return time.clock_gettime(time.CLOCK_REALTIME)
+ except OSError:
+ # CLOCK_REALTIME is not supported (unlikely)
+ pass
+ if hasattr(_time, "gettimeofday"):
+ try:
+ # resolution = 1 microsecond
+ return _time.gettimeofday()
+ except OSError:
+ # gettimeofday() should not fail
+ pass
+ if hasattr(_time, "ftime"):
+ # resolution = 1 millisecond
+ return _time.ftime()
+ else:
+ # resolution = 1 second
+ return _time.time()
+
+
time.sleep()
-------------
+^^^^^^^^^^^^
Suspend execution for the given number of seconds. The actual suspension time
may be less than that requested because any caught signal will terminate the
@@ -184,9 +306,11 @@
seconds = int(seconds)
_time.sleep(seconds)
+Deprecated functions
+--------------------
time.clock()
-------------
+^^^^^^^^^^^^
On Unix, return the current processor time as a floating point number expressed
in seconds. The precision, and in fact the very definition of the meaning of
@@ -222,30 +346,6 @@
clock = _time.clock
-time.get_clock_info(name)
--------------------------
-
-Get information on the specified clock. Supported clocks:
-
- * "clock": time.clock()
- * "monotonic": time.monotonic()
- * "time": time.time()
-
-Return a dictionary with the following keys:
-
- * Mandatory keys:
-
- * "function" (str): name of the underlying operating system function.
- Examples: "QueryPerformanceCounter()", "clock_gettime(CLOCK_REALTIME)".
- * "resolution" (float): resolution in seconds of the clock
- * "is_monotonic" (bool): True if the clock cannot go backward
-
- * Optional keys:
-
- * "precision" (float): precision in seconds of the clock
- * "is_adjusted" (bool): True if the clock can be adjusted (e.g. by a NTP
- daemon)
-
Glossary
========
@@ -890,6 +990,7 @@
========================= =============== =============
GetProcessTimes() 100 ns No
CLOCK_PROCESS_CPUTIME_ID 1 ns No
+getrusage() 1 µs No
clock() \- No
========================= =============== =============
@@ -899,9 +1000,10 @@
Name Operating system Precision
========================= ================ ===============
CLOCK_PROCESS_CPUTIME_ID Linux 3.2 1 ns
-clock() Linux 3.2 1 µs
clock() SunOS 5.11 1 µs
+getrusage() Linux 3.0 4 ms
clock() FreeBSD 8.2 7.8 ms
+clock() Linux 3.2 10 ms
clock() OpenBSD 5.0 10 ms
GetProcessTimes() Windows Seven 15.6 ms
========================= ================ ===============
@@ -937,6 +1039,10 @@
* The clock resolution can be read using clock_getres().
* GetProcessTimes(): call GetSystemTimeAdjustment().
+Python source code includes a portable library to get the process time (CPU
+time): `Tools/pybench/systimes.py
+<http://hg.python.org/cpython/file/tip/Tools/pybench/systimes.py>`_.
+
Thread time
-----------
@@ -1123,8 +1229,10 @@
Alternatives: API design
========================
-Other names for time.monotonic()
---------------------------------
+Other names for new functions
+-----------------------------
+
+time.monotonic():
* time.counter()
* time.seconds()
@@ -1136,6 +1244,12 @@
The name "time.try_monotonic()" was also proposed when time.monotonic() was
falling back to the system clock when no monotonic clock was available.
+time.perf_counter():
+
+ * time.hires()
+ * time.highres()
+ * time.timer()
+
Only expose operating system clocks
-----------------------------------
@@ -1234,52 +1348,6 @@
see the same clock value
-Deferred API: time.perf_counter()
-=================================
-
-Performance counter used for benchmarking and profiling. The reference point of
-the returned value is undefined so only the difference between consecutive calls is
-valid and is number of seconds.
-
-Pseudo-code::
-
- def perf_counter():
- if perf_counter.use_performance_counter:
- if perf_counter.perf_frequency is None:
- try:
- perf_counter.perf_frequency = float(_time.QueryPerformanceFrequency())
- except OSError:
- # QueryPerformanceFrequency() fails if the installed
- # hardware does not support a high-resolution performance
- # counter
- perf_counter.use_performance_counter = False
- else:
- return _time.QueryPerformanceCounter() / perf_counter.perf_frequency
- else:
- return _time.QueryPerformanceCounter() / perf_counter.perf_frequency
- if perf_counter.use_monotonic:
- # Monotonic clock is preferred over system clock
- try:
- return time.monotonic()
- except OSError:
- perf_counter.use_monotonic = False
- return time.time()
- perf_counter.use_performance_counter = (os.name == 'nt')
- if perf_counter.use_performance_counter:
- perf_counter.perf_frequency = None
- perf_counter.use_monotonic = hasattr(time, 'monotonic')
-
-Other names proposed for time.perf_counter():
-
- * time.hires()
- * time.highres()
- * time.timer()
-
-Python source code includes a portable library to get the process time (CPU
-time): `Tools/pybench/systimes.py
-<http://hg.python.org/cpython/file/tip/Tools/pybench/systimes.py>`_.
-
-
Footnotes
=========
--
Repository URL: http://hg.python.org/peps
More information about the Python-checkins
mailing list