Author: Yannick Jadoul <[email protected]>
Branch: py3.7-time-minor-bpos
Changeset: r98404:7f949f5fb55c
Date: 2019-12-29 17:57 +0100
http://bitbucket.org/pypy/pypy/changeset/7f949f5fb55c/
Log: Implement bpo-32025: Add time.thread_time()
diff --git a/pypy/module/time/interp_time.py b/pypy/module/time/interp_time.py
--- a/pypy/module/time/interp_time.py
+++ b/pypy/module/time/interp_time.py
@@ -240,6 +240,8 @@
HAS_CLOCK_MONOTONIC = rtime.CLOCK_MONOTONIC is not None
HAS_MONOTONIC = (_WIN or _MACOSX or
(HAS_CLOCK_GETTIME and (HAS_CLOCK_HIGHRES or
HAS_CLOCK_MONOTONIC)))
+HAS_THREAD_TIME = (_WIN or
+ (HAS_CLOCK_GETTIME and rtime.CLOCK_PROCESS_CPUTIME_ID is
not None))
tm = cConfig.tm
glob_buf = lltype.malloc(tm, flavor='raw', zero=True, immortal=True)
@@ -1220,6 +1222,75 @@
sum of the kernel and user-space CPU time"""
return _process_time_impl(space, w_info, True)
+if HAS_THREAD_TIME:
+ if _WIN:
+ _GetCurrentThread = rwin32.winexternal('GetCurrentThread', [],
rwin32.HANDLE)
+ _GetThreadTimes = rwin32.winexternal('GetThreadTimes', [rwin32.HANDLE,
+
lltype.Ptr(rwin32.FILETIME),
+
lltype.Ptr(rwin32.FILETIME),
+
lltype.Ptr(rwin32.FILETIME),
+
lltype.Ptr(rwin32.FILETIME)],
+ rwin32.BOOL)
+ def _thread_time_impl(space, w_info, return_ns):
+ thread = _GetCurrentThread()
+
+ with lltype.scoped_alloc(rwin32.FILETIME) as creation_time, \
+ lltype.scoped_alloc(rwin32.FILETIME) as exit_time, \
+ lltype.scoped_alloc(rwin32.FILETIME) as kernel_time, \
+ lltype.scoped_alloc(rwin32.FILETIME) as user_time:
+ ok = _GetThreadTimes(thread, creation_time, exit_time,
+ kernel_time, user_time)
+ if not ok:
+ raise wrap_oserror(space,
+ rwin32.lastSavedWindowsError("GetThreadTimes"))
+ ktime = (kernel_time.c_dwLowDateTime |
+ r_ulonglong(kernel_time.c_dwHighDateTime) << 32)
+ utime = (user_time.c_dwLowDateTime |
+ r_ulonglong(user_time.c_dwHighDateTime) << 32)
+
+ if w_info is not None:
+ _setinfo(space, w_info, "GetThreadTimes()", 1e-7, True, False)
+
+ # ktime and utime have a resolution of 100 nanoseconds
+ if return_ns:
+ return space.newint((r_int64(ktime) + r_int64(utime)) * 10**2)
+ else:
+ return space.newfloat((float(ktime) + float(utime)) * 1e-7)
+ else:
+ def _thread_time_impl(space, w_info, return_ns):
+ clk_id = rtime.CLOCK_THREAD_CPUTIME_ID
+ implementation = "clock_gettime(CLOCK_THREAD_CPUTIME_ID)"
+
+ with lltype.scoped_alloc(TIMESPEC) as timespec:
+ ret = c_clock_gettime(clk_id, timespec)
+ if ret == 0:
+ if w_info is not None:
+ with lltype.scoped_alloc(TIMESPEC) as tsres:
+ ret = c_clock_getres(clk_id, tsres)
+ if ret == 0:
+ res = _timespec_to_seconds(tsres)
+ else:
+ res = 1e-9
+ _setinfo(space, w_info,
+ implementation, res, True, False)
+ if return_ns:
+ return space.newint(_timespec_to_nanoseconds(timespec))
+ else:
+ return space.newfloat(_timespec_to_seconds(timespec))
+
+ def thread_time(space, w_info=None):
+ """thread_time() -> float
+
+ Thread time for profiling: sum of the kernel and user-space CPU
time."""
+ return _thread_time_impl(space, w_info, False)
+
+ def thread_time_ns(space, w_info=None):
+ """thread_time_ns() -> int
+
+ Thread time for profiling as nanoseconds:
+ sum of the kernel and user-space CPU time."""
+ return _thread_time_impl(space, w_info, True)
+
_clock = external('clock', [], rposix.CLOCK_T)
def _clock_impl(space, w_info, return_ns):
space.warn(space.newtext(
diff --git a/pypy/module/time/moduledef.py b/pypy/module/time/moduledef.py
--- a/pypy/module/time/moduledef.py
+++ b/pypy/module/time/moduledef.py
@@ -1,6 +1,6 @@
from pypy.interpreter.mixedmodule import MixedModule
-from .interp_time import HAS_MONOTONIC
+from .interp_time import HAS_MONOTONIC, HAS_THREAD_TIME
from rpython.rlib import rtime
import os
@@ -39,6 +39,9 @@
if HAS_MONOTONIC:
interpleveldefs['monotonic'] = 'interp_time.monotonic'
interpleveldefs['monotonic_ns'] = 'interp_time.monotonic_ns'
+ if HAS_THREAD_TIME:
+ interpleveldefs['thread_time'] = 'interp_time.thread_time'
+ interpleveldefs['thread_time_ns'] = 'interp_time.thread_time_ns'
if os.name == "posix":
interpleveldefs['tzset'] = 'interp_time.tzset'
diff --git a/pypy/module/time/test/test_time.py
b/pypy/module/time/test/test_time.py
--- a/pypy/module/time/test/test_time.py
+++ b/pypy/module/time/test/test_time.py
@@ -537,6 +537,29 @@
assert (t2 - t1) < 5 * 10**7
assert abs(time.process_time() - time.process_time_ns() * 1e-9) < 0.1
+ def test_thread_time(self):
+ import time
+ if not hasattr(time, 'thread_time'):
+ skip("need time.thread_time")
+ t1 = time.thread_time()
+ assert isinstance(t1, float)
+ time.sleep(0.1)
+ t2 = time.thread_time()
+ # thread_time_time() should not include time spent during sleep
+ assert (t2 - t1) < 0.05
+
+ def test_thread_time_ns(self):
+ import time
+ if not hasattr(time, 'thread_time_ns'):
+ skip("need time.thread_time_ns")
+ t1 = time.thread_time_ns()
+ assert isinstance(t1, int)
+ time.sleep(0.1)
+ t2 = time.process_time_ns()
+ # process_thread_ns() should not include time spent during sleep
+ assert (t2 - t1) < 5 * 10**7
+ assert abs(time.thread_time() - time.thread_time_ns() * 1e-9) < 0.1
+
def test_get_clock_info(self):
import time
clocks = ['clock', 'perf_counter', 'process_time', 'time']
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit