summaryrefslogtreecommitdiffstats
path: root/Tools/pybench/systimes.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/pybench/systimes.py')
-rw-r--r--Tools/pybench/systimes.py197
1 files changed, 197 insertions, 0 deletions
diff --git a/Tools/pybench/systimes.py b/Tools/pybench/systimes.py
new file mode 100644
index 0000000..79d249f
--- /dev/null
+++ b/Tools/pybench/systimes.py
@@ -0,0 +1,197 @@
+#!/usr/bin/env python
+
+""" systimes() user and system timer implementations for use by
+ pybench.
+
+ This module implements various different strategies for measuring
+ performance timings. It tries to choose the best available method
+ based on the platforma and available tools.
+
+ On Windows, it is recommended to have the Mark Hammond win32
+ package installed. Alternatively, the Thomas Heller ctypes
+ packages can also be used.
+
+ On Unix systems, the standard resource module provides the highest
+ resolution timings. Unfortunately, it is not available on all Unix
+ platforms.
+
+ If no supported timing methods based on process time can be found,
+ the module reverts to the highest resolution wall-time timer
+ instead. The system time part will then always be 0.0.
+
+ The module exports one public API:
+
+ def systimes():
+
+ Return the current timer values for measuring user and system
+ time as tuple of seconds (user_time, system_time).
+
+ Copyright (c) 2006, Marc-Andre Lemburg (mal@egenix.com). See the
+ documentation for further information on copyrights, or contact
+ the author. All Rights Reserved.
+
+"""
+import time, sys, struct
+
+#
+# Note: Please keep this module compatible to Python 1.5.2.
+#
+# TODOs:
+#
+# * Add ctypes wrapper for new clock_gettime() real-time POSIX APIs;
+# these will then provide nano-second resolution where available.
+#
+# * Add a function that returns the resolution of systimes()
+# values, ie. systimesres().
+#
+
+### Choose an implementation
+
+SYSTIMES_IMPLEMENTATION = None
+USE_CTYPES_GETPROCESSTIMES = 'cytpes GetProcessTimes() wrapper'
+USE_WIN32PROCESS_GETPROCESSTIMES = 'win32process.GetProcessTimes()'
+USE_RESOURCE_GETRUSAGE = 'resource.getrusage()'
+USE_PROCESS_TIME_CLOCK = 'time.clock() (process time)'
+USE_WALL_TIME_CLOCK = 'time.clock() (wall-time)'
+USE_WALL_TIME_TIME = 'time.time() (wall-time)'
+
+if sys.platform[:3] == 'win':
+ # Windows platform
+ try:
+ import win32process
+ except ImportError:
+ try:
+ import ctypes
+ except ImportError:
+ # Use the wall-time implementation time.clock(), since this
+ # is the highest resolution clock available on Windows
+ SYSTIMES_IMPLEMENTATION = USE_WALL_TIME_CLOCK
+ else:
+ SYSTIMES_IMPLEMENTATION = USE_CTYPES_GETPROCESSTIMES
+ else:
+ SYSTIMES_IMPLEMENTATION = USE_WIN32PROCESS_GETPROCESSTIMES
+else:
+ # All other platforms
+ try:
+ import resource
+ except ImportError:
+ pass
+ else:
+ SYSTIMES_IMPLEMENTATION = USE_RESOURCE_GETRUSAGE
+
+# Fall-back solution
+if SYSTIMES_IMPLEMENTATION is None:
+ # Check whether we can use time.clock() as approximation
+ # for systimes()
+ start = time.clock()
+ time.sleep(0.1)
+ stop = time.clock()
+ if stop - start < 0.001:
+ # Looks like time.clock() is usable (and measures process
+ # time)
+ SYSTIMES_IMPLEMENTATION = USE_PROCESS_TIME_CLOCK
+ else:
+ # Use wall-time implementation time.time() since this provides
+ # the highest resolution clock on most systems
+ SYSTIMES_IMPLEMENTATION = USE_WALL_TIME_TIME
+
+### Implementations
+
+def getrusage_systimes():
+ return resource.getrusage(resource.RUSAGE_SELF)[:2]
+
+def process_time_clock_systimes():
+ return (time.clock(), 0.0)
+
+def wall_time_clock_systimes():
+ return (time.clock(), 0.0)
+
+def wall_time_time_systimes():
+ return (time.time(), 0.0)
+
+# Number of clock ticks per second for the values returned
+# by GetProcessTimes() on Windows.
+#
+# Note: Ticks returned by GetProcessTimes() are micro-seconds on
+# Windows XP (though the docs say 100ns intervals)
+WIN32_PROCESS_TIMES_TICKS_PER_SECOND = 10e6
+
+def win32process_getprocesstimes_systimes():
+ d = win32process.GetProcessTimes(win32process.GetCurrentProcess())
+ # Note: I'm not sure whether KernelTime on Windows is the same as
+ # system time on Unix - I've yet to see a non-zero value for
+ # KernelTime on Windows.
+ return (d['UserTime'] / WIN32_PROCESS_TIMES_TICKS_PER_SECOND,
+ d['KernelTime'] / WIN32_PROCESS_TIMES_TICKS_PER_SECOND)
+
+def ctypes_getprocesstimes_systimes():
+ creationtime = ctypes.c_ulonglong()
+ exittime = ctypes.c_ulonglong()
+ kerneltime = ctypes.c_ulonglong()
+ usertime = ctypes.c_ulonglong()
+ rc = ctypes.windll.kernel32.GetProcessTimes(
+ ctypes.windll.kernel32.GetCurrentProcess(),
+ ctypes.byref(creationtime),
+ ctypes.byref(exittime),
+ ctypes.byref(kerneltime),
+ ctypes.byref(usertime))
+ if not rc:
+ raise TypeError('GetProcessTimes() returned an error')
+ return (usertime.value / WIN32_PROCESS_TIMES_TICKS_PER_SECOND,
+ kerneltime.value / WIN32_PROCESS_TIMES_TICKS_PER_SECOND)
+
+# Select the default for the systimes() function
+
+if SYSTIMES_IMPLEMENTATION is USE_RESOURCE_GETRUSAGE:
+ systimes = getrusage_systimes
+
+elif SYSTIMES_IMPLEMENTATION is USE_PROCESS_TIME_CLOCK:
+ systimes = process_time_clock_systimes
+
+elif SYSTIMES_IMPLEMENTATION is USE_WALL_TIME_CLOCK:
+ systimes = wall_time_clock_systimes
+
+elif SYSTIMES_IMPLEMENTATION is USE_WALL_TIME_TIME:
+ systimes = wall_time_time_systimes
+
+elif SYSTIMES_IMPLEMENTATION is USE_WIN32PROCESS_GETPROCESSTIMES:
+ systimes = win32process_getprocesstimes_systimes
+
+elif SYSTIMES_IMPLEMENTATION is USE_CTYPES_GETPROCESSTIMES:
+ systimes = ctypes_getprocesstimes_systimes
+
+else:
+ raise TypeError('no suitable systimes() implementation found')
+
+### Testing
+
+def some_workload():
+ x = 0L
+ for i in xrange(10000000L):
+ x = x + 1L
+
+def test_workload():
+ print 'Testing systimes() under load conditions'
+ t0 = systimes()
+ some_workload()
+ t1 = systimes()
+ print 'before:', t0
+ print 'after:', t1
+ print 'differences:', (t1[0] - t0[0], t1[1] - t0[1])
+ print
+
+def test_idle():
+ print 'Testing systimes() under idle conditions'
+ t0 = systimes()
+ time.sleep(1)
+ t1 = systimes()
+ print 'before:', t0
+ print 'after:', t1
+ print 'differences:', (t1[0] - t0[0], t1[1] - t0[1])
+ print
+
+if __name__ == '__main__':
+ print 'Using %s as timer' % SYSTIMES_IMPLEMENTATION
+ print
+ test_workload()
+ test_idle()