blob: 634e41b142e6d3a93671411ec271f0b123a4e4da [file] [log] [blame]
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001________________________________________________________________________
2
3PYBENCH - A Python Benchmark Suite
4________________________________________________________________________
5
6 Extendable suite of of low-level benchmarks for measuring
7 the performance of the Python implementation
8 (interpreter, compiler or VM).
9
10pybench is a collection of tests that provides a standardized way to
11measure the performance of Python implementations. It takes a very
12close look at different aspects of Python programs and let's you
13decide which factors are more important to you than others, rather
14than wrapping everything up in one number, like the other performance
15tests do (e.g. pystone which is included in the Python Standard
16Library).
17
18pybench has been used in the past by several Python developers to
19track down performance bottlenecks or to demonstrate the impact of
20optimizations and new features in Python.
21
22The command line interface for pybench is the file pybench.py. Run
23this script with option '--help' to get a listing of the possible
24options. Without options, pybench will simply execute the benchmark
25and then print out a report to stdout.
26
27
28Micro-Manual
29------------
30
31Run 'pybench.py -h' to see the help screen.
32Run 'pybench.py' to just let the benchmark suite do it's thing and
33'pybench.py -f <file>' to have it store the results in a file too.
34
35This is the current output of pybench.py --help:
36
37Synopsis:
38 pybench.py [option] files...
39
40Options and default settings:
41 -n arg number of rounds (10)
42 -f arg save benchmark to file arg ()
43 -c arg compare benchmark with the one in file arg ()
44 -s arg show benchmark in file arg, then exit ()
45 -S show statistics of benchmarks (0)
46 -w arg set warp factor to arg (20)
47 -d hide noise in compares (0)
48 --no-gc disable garbage collection (0)
49 -v generate verbose output
50 -h show this help text
51 --help show this help text
52 --debug enable debugging
53 --copyright show copyright
54 --examples show examples of usage
55
56Version:
57 1.3
58
59The normal operation is to run the suite and display the
60results. Use -f to save them for later reuse or comparisms.
61
62Examples:
63
64python1.5 pybench.py -w 100 -f p15
65python1.4 pybench.py -w 100 -f p14
66python pybench.py -s p15 -c p14
67
68
69License
70-------
71
72See LICENSE file.
73
74
75Sample output
76-------------
77
78PYBENCH 1.3
79
80Machine Details:
81 Platform ID: Linux-2.6.8-24.19-default-x86_64-with-SuSE-9.2-x86-64
82 Executable: /home/lemburg/projects/Python/Installation/bin/python
83 Python: 2.5a1.0
84 Compiler: GCC 3.3.4 (pre 3.3.5 20040809)
85 Build: Apr 9 2006 01:50:57 (#trunk)
86
87Searching for tests...
88 BuiltinFunctionCalls
89 BuiltinMethodLookup
90 CompareFloats
91 CompareFloatsIntegers
92 CompareIntegers
93 CompareInternedStrings
94 CompareLongs
95 CompareStrings
96 CompareUnicode
97 ConcatStrings
98 ConcatUnicode
99 CreateInstances
100 CreateStringsWithConcat
101 CreateUnicodeWithConcat
102 DictCreation
103 DictWithFloatKeys
104 DictWithIntegerKeys
105 DictWithStringKeys
106 ForLoops
107 IfThenElse
108 ListSlicing
109 NestedForLoops
110 NormalClassAttribute
111 NormalInstanceAttribute
112 PythonFunctionCalls
113 PythonMethodCalls
114 Recursion
115 SecondImport
116 SecondPackageImport
117 SecondSubmoduleImport
118 SimpleComplexArithmetic
119 SimpleDictManipulation
120 SimpleFloatArithmetic
121 SimpleIntFloatArithmetic
122 SimpleIntegerArithmetic
123 SimpleListManipulation
124 SimpleLongArithmetic
125 SmallLists
126 SmallTuples
127 SpecialClassAttribute
128 SpecialInstanceAttribute
129 StringMappings
130 StringPredicates
131 StringSlicing
132 TryExcept
133 TryRaiseExcept
134 TupleSlicing
135 UnicodeMappings
136 UnicodePredicates
137 UnicodeProperties
138 UnicodeSlicing
139
140Running 10 round(s) of the suite:
141
142...
143
144 Round 10 real abs overhead
145 BuiltinFunctionCalls: 0.030r 0.030a 0.000o
146 BuiltinMethodLookup: 0.059r 0.060a 0.001o
147 CompareFloats: 0.050r 0.050a 0.000o
148 CompareFloatsIntegers: 0.050r 0.050a 0.000o
149 CompareIntegers: 0.070r 0.070a 0.000o
150 CompareInternedStrings: 0.039r 0.040a 0.001o
151 CompareLongs: 0.050r 0.050a 0.000o
152 CompareStrings: 0.060r 0.060a 0.000o
153 CompareUnicode: 0.060r 0.060a 0.000o
154 ConcatStrings: 0.040r 0.040a 0.000o
155 ConcatUnicode: 0.050r 0.050a 0.000o
156 CreateInstances: 0.050r 0.050a 0.000o
157 CreateStringsWithConcat: 0.029r 0.030a 0.001o
158 CreateUnicodeWithConcat: 0.060r 0.060a 0.000o
159 DictCreation: 0.040r 0.040a 0.000o
160 DictWithFloatKeys: 0.089r 0.090a 0.000o
161 DictWithIntegerKeys: 0.059r 0.060a 0.001o
162 DictWithStringKeys: 0.070r 0.070a 0.001o
163 ForLoops: 0.050r 0.050a 0.000o
164 IfThenElse: 0.070r 0.070a 0.000o
165 ListSlicing: 0.030r 0.030a 0.000o
166 NestedForLoops: 0.030r 0.030a 0.000o
167 NormalClassAttribute: 0.060r 0.060a 0.000o
168 NormalInstanceAttribute: 0.060r 0.060a 0.000o
169 PythonFunctionCalls: 0.060r 0.060a 0.000o
170 PythonMethodCalls: 0.050r 0.050a 0.000o
171 Recursion: 0.050r 0.050a 0.000o
172 SecondImport: 0.030r 0.030a 0.000o
173 SecondPackageImport: 0.030r 0.030a 0.000o
174 SecondSubmoduleImport: 0.040r 0.040a 0.000o
175 SimpleComplexArithmetic: 0.030r 0.030a 0.000o
176 SimpleDictManipulation: 0.040r 0.040a 0.000o
177 SimpleFloatArithmetic: 0.050r 0.050a 0.001o
178 SimpleIntFloatArithmetic: 0.060r 0.060a 0.000o
179 SimpleIntegerArithmetic: 0.060r 0.060a 0.000o
180 SimpleListManipulation: 0.030r 0.030a 0.000o
181 SimpleLongArithmetic: 0.030r 0.030a 0.000o
182 SmallLists: 0.050r 0.050a 0.000o
183 SmallTuples: 0.050r 0.050a 0.000o
184 SpecialClassAttribute: 0.060r 0.060a 0.000o
185 SpecialInstanceAttribute: 0.079r 0.080a 0.001o
186 StringMappings: 0.060r 0.060a 0.000o
187 StringPredicates: 0.049r 0.050a 0.001o
188 StringSlicing: 0.039r 0.040a 0.000o
189 TryExcept: 0.079r 0.080a 0.001o
190 TryRaiseExcept: 0.059r 0.060a 0.001o
191 TupleSlicing: 0.050r 0.050a 0.000o
192 UnicodeMappings: 0.070r 0.070a 0.001o
193 UnicodePredicates: 0.059r 0.060a 0.001o
194 UnicodeProperties: 0.059r 0.060a 0.001o
195 UnicodeSlicing: 0.050r 0.050a 0.000o
196 ----------------------
197 Average round time: 2.937 seconds
198
199
200Tests: per run per oper. overhead
201------------------------------------------------------------------------
202 BuiltinFunctionCalls: 29.85 ms 0.23 us 0.00 ms
203 BuiltinMethodLookup: 66.85 ms 0.13 us 0.50 ms
204 CompareFloats: 43.00 ms 0.10 us 0.00 ms
205 CompareFloatsIntegers: 51.80 ms 0.12 us 0.00 ms
206 CompareIntegers: 70.70 ms 0.08 us 0.50 ms
207 CompareInternedStrings: 41.40 ms 0.08 us 0.50 ms
208 CompareLongs: 47.90 ms 0.11 us 0.00 ms
209 CompareStrings: 58.50 ms 0.12 us 0.50 ms
210 CompareUnicode: 56.55 ms 0.15 us 0.50 ms
211 ConcatStrings: 44.75 ms 0.30 us 0.00 ms
212 ConcatUnicode: 54.55 ms 0.36 us 0.50 ms
213 CreateInstances: 50.95 ms 1.21 us 0.00 ms
214 CreateStringsWithConcat: 28.85 ms 0.14 us 0.50 ms
215 CreateUnicodeWithConcat: 53.75 ms 0.27 us 0.00 ms
216 DictCreation: 41.90 ms 0.28 us 0.00 ms
217 DictWithFloatKeys: 88.50 ms 0.15 us 0.50 ms
218 DictWithIntegerKeys: 62.55 ms 0.10 us 0.50 ms
219 DictWithStringKeys: 60.50 ms 0.10 us 0.50 ms
220 ForLoops: 46.90 ms 4.69 us 0.00 ms
221 IfThenElse: 60.55 ms 0.09 us 0.00 ms
222 ListSlicing: 29.90 ms 8.54 us 0.00 ms
223 NestedForLoops: 33.95 ms 0.10 us 0.00 ms
224 NormalClassAttribute: 62.75 ms 0.10 us 0.50 ms
225 NormalInstanceAttribute: 61.80 ms 0.10 us 0.50 ms
226 PythonFunctionCalls: 60.00 ms 0.36 us 0.00 ms
227 PythonMethodCalls: 50.00 ms 0.67 us 0.00 ms
228 Recursion: 46.85 ms 3.75 us 0.00 ms
229 SecondImport: 35.00 ms 1.40 us 0.00 ms
230 SecondPackageImport: 32.00 ms 1.28 us 0.00 ms
231 SecondSubmoduleImport: 38.00 ms 1.52 us 0.00 ms
232 SimpleComplexArithmetic: 26.85 ms 0.12 us 0.00 ms
233 SimpleDictManipulation: 40.85 ms 0.14 us 0.00 ms
234 SimpleFloatArithmetic: 48.70 ms 0.09 us 0.50 ms
235 SimpleIntFloatArithmetic: 57.70 ms 0.09 us 0.00 ms
236 SimpleIntegerArithmetic: 58.75 ms 0.09 us 0.50 ms
237 SimpleListManipulation: 34.80 ms 0.13 us 0.00 ms
238 SimpleLongArithmetic: 30.95 ms 0.19 us 0.50 ms
239 SmallLists: 47.60 ms 0.19 us 0.00 ms
240 SmallTuples: 48.80 ms 0.20 us 0.50 ms
241 SpecialClassAttribute: 61.70 ms 0.10 us 0.00 ms
242 SpecialInstanceAttribute: 76.70 ms 0.13 us 0.50 ms
243 StringMappings: 58.70 ms 0.47 us 0.00 ms
244 StringPredicates: 50.00 ms 0.18 us 1.00 ms
245 StringSlicing: 39.65 ms 0.23 us 0.50 ms
246 TryExcept: 84.45 ms 0.06 us 0.50 ms
247 TryRaiseExcept: 61.75 ms 4.12 us 0.50 ms
248 TupleSlicing: 48.95 ms 0.47 us 0.00 ms
249 UnicodeMappings: 71.50 ms 3.97 us 0.50 ms
250 UnicodePredicates: 52.75 ms 0.23 us 1.00 ms
251 UnicodeProperties: 61.90 ms 0.31 us 1.00 ms
252 UnicodeSlicing: 53.75 ms 0.31 us 0.50 ms
253------------------------------------------------------------------------
254 Average round time: 2937.00 ms
255
256________________________________________________________________________
257
258Writing New Tests
259________________________________________________________________________
260
261pybench tests are simple modules defining one or more pybench.Test
262subclasses.
263
264Writing a test essentially boils down to providing two methods:
265.test() which runs .rounds number of .operations test operations each
266and .calibrate() which does the same except that it doesn't actually
267execute the operations.
268
269
270Here's an example:
271------------------
272
273from pybench import Test
274
275class IntegerCounting(Test):
276
277 # Version number of the test as float (x.yy); this is important
278 # for comparisons of benchmark runs - tests with unequal version
279 # number will not get compared.
280 version = 1.0
281
282 # The number of abstract operations done in each round of the
283 # test. An operation is the basic unit of what you want to
284 # measure. The benchmark will output the amount of run-time per
285 # operation. Note that in order to raise the measured timings
286 # significantly above noise level, it is often required to repeat
287 # sets of operations more than once per test round. The measured
288 # overhead per test round should be less than 1 second.
289 operations = 20
290
291 # Number of rounds to execute per test run. This should be
292 # adjusted to a figure that results in a test run-time of between
293 # 20-50 seconds.
294 rounds = 100000
295
296 def test(self):
297
298 """ Run the test.
299
300 The test needs to run self.rounds executing
301 self.operations number of operations each.
302
303 """
304 # Init the test
305 a = 1
306
307 # Run test rounds
308 #
309 # NOTE: Use xrange() for all test loops unless you want to face
310 # a 20MB process !
311 #
312 for i in xrange(self.rounds):
313
314 # Repeat the operations per round to raise the run-time
315 # per operation significantly above the noise level of the
316 # for-loop overhead.
317
318 # Execute 20 operations (a += 1):
319 a += 1
320 a += 1
321 a += 1
322 a += 1
323 a += 1
324 a += 1
325 a += 1
326 a += 1
327 a += 1
328 a += 1
329 a += 1
330 a += 1
331 a += 1
332 a += 1
333 a += 1
334 a += 1
335 a += 1
336 a += 1
337 a += 1
338 a += 1
339
340 def calibrate(self):
341
342 """ Calibrate the test.
343
344 This method should execute everything that is needed to
345 setup and run the test - except for the actual operations
346 that you intend to measure. pybench uses this method to
347 measure the test implementation overhead.
348
349 """
350 # Init the test
351 a = 1
352
353 # Run test rounds (without actually doing any operation)
354 for i in xrange(self.rounds):
355
356 # Skip the actual execution of the operations, since we
357 # only want to measure the test's administration overhead.
358 pass
359
360Registering a new test module
361-----------------------------
362
363To register a test module with pybench, the classes need to be
364imported into the pybench.Setup module. pybench will then scan all the
365symbols defined in that module for subclasses of pybench.Test and
366automatically add them to the benchmark suite.
367
368
369Have fun,
370--
371Marc-Andre Lemburg
372mal@lemburg.com