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

Reply via email to