~ubuntu-branches/ubuntu/maverick/python3.1/maverick

« back to all changes in this revision

Viewing changes to Tools/pybench/systimes.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-23 00:01:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090323000127-5fstfxju4ufrhthq
Tags: upstream-3.1~a1+20090322
ImportĀ upstreamĀ versionĀ 3.1~a1+20090322

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
 
 
3
""" systimes() user and system timer implementations for use by
 
4
    pybench.
 
5
 
 
6
    This module implements various different strategies for measuring
 
7
    performance timings. It tries to choose the best available method
 
8
    based on the platforma and available tools.
 
9
 
 
10
    On Windows, it is recommended to have the Mark Hammond win32
 
11
    package installed. Alternatively, the Thomas Heller ctypes
 
12
    packages can also be used.
 
13
 
 
14
    On Unix systems, the standard resource module provides the highest
 
15
    resolution timings. Unfortunately, it is not available on all Unix
 
16
    platforms.
 
17
 
 
18
    If no supported timing methods based on process time can be found,
 
19
    the module reverts to the highest resolution wall-clock timer
 
20
    instead. The system time part will then always be 0.0.
 
21
 
 
22
    The module exports one public API:
 
23
 
 
24
    def systimes():
 
25
 
 
26
        Return the current timer values for measuring user and system
 
27
        time as tuple of seconds (user_time, system_time).
 
28
 
 
29
    Copyright (c) 2006, Marc-Andre Lemburg (mal@egenix.com). See the
 
30
    documentation for further information on copyrights, or contact
 
31
    the author. All Rights Reserved.
 
32
 
 
33
"""
 
34
 
 
35
from __future__ import print_function
 
36
 
 
37
import time, sys
 
38
 
 
39
#
 
40
# Note: Please keep this module compatible to Python 1.5.2.
 
41
#
 
42
# TODOs:
 
43
#
 
44
# * Add ctypes wrapper for new clock_gettime() real-time POSIX APIs;
 
45
#   these will then provide nano-second resolution where available.
 
46
#
 
47
# * Add a function that returns the resolution of systimes()
 
48
#   values, ie. systimesres().
 
49
#
 
50
 
 
51
### Choose an implementation
 
52
 
 
53
SYSTIMES_IMPLEMENTATION = None
 
54
USE_CTYPES_GETPROCESSTIMES = 'ctypes GetProcessTimes() wrapper'
 
55
USE_WIN32PROCESS_GETPROCESSTIMES = 'win32process.GetProcessTimes()'
 
56
USE_RESOURCE_GETRUSAGE = 'resource.getrusage()'
 
57
USE_PROCESS_TIME_CLOCK = 'time.clock() (process time)'
 
58
USE_WALL_TIME_CLOCK = 'time.clock() (wall-clock)'
 
59
USE_WALL_TIME_TIME = 'time.time() (wall-clock)'
 
60
 
 
61
if sys.platform[:3] == 'win':
 
62
    # Windows platform
 
63
    try:
 
64
        import win32process
 
65
    except ImportError:
 
66
        try:
 
67
            import ctypes
 
68
        except ImportError:
 
69
            # Use the wall-clock implementation time.clock(), since this
 
70
            # is the highest resolution clock available on Windows
 
71
            SYSTIMES_IMPLEMENTATION = USE_WALL_TIME_CLOCK
 
72
        else:
 
73
            SYSTIMES_IMPLEMENTATION = USE_CTYPES_GETPROCESSTIMES
 
74
    else:
 
75
        SYSTIMES_IMPLEMENTATION = USE_WIN32PROCESS_GETPROCESSTIMES
 
76
else:
 
77
    # All other platforms
 
78
    try:
 
79
        import resource
 
80
    except ImportError:
 
81
        pass
 
82
    else:
 
83
        SYSTIMES_IMPLEMENTATION = USE_RESOURCE_GETRUSAGE
 
84
 
 
85
# Fall-back solution
 
86
if SYSTIMES_IMPLEMENTATION is None:
 
87
    # Check whether we can use time.clock() as approximation
 
88
    # for systimes()
 
89
    start = time.clock()
 
90
    time.sleep(0.1)
 
91
    stop = time.clock()
 
92
    if stop - start < 0.001:
 
93
        # Looks like time.clock() is usable (and measures process
 
94
        # time)
 
95
        SYSTIMES_IMPLEMENTATION = USE_PROCESS_TIME_CLOCK
 
96
    else:
 
97
        # Use wall-clock implementation time.time() since this provides
 
98
        # the highest resolution clock on most systems
 
99
        SYSTIMES_IMPLEMENTATION = USE_WALL_TIME_TIME
 
100
 
 
101
### Implementations
 
102
 
 
103
def getrusage_systimes():
 
104
    return resource.getrusage(resource.RUSAGE_SELF)[:2]
 
105
 
 
106
def process_time_clock_systimes():
 
107
    return (time.clock(), 0.0)
 
108
 
 
109
def wall_clock_clock_systimes():
 
110
    return (time.clock(), 0.0)
 
111
 
 
112
def wall_clock_time_systimes():
 
113
    return (time.time(), 0.0)
 
114
 
 
115
# Number of clock ticks per second for the values returned
 
116
# by GetProcessTimes() on Windows.
 
117
#
 
118
# Note: Ticks returned by GetProcessTimes() are 100ns intervals on
 
119
# Windows XP. However, the process times are only updated with every
 
120
# clock tick and the frequency of these is somewhat lower: depending
 
121
# on the OS version between 10ms and 15ms. Even worse, the process
 
122
# time seems to be allocated to process currently running when the
 
123
# clock interrupt arrives, ie. it is possible that the current time
 
124
# slice gets accounted to a different process.
 
125
 
 
126
WIN32_PROCESS_TIMES_TICKS_PER_SECOND = 1e7
 
127
 
 
128
def win32process_getprocesstimes_systimes():
 
129
    d = win32process.GetProcessTimes(win32process.GetCurrentProcess())
 
130
    return (d['UserTime'] / WIN32_PROCESS_TIMES_TICKS_PER_SECOND,
 
131
            d['KernelTime'] / WIN32_PROCESS_TIMES_TICKS_PER_SECOND)
 
132
 
 
133
def ctypes_getprocesstimes_systimes():
 
134
    creationtime = ctypes.c_ulonglong()
 
135
    exittime = ctypes.c_ulonglong()
 
136
    kerneltime = ctypes.c_ulonglong()
 
137
    usertime = ctypes.c_ulonglong()
 
138
    rc = ctypes.windll.kernel32.GetProcessTimes(
 
139
        ctypes.windll.kernel32.GetCurrentProcess(),
 
140
        ctypes.byref(creationtime),
 
141
        ctypes.byref(exittime),
 
142
        ctypes.byref(kerneltime),
 
143
        ctypes.byref(usertime))
 
144
    if not rc:
 
145
        raise TypeError('GetProcessTimes() returned an error')
 
146
    return (usertime.value / WIN32_PROCESS_TIMES_TICKS_PER_SECOND,
 
147
            kerneltime.value / WIN32_PROCESS_TIMES_TICKS_PER_SECOND)
 
148
 
 
149
# Select the default for the systimes() function
 
150
 
 
151
if SYSTIMES_IMPLEMENTATION is USE_RESOURCE_GETRUSAGE:
 
152
    systimes = getrusage_systimes
 
153
 
 
154
elif SYSTIMES_IMPLEMENTATION is USE_PROCESS_TIME_CLOCK:
 
155
    systimes = process_time_clock_systimes
 
156
 
 
157
elif SYSTIMES_IMPLEMENTATION is USE_WALL_TIME_CLOCK:
 
158
    systimes = wall_clock_clock_systimes
 
159
 
 
160
elif SYSTIMES_IMPLEMENTATION is USE_WALL_TIME_TIME:
 
161
    systimes = wall_clock_time_systimes
 
162
 
 
163
elif SYSTIMES_IMPLEMENTATION is USE_WIN32PROCESS_GETPROCESSTIMES:
 
164
    systimes = win32process_getprocesstimes_systimes
 
165
 
 
166
elif SYSTIMES_IMPLEMENTATION is USE_CTYPES_GETPROCESSTIMES:
 
167
    systimes = ctypes_getprocesstimes_systimes
 
168
 
 
169
else:
 
170
    raise TypeError('no suitable systimes() implementation found')
 
171
 
 
172
def processtime():
 
173
 
 
174
    """ Return the total time spent on the process.
 
175
 
 
176
        This is the sum of user and system time as returned by
 
177
        systimes().
 
178
 
 
179
    """
 
180
    user, system = systimes()
 
181
    return user + system
 
182
 
 
183
### Testing
 
184
 
 
185
def some_workload():
 
186
    x = 0
 
187
    for i in range(10000000):
 
188
        x = x + 1
 
189
 
 
190
def test_workload():
 
191
    print('Testing systimes() under load conditions')
 
192
    t0 = systimes()
 
193
    some_workload()
 
194
    t1 = systimes()
 
195
    print('before:', t0)
 
196
    print('after:', t1)
 
197
    print('differences:', (t1[0] - t0[0], t1[1] - t0[1]))
 
198
    print()
 
199
 
 
200
def test_idle():
 
201
    print('Testing systimes() under idle conditions')
 
202
    t0 = systimes()
 
203
    time.sleep(1)
 
204
    t1 = systimes()
 
205
    print('before:', t0)
 
206
    print('after:', t1)
 
207
    print('differences:', (t1[0] - t0[0], t1[1] - t0[1]))
 
208
    print()
 
209
 
 
210
if __name__ == '__main__':
 
211
    print('Using %s as timer' % SYSTIMES_IMPLEMENTATION)
 
212
    print()
 
213
    test_workload()
 
214
    test_idle()