Kaydet (Commit) fe98e2fc authored tarafından Victor Stinner's avatar Victor Stinner

Issue #14428: Use the new time.perf_counter() and time.process_time() functions

 * Replace "time.clock on windows, or time.time" with time.perf_counter()
 * profile module: only use time.process_time() instead of trying different
   functions providing the process time
 * timeit module: use time.perf_counter() by default, time.time() and
   time.clock() can still be used using --time and --clock options
 * pybench program: use time.perf_counter() by default, add support for
   the new time.process_time() and time.perf_counter() functions, but stay
   backward compatible. Use also time.get_clock_info() to display information
   of the timer.
üst 47620a66
...@@ -6,16 +6,12 @@ ...@@ -6,16 +6,12 @@
# #
import time import time
import sys
import multiprocessing import multiprocessing
import threading import threading
import queue import queue
import gc import gc
if sys.platform == 'win32': _timer = time.perf_counter
_timer = time.clock
else:
_timer = time.time
delta = 1 delta = 1
......
...@@ -149,9 +149,9 @@ class ColorDelegator(Delegator): ...@@ -149,9 +149,9 @@ class ColorDelegator(Delegator):
self.stop_colorizing = False self.stop_colorizing = False
self.colorizing = True self.colorizing = True
if DEBUG: print("colorizing...") if DEBUG: print("colorizing...")
t0 = time.clock() t0 = time.perf_counter()
self.recolorize_main() self.recolorize_main()
t1 = time.clock() t1 = time.perf_counter()
if DEBUG: print("%.3f seconds" % (t1-t0)) if DEBUG: print("%.3f seconds" % (t1-t0))
finally: finally:
self.colorizing = False self.colorizing = False
......
...@@ -83,26 +83,6 @@ def runctx(statement, globals, locals, filename=None, sort=-1): ...@@ -83,26 +83,6 @@ def runctx(statement, globals, locals, filename=None, sort=-1):
else: else:
return prof.print_stats(sort) return prof.print_stats(sort)
if hasattr(os, "times"):
def _get_time_times(timer=os.times):
t = timer()
return t[0] + t[1]
# Using getrusage(3) is better than clock(3) if available:
# on some systems (e.g. FreeBSD), getrusage has a higher resolution
# Furthermore, on a POSIX system, returns microseconds, which
# wrap around after 36min.
_has_res = 0
try:
import resource
resgetrusage = lambda: resource.getrusage(resource.RUSAGE_SELF)
def _get_time_resource(timer=resgetrusage):
t = timer()
return t[0] + t[1]
_has_res = 1
except ImportError:
pass
class Profile: class Profile:
"""Profiler class. """Profiler class.
...@@ -155,20 +135,8 @@ class Profile: ...@@ -155,20 +135,8 @@ class Profile:
self.bias = bias # Materialize in local dict for lookup speed. self.bias = bias # Materialize in local dict for lookup speed.
if not timer: if not timer:
if _has_res: self.timer = self.get_time = time.process_time
self.timer = resgetrusage self.dispatcher = self.trace_dispatch_i
self.dispatcher = self.trace_dispatch
self.get_time = _get_time_resource
elif hasattr(time, 'clock'):
self.timer = self.get_time = time.clock
self.dispatcher = self.trace_dispatch_i
elif hasattr(os, 'times'):
self.timer = os.times
self.dispatcher = self.trace_dispatch
self.get_time = _get_time_times
else:
self.timer = self.get_time = time.time
self.dispatcher = self.trace_dispatch_i
else: else:
self.timer = timer self.timer = timer
t = self.timer() # test out timer function t = self.timer() # test out timer function
......
...@@ -9,13 +9,13 @@ def main(): ...@@ -9,13 +9,13 @@ def main():
timefunc(10, p.findall, s) timefunc(10, p.findall, s)
def timefunc(n, func, *args, **kw): def timefunc(n, func, *args, **kw):
t0 = time.clock() t0 = time.perf_counter()
try: try:
for i in range(n): for i in range(n):
result = func(*args, **kw) result = func(*args, **kw)
return result return result
finally: finally:
t1 = time.clock() t1 = time.perf_counter()
if n > 1: if n > 1:
print(n, "times", end=' ') print(n, "times", end=' ')
print(func.__name__, "%.3f" % (t1-t0), "CPU seconds") print(func.__name__, "%.3f" % (t1-t0), "CPU seconds")
......
...@@ -57,9 +57,9 @@ def flush(): ...@@ -57,9 +57,9 @@ def flush():
sys.stdout.flush() sys.stdout.flush()
def doit(L): def doit(L):
t0 = time.clock() t0 = time.perf_counter()
L.sort() L.sort()
t1 = time.clock() t1 = time.perf_counter()
print("%6.2f" % (t1-t0), end=' ') print("%6.2f" % (t1-t0), end=' ')
flush() flush()
......
...@@ -15,8 +15,8 @@ Options: ...@@ -15,8 +15,8 @@ Options:
-n/--number N: how many times to execute 'statement' (default: see below) -n/--number N: how many times to execute 'statement' (default: see below)
-r/--repeat N: how many times to repeat the timer (default 3) -r/--repeat N: how many times to repeat the timer (default 3)
-s/--setup S: statement to be executed once initially (default 'pass') -s/--setup S: statement to be executed once initially (default 'pass')
-t/--time: use time.time() (default on Unix) -t/--time: use time.time()
-c/--clock: use time.clock() (default on Windows) -c/--clock: use time.clock()
-v/--verbose: print raw timing results; repeat for more digits precision -v/--verbose: print raw timing results; repeat for more digits precision
-h/--help: print this usage message and exit -h/--help: print this usage message and exit
--: separate options from statement, use when statement starts with - --: separate options from statement, use when statement starts with -
...@@ -66,13 +66,7 @@ __all__ = ["Timer"] ...@@ -66,13 +66,7 @@ __all__ = ["Timer"]
dummy_src_name = "<timeit-src>" dummy_src_name = "<timeit-src>"
default_number = 1000000 default_number = 1000000
default_repeat = 3 default_repeat = 3
default_timer = time.perf_counter
if sys.platform == "win32":
# On Windows, the best timer is time.clock()
default_timer = time.clock
else:
# On most other platforms the best timer is time.time()
default_timer = time.time
# Don't change the indentation of the template; the reindent() calls # Don't change the indentation of the template; the reindent() calls
# in Timer.__init__() depend on setup being indented 4 spaces and stmt # in Timer.__init__() depend on setup being indented 4 spaces and stmt
......
...@@ -73,11 +73,15 @@ ALLOW_SKIPPING_CALIBRATION = 1 ...@@ -73,11 +73,15 @@ ALLOW_SKIPPING_CALIBRATION = 1
# Timer types # Timer types
TIMER_TIME_TIME = 'time.time' TIMER_TIME_TIME = 'time.time'
TIMER_TIME_PROCESS_TIME = 'time.process_time'
TIMER_TIME_PERF_COUNTER = 'time.perf_counter'
TIMER_TIME_CLOCK = 'time.clock' TIMER_TIME_CLOCK = 'time.clock'
TIMER_SYSTIMES_PROCESSTIME = 'systimes.processtime' TIMER_SYSTIMES_PROCESSTIME = 'systimes.processtime'
# Choose platform default timer # Choose platform default timer
if sys.platform[:3] == 'win': if hasattr(time, 'perf_counter'):
TIMER_PLATFORM_DEFAULT = TIMER_TIME_PERF_COUNTER
elif sys.platform[:3] == 'win':
# On WinXP this has 2.5ms resolution # On WinXP this has 2.5ms resolution
TIMER_PLATFORM_DEFAULT = TIMER_TIME_CLOCK TIMER_PLATFORM_DEFAULT = TIMER_TIME_CLOCK
else: else:
...@@ -93,6 +97,10 @@ def get_timer(timertype): ...@@ -93,6 +97,10 @@ def get_timer(timertype):
if timertype == TIMER_TIME_TIME: if timertype == TIMER_TIME_TIME:
return time.time return time.time
elif timertype == TIMER_TIME_PROCESS_TIME:
return time.process_time
elif timertype == TIMER_TIME_PERF_COUNTER:
return time.perf_counter
elif timertype == TIMER_TIME_CLOCK: elif timertype == TIMER_TIME_CLOCK:
return time.clock return time.clock
elif timertype == TIMER_SYSTIMES_PROCESSTIME: elif timertype == TIMER_SYSTIMES_PROCESSTIME:
...@@ -866,7 +874,18 @@ python pybench.py -s p25.pybench -c p21.pybench ...@@ -866,7 +874,18 @@ python pybench.py -s p25.pybench -c p21.pybench
print('* using timer: systimes.processtime (%s)' % \ print('* using timer: systimes.processtime (%s)' % \
systimes.SYSTIMES_IMPLEMENTATION) systimes.SYSTIMES_IMPLEMENTATION)
else: else:
# Check that the clock function does exist
try:
get_timer(timer)
except TypeError:
print("* Error: Unknown timer: %s" % timer)
return
print('* using timer: %s' % timer) print('* using timer: %s' % timer)
if hasattr(time, 'get_clock_info'):
info = time.get_clock_info(timer[5:])
print('* timer: resolution=%s, implementation=%s'
% (info.resolution, info.implementation))
print() print()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment