Commit 70f03984 authored by Marc-André Lemburg's avatar Marc-André Lemburg

Update pybench to version 2.0.

parent 7f36041d
from pybench import Test
class SimpleIntegerArithmetic(Test):
version = 2.0
operations = 5 * (3 + 5 + 5 + 3 + 3 + 3)
rounds = 120000
def test(self):
for i in xrange(self.rounds):
a = 2
b = 3
c = 3
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2
b = 3
c = 3
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2
b = 3
c = 3
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2
b = 3
c = 3
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2
b = 3
c = 3
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
def calibrate(self):
for i in xrange(self.rounds):
pass
class SimpleFloatArithmetic(Test):
version = 2.0
operations = 5 * (3 + 5 + 5 + 3 + 3 + 3)
rounds = 120000
def test(self):
for i in xrange(self.rounds):
a = 2.1
b = 3.3332
c = 3.14159
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2.1
b = 3.3332
c = 3.14159
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2.1
b = 3.3332
c = 3.14159
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2.1
b = 3.3332
c = 3.14159
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2.1
b = 3.3332
c = 3.14159
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
def calibrate(self):
for i in xrange(self.rounds):
pass
class SimpleIntFloatArithmetic(Test):
version = 2.0
operations = 5 * (3 + 5 + 5 + 3 + 3 + 3)
rounds = 120000
def test(self):
for i in xrange(self.rounds):
a = 2
b = 3
c = 3.14159
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2
b = 3
c = 3.14159
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2
b = 3
c = 3.14159
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2
b = 3
c = 3.14159
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2
b = 3
c = 3.14159
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
def calibrate(self):
for i in xrange(self.rounds):
pass
class SimpleLongArithmetic(Test):
version = 2.0
operations = 5 * (3 + 5 + 5 + 3 + 3 + 3)
rounds = 60000
def test(self):
for i in xrange(self.rounds):
a = 2220001L
b = 100001L
c = 30005L
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2220001L
b = 100001L
c = 30005L
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2220001L
b = 100001L
c = 30005L
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2220001L
b = 100001L
c = 30005L
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2220001L
b = 100001L
c = 30005L
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
def calibrate(self):
for i in xrange(self.rounds):
pass
class SimpleComplexArithmetic(Test):
version = 2.0
operations = 5 * (3 + 5 + 5 + 3 + 3 + 3)
rounds = 80000
def test(self):
for i in xrange(self.rounds):
a = 2 + 3j
b = 2.5 + 4.5j
c = 1.2 + 6.2j
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2 + 3j
b = 2.5 + 4.5j
c = 1.2 + 6.2j
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2 + 3j
b = 2.5 + 4.5j
c = 1.2 + 6.2j
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2 + 3j
b = 2.5 + 4.5j
c = 1.2 + 6.2j
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
a = 2 + 3j
b = 2.5 + 4.5j
c = 1.2 + 6.2j
c = a + b
c = b + c
c = c + a
c = a + b
c = b + c
c = c - a
c = a - b
c = b - c
c = c - a
c = b - c
c = a / b
c = b / a
c = c / b
c = a * b
c = b * a
c = c * b
c = a / b
c = b / a
c = c / b
def calibrate(self):
for i in xrange(self.rounds):
pass
from pybench import Test
class PythonFunctionCalls(Test):
version = 2.0
operations = 5*(1+4+4+2)
rounds = 60000
def test(self):
global f,f1,g,h
# define functions
def f():
pass
def f1(x):
pass
def g(a,b,c):
return a,b,c
def h(a,b,c,d=1,e=2,f=3):
return d,e,f
# do calls
for i in xrange(self.rounds):
f()
f1(i)
f1(i)
f1(i)
f1(i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
h(i,i,3,i,i)
h(i,i,i,2,i,3)
f()
f1(i)
f1(i)
f1(i)
f1(i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
h(i,i,3,i,i)
h(i,i,i,2,i,3)
f()
f1(i)
f1(i)
f1(i)
f1(i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
h(i,i,3,i,i)
h(i,i,i,2,i,3)
f()
f1(i)
f1(i)
f1(i)
f1(i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
h(i,i,3,i,i)
h(i,i,i,2,i,3)
f()
f1(i)
f1(i)
f1(i)
f1(i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
h(i,i,3,i,i)
h(i,i,i,2,i,3)
def calibrate(self):
global f,f1,g,h
# define functions
def f():
pass
def f1(x):
pass
def g(a,b,c):
return a,b,c
def h(a,b,c,d=1,e=2,f=3):
return d,e,f
# do calls
for i in xrange(self.rounds):
pass
###
class BuiltinFunctionCalls(Test):
version = 2.0
operations = 5*(2+5+5+5)
rounds = 60000
def test(self):
# localize functions
f0 = globals
f1 = hash
f2 = cmp
f3 = range
# do calls
for i in xrange(self.rounds):
f0()
f0()
f1(i)
f1(i)
f1(i)
f1(i)
f1(i)
f2(1,2)
f2(1,2)
f2(1,2)
f2(1,2)
f2(1,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
f0()
f0()
f1(i)
f1(i)
f1(i)
f1(i)
f1(i)
f2(1,2)
f2(1,2)
f2(1,2)
f2(1,2)
f2(1,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
f0()
f0()
f1(i)
f1(i)
f1(i)
f1(i)
f1(i)
f2(1,2)
f2(1,2)
f2(1,2)
f2(1,2)
f2(1,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
f0()
f0()
f1(i)
f1(i)
f1(i)
f1(i)
f1(i)
f2(1,2)
f2(1,2)
f2(1,2)
f2(1,2)
f2(1,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
f0()
f0()
f1(i)
f1(i)
f1(i)
f1(i)
f1(i)
f2(1,2)
f2(1,2)
f2(1,2)
f2(1,2)
f2(1,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
f3(1,3,2)
def calibrate(self):
# localize functions
f0 = dir
f1 = hash
f2 = range
f3 = range
# do calls
for i in xrange(self.rounds):
pass
###
class PythonMethodCalls(Test):
version = 2.0
operations = 5*(6 + 5 + 4)
rounds = 30000
def test(self):
class c:
x = 2
s = 'string'
def f(self):
return self.x
def j(self,a,b):
self.y = a
self.t = b
return self.y
def k(self,a,b,c=3):
self.y = a
self.s = b
self.t = c
o = c()
for i in xrange(self.rounds):
o.f()
o.f()
o.f()
o.f()
o.f()
o.f()
o.j(i,i)
o.j(i,i)
o.j(i,2)
o.j(i,2)
o.j(2,2)
o.k(i,i)
o.k(i,2)
o.k(i,2,3)
o.k(i,i,c=4)
o.f()
o.f()
o.f()
o.f()
o.f()
o.f()
o.j(i,i)
o.j(i,i)
o.j(i,2)
o.j(i,2)
o.j(2,2)
o.k(i,i)
o.k(i,2)
o.k(i,2,3)
o.k(i,i,c=4)
o.f()
o.f()
o.f()
o.f()
o.f()
o.f()
o.j(i,i)
o.j(i,i)
o.j(i,2)
o.j(i,2)
o.j(2,2)
o.k(i,i)
o.k(i,2)
o.k(i,2,3)
o.k(i,i,c=4)
o.f()
o.f()
o.f()
o.f()
o.f()
o.f()
o.j(i,i)
o.j(i,i)
o.j(i,2)
o.j(i,2)
o.j(2,2)
o.k(i,i)
o.k(i,2)
o.k(i,2,3)
o.k(i,i,c=4)
o.f()
o.f()
o.f()
o.f()
o.f()
o.f()
o.j(i,i)
o.j(i,i)
o.j(i,2)
o.j(i,2)
o.j(2,2)
o.k(i,i)
o.k(i,2)
o.k(i,2,3)
o.k(i,i,c=4)
def calibrate(self):
class c:
x = 2
s = 'string'
def f(self):
return self.x
def j(self,a,b):
self.y = a
self.t = b
def k(self,a,b,c=3):
self.y = a
self.s = b
self.t = c
o = c
for i in xrange(self.rounds):
pass
###
class Recursion(Test):
version = 2.0
operations = 5
rounds = 100000
def test(self):
global f
def f(x):
if x > 1:
return f(x-1)
return 1
for i in xrange(self.rounds):
f(10)
f(10)
f(10)
f(10)
f(10)
def calibrate(self):
global f
def f(x):
if x > 0:
return f(x-1)
return 1
for i in xrange(self.rounds):
pass
### Test to make Fredrik happy...
if __name__ == '__main__':
import timeit
if 0:
timeit.TestClass = PythonFunctionCalls
timeit.main(['-s', 'test = TestClass(); test.rounds = 1000',
'test.test()'])
else:
setup = """\
global f,f1,g,h
# define functions
def f():
pass
def f1(x):
pass
def g(a,b,c):
return a,b,c
def h(a,b,c,d=1,e=2,f=3):
return d,e,f
i = 1
"""
test = """\
f()
f1(i)
f1(i)
f1(i)
f1(i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
h(i,i,3,i,i)
h(i,i,i,2,i,3)
f()
f1(i)
f1(i)
f1(i)
f1(i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
h(i,i,3,i,i)
h(i,i,i,2,i,3)
f()
f1(i)
f1(i)
f1(i)
f1(i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
h(i,i,3,i,i)
h(i,i,i,2,i,3)
f()
f1(i)
f1(i)
f1(i)
f1(i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
h(i,i,3,i,i)
h(i,i,i,2,i,3)
f()
f1(i)
f1(i)
f1(i)
f1(i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
g(i,i,i)
h(i,i,3,i,i)
h(i,i,i,2,i,3)
"""
timeit.main(['-s', setup,
test])
""" CommandLine - Get and parse command line options
NOTE: This still is very much work in progress !!!
Different version are likely to be incompatible.
TODO:
* Incorporate the changes made by (see Inbox)
* Add number range option using srange()
"""
__copyright__ = """\
Copyright (c), 1997-2006, Marc-Andre Lemburg (mal@lemburg.com)
Copyright (c), 2000-2006, eGenix.com Software GmbH (info@egenix.com)
See the documentation for further information on copyrights,
or contact the author. All Rights Reserved.
"""
__version__ = '1.2'
import sys, getopt, string, glob, os, re, exceptions, traceback
### Helpers
def _getopt_flags(options):
""" Convert the option list to a getopt flag string and long opt
list
"""
s = []
l = []
for o in options:
if o.prefix == '-':
# short option
s.append(o.name)
if o.takes_argument:
s.append(':')
else:
# long option
if o.takes_argument:
l.append(o.name+'=')
else:
l.append(o.name)
return string.join(s,''),l
def invisible_input(prompt='>>> '):
""" Get raw input from a terminal without echoing the characters to
the terminal, e.g. for password queries.
"""
import getpass
entry = getpass.getpass(prompt)
if entry is None:
raise KeyboardInterrupt
return entry
def fileopen(name, mode='wb', encoding=None):
""" Open a file using mode.
Default mode is 'wb' meaning to open the file for writing in
binary mode. If encoding is given, I/O to and from the file is
transparently encoded using the given encoding.
Files opened for writing are chmod()ed to 0600.
"""
if name == 'stdout':
return sys.stdout
elif name == 'stderr':
return sys.stderr
elif name == 'stdin':
return sys.stdin
else:
if encoding is not None:
import codecs
f = codecs.open(name, mode, encoding)
else:
f = open(name, mode)
if 'w' in mode:
os.chmod(name, 0600)
return f
def option_dict(options):
""" Return a dictionary mapping option names to Option instances.
"""
d = {}
for option in options:
d[option.name] = option
return d
# Alias
getpasswd = invisible_input
_integerRE = re.compile('\s*(-?\d+)\s*$')
_integerRangeRE = re.compile('\s*(-?\d+)\s*-\s*(-?\d+)\s*$')
def srange(s,
split=string.split,integer=_integerRE,
integerRange=_integerRangeRE):
""" Converts a textual representation of integer numbers and ranges
to a Python list.
Supported formats: 2,3,4,2-10,-1 - -3, 5 - -2
Values are appended to the created list in the order specified
in the string.
"""
l = []
append = l.append
for entry in split(s,','):
m = integer.match(entry)
if m:
append(int(m.groups()[0]))
continue
m = integerRange.match(entry)
if m:
start,end = map(int,m.groups())
l[len(l):] = range(start,end+1)
return l
def abspath(path,
expandvars=os.path.expandvars,expanduser=os.path.expanduser,
join=os.path.join,getcwd=os.getcwd):
""" Return the corresponding absolute path for path.
path is expanded in the usual shell ways before
joining it with the current working directory.
"""
try:
path = expandvars(path)
except AttributeError:
pass
try:
path = expanduser(path)
except AttributeError:
pass
return join(getcwd(), path)
### Option classes
class Option:
""" Option base class. Takes no argument.
"""
default = None
helptext = ''
prefix = '-'
takes_argument = 0
has_default = 0
tab = 15
def __init__(self,name,help=None):
if not name[:1] == '-':
raise TypeError,'option names must start with "-"'
if name[1:2] == '-':
self.prefix = '--'
self.name = name[2:]
else:
self.name = name[1:]
if help:
self.help = help
def __str__(self):
o = self
name = o.prefix + o.name
if o.takes_argument:
name = name + ' arg'
if len(name) > self.tab:
name = name + '\n' + ' ' * (self.tab + 1 + len(o.prefix))
else:
name = '%-*s ' % (self.tab, name)
description = o.help
if o.has_default:
description = description + ' (%s)' % o.default
return '%s %s' % (name, description)
class ArgumentOption(Option):
""" Option that takes an argument.
An optional default argument can be given.
"""
def __init__(self,name,help=None,default=None):
# Basemethod
Option.__init__(self,name,help)
if default is not None:
self.default = default
self.has_default = 1
self.takes_argument = 1
class SwitchOption(Option):
""" Options that can be on or off. Has an optional default value.
"""
def __init__(self,name,help=None,default=None):
# Basemethod
Option.__init__(self,name,help)
if default is not None:
self.default = default
self.has_default = 1
### Application baseclass
class Application:
""" Command line application interface with builtin argument
parsing.
"""
# Options the program accepts (Option instances)
options = []
# Standard settings; these are appended to options in __init__
preset_options = [SwitchOption('-v',
'generate verbose output'),
SwitchOption('-h',
'show this help text'),
SwitchOption('--help',
'show this help text'),
SwitchOption('--debug',
'enable debugging'),
SwitchOption('--copyright',
'show copyright'),
SwitchOption('--examples',
'show examples of usage')]
# The help layout looks like this:
# [header] - defaults to ''
#
# [synopsis] - formatted as '<self.name> %s' % self.synopsis
#
# options:
# [options] - formatted from self.options
#
# [version] - formatted as 'Version:\n %s' % self.version, if given
#
# [about] - defaults to ''
#
# Note: all fields that do not behave as template are formatted
# using the instances dictionary as substitution namespace,
# e.g. %(name)s will be replaced by the applications name.
#
# Header (default to program name)
header = ''
# Name (defaults to program name)
name = ''
# Synopsis (%(name)s is replaced by the program name)
synopsis = '%(name)s [option] files...'
# Version (optional)
version = ''
# General information printed after the possible options (optional)
about = ''
# Examples of usage to show when the --examples option is given (optional)
examples = ''
# Copyright to show
copyright = __copyright__
# Apply file globbing ?
globbing = 1
# Generate debug output ?
debug = 0
# Generate verbose output ?
verbose = 0
# Internal errors to catch
InternalError = exceptions.Exception
# Instance variables:
values = None # Dictionary of passed options (or default values)
# indexed by the options name, e.g. '-h'
files = None # List of passed filenames
optionlist = None # List of passed options
def __init__(self,argv=None):
# Setup application specs
if argv is None:
argv = sys.argv
self.filename = os.path.split(argv[0])[1]
if not self.name:
self.name = os.path.split(self.filename)[1]
else:
self.name = self.name
if not self.header:
self.header = self.name
else:
self.header = self.header
# Init .arguments list
self.arguments = argv[1:]
# Setup Option mapping
self.option_map = option_dict(self.options)
# Append preset options
for option in self.preset_options:
if not self.option_map.has_key(option.name):
self.add_option(option)
# Init .files list
self.files = []
# Start Application
try:
# Process startup
rc = self.startup()
if rc is not None:
raise SystemExit,rc
# Parse command line
rc = self.parse()
if rc is not None:
raise SystemExit,rc
# Start application
rc = self.main()
if rc is None:
rc = 0
except SystemExit,rc:
pass
except KeyboardInterrupt:
print
print '* User Break'
print
rc = 1
except self.InternalError:
print
print '* Internal Error (use --debug to display the traceback)'
if self.debug:
print
traceback.print_exc(20, sys.stdout)
elif self.verbose:
print ' %s: %s' % sys.exc_info()[:2]
print
rc = 1
raise SystemExit,rc
def add_option(self, option):
""" Add a new Option instance to the Application dynamically.
Note that this has to be done *before* .parse() is being
executed.
"""
self.options.append(option)
self.option_map[option.name] = option
def startup(self):
""" Set user defined instance variables.
If this method returns anything other than None, the
process is terminated with the return value as exit code.
"""
return None
def exit(self, rc=0):
""" Exit the program.
rc is used as exit code and passed back to the calling
program. It defaults to 0 which usually means: OK.
"""
raise SystemExit, rc
def parse(self):
""" Parse the command line and fill in self.values and self.files.
After having parsed the options, the remaining command line
arguments are interpreted as files and passed to .handle_files()
for processing.
As final step the option handlers are called in the order
of the options given on the command line.
"""
# Parse arguments
self.values = values = {}
for o in self.options:
if o.has_default:
values[o.prefix+o.name] = o.default
else:
values[o.prefix+o.name] = 0
flags,lflags = _getopt_flags(self.options)
try:
optlist,files = getopt.getopt(self.arguments,flags,lflags)
if self.globbing:
l = []
for f in files:
gf = glob.glob(f)
if not gf:
l.append(f)
else:
l[len(l):] = gf
files = l
self.optionlist = optlist
self.files = files + self.files
except getopt.error,why:
self.help(why)
sys.exit(1)
# Call file handler
rc = self.handle_files(self.files)
if rc is not None:
sys.exit(rc)
# Call option handlers
for optionname, value in optlist:
# Try to convert value to integer
try:
value = string.atoi(value)
except ValueError:
pass
# Find handler and call it (or count the number of option
# instances on the command line)
handlername = 'handle' + string.replace(optionname, '-', '_')
try:
handler = getattr(self, handlername)
except AttributeError:
if value == '':
# count the number of occurances
if values.has_key(optionname):
values[optionname] = values[optionname] + 1
else:
values[optionname] = 1
else:
values[optionname] = value
else:
rc = handler(value)
if rc is not None:
raise SystemExit, rc
# Apply final file check (for backward compatibility)
rc = self.check_files(self.files)
if rc is not None:
sys.exit(rc)
def check_files(self,filelist):
""" Apply some user defined checks on the files given in filelist.
This may modify filelist in place. A typical application
is checking that at least n files are given.
If this method returns anything other than None, the
process is terminated with the return value as exit code.
"""
return None
def help(self,note=''):
self.print_header()
if self.synopsis:
print 'Synopsis:'
# To remain backward compatible:
try:
synopsis = self.synopsis % self.name
except (NameError, KeyError, TypeError):
synopsis = self.synopsis % self.__dict__
print ' ' + synopsis
print
self.print_options()
if self.version:
print 'Version:'
print ' %s' % self.version
print
if self.about:
print string.strip(self.about % self.__dict__)
print
if note:
print '-'*72
print 'Note:',note
print
def notice(self,note):
print '-'*72
print 'Note:',note
print '-'*72
print
def print_header(self):
print '-'*72
print self.header % self.__dict__
print '-'*72
print
def print_options(self):
options = self.options
print 'Options and default settings:'
if not options:
print ' None'
return
long = filter(lambda x: x.prefix == '--', options)
short = filter(lambda x: x.prefix == '-', options)
items = short + long
for o in options:
print ' ',o
print
#
# Example handlers:
#
# If a handler returns anything other than None, processing stops
# and the return value is passed to sys.exit() as argument.
#
# File handler
def handle_files(self,files):
""" This may process the files list in place.
"""
return None
# Short option handler
def handle_h(self,arg):
self.help()
return 0
def handle_v(self, value):
""" Turn on verbose output.
"""
self.verbose = 1
# Handlers for long options have two underscores in their name
def handle__help(self,arg):
self.help()
return 0
def handle__debug(self,arg):
self.debug = 1
# We don't want to catch internal errors:
self.InternalError = None
def handle__copyright(self,arg):
self.print_header()
print string.strip(self.copyright % self.__dict__)
print
return 0
def handle__examples(self,arg):
self.print_header()
if self.examples:
print 'Examples:'
print
print string.strip(self.examples % self.__dict__)
print
else:
print 'No examples available.'
print
return 0
def main(self):
""" Override this method as program entry point.
The return value is passed to sys.exit() as argument. If
it is None, 0 is assumed (meaning OK). Unhandled
exceptions are reported with exit status code 1 (see
__init__ for further details).
"""
return None
# Alias
CommandLine = Application
def _test():
class MyApplication(Application):
header = 'Test Application'
version = __version__
options = [Option('-v','verbose')]
def handle_v(self,arg):
print 'VERBOSE, Yeah !'
cmd = MyApplication()
if not cmd.values['-h']:
cmd.help()
print 'files:',cmd.files
print 'Bye...'
if __name__ == '__main__':
_test()
from pybench import Test
class IfThenElse(Test):
version = 2.0
operations = 30*3 # hard to say...
rounds = 150000
def test(self):
a,b,c = 1,2,3
for i in xrange(self.rounds):
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
if a == 1:
if b == 2:
if c != 3:
c = 3
b = 3
else:
c = 2
elif b == 3:
b = 2
a = 2
elif a == 2:
a = 3
else:
a = 1
def calibrate(self):
a,b,c = 1,2,3
for i in xrange(self.rounds):
pass
class NestedForLoops(Test):
version = 2.0
operations = 1000*10*5
rounds = 300
def test(self):
l1 = range(1000)
l2 = range(10)
l3 = range(5)
for i in xrange(self.rounds):
for i in l1:
for j in l2:
for k in l3:
pass
def calibrate(self):
l1 = range(1000)
l2 = range(10)
l3 = range(5)
for i in xrange(self.rounds):
pass
class ForLoops(Test):
version = 2.0
operations = 5 * 5
rounds = 10000
def test(self):
l1 = range(100)
for i in xrange(self.rounds):
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
for i in l1:
pass
def calibrate(self):
l1 = range(1000)
for i in xrange(self.rounds):
pass
from pybench import Test
class DictCreation(Test):
version = 2.0
operations = 5*(5 + 5)
rounds = 80000
def test(self):
for i in xrange(self.rounds):
d1 = {}
d2 = {}
d3 = {}
d4 = {}
d5 = {}
d1 = {1:2,3:4,5:6}
d2 = {2:3,4:5,6:7}
d3 = {3:4,5:6,7:8}
d4 = {4:5,6:7,8:9}
d5 = {6:7,8:9,10:11}
d1 = {}
d2 = {}
d3 = {}
d4 = {}
d5 = {}
d1 = {1:2,3:4,5:6}
d2 = {2:3,4:5,6:7}
d3 = {3:4,5:6,7:8}
d4 = {4:5,6:7,8:9}
d5 = {6:7,8:9,10:11}
d1 = {}
d2 = {}
d3 = {}
d4 = {}
d5 = {}
d1 = {1:2,3:4,5:6}
d2 = {2:3,4:5,6:7}
d3 = {3:4,5:6,7:8}
d4 = {4:5,6:7,8:9}
d5 = {6:7,8:9,10:11}
d1 = {}
d2 = {}
d3 = {}
d4 = {}
d5 = {}
d1 = {1:2,3:4,5:6}
d2 = {2:3,4:5,6:7}
d3 = {3:4,5:6,7:8}
d4 = {4:5,6:7,8:9}
d5 = {6:7,8:9,10:11}
d1 = {}
d2 = {}
d3 = {}
d4 = {}
d5 = {}
d1 = {1:2,3:4,5:6}
d2 = {2:3,4:5,6:7}
d3 = {3:4,5:6,7:8}
d4 = {4:5,6:7,8:9}
d5 = {6:7,8:9,10:11}
def calibrate(self):
for i in xrange(self.rounds):
pass
class DictWithStringKeys(Test):
version = 2.0
operations = 5*(6 + 6)
rounds = 200000
def test(self):
d = {}
for i in xrange(self.rounds):
d['abc'] = 1
d['def'] = 2
d['ghi'] = 3
d['jkl'] = 4
d['mno'] = 5
d['pqr'] = 6
d['abc']
d['def']
d['ghi']
d['jkl']
d['mno']
d['pqr']
d['abc'] = 1
d['def'] = 2
d['ghi'] = 3
d['jkl'] = 4
d['mno'] = 5
d['pqr'] = 6
d['abc']
d['def']
d['ghi']
d['jkl']
d['mno']
d['pqr']
d['abc'] = 1
d['def'] = 2
d['ghi'] = 3
d['jkl'] = 4
d['mno'] = 5
d['pqr'] = 6
d['abc']
d['def']
d['ghi']
d['jkl']
d['mno']
d['pqr']
d['abc'] = 1
d['def'] = 2
d['ghi'] = 3
d['jkl'] = 4
d['mno'] = 5
d['pqr'] = 6
d['abc']
d['def']
d['ghi']
d['jkl']
d['mno']
d['pqr']
d['abc'] = 1
d['def'] = 2
d['ghi'] = 3
d['jkl'] = 4
d['mno'] = 5
d['pqr'] = 6
d['abc']
d['def']
d['ghi']
d['jkl']
d['mno']
d['pqr']
def calibrate(self):
d = {}
for i in xrange(self.rounds):
pass
class DictWithFloatKeys(Test):
version = 2.0
operations = 5*(6 + 6)
rounds = 150000
def test(self):
d = {}
for i in xrange(self.rounds):
d[1.234] = 1
d[2.345] = 2
d[3.456] = 3
d[4.567] = 4
d[5.678] = 5
d[6.789] = 6
d[1.234]
d[2.345]
d[3.456]
d[4.567]
d[5.678]
d[6.789]
d[1.234] = 1
d[2.345] = 2
d[3.456] = 3
d[4.567] = 4
d[5.678] = 5
d[6.789] = 6
d[1.234]
d[2.345]
d[3.456]
d[4.567]
d[5.678]
d[6.789]
d[1.234] = 1
d[2.345] = 2
d[3.456] = 3
d[4.567] = 4
d[5.678] = 5
d[6.789] = 6
d[1.234]
d[2.345]
d[3.456]
d[4.567]
d[5.678]
d[6.789]
d[1.234] = 1
d[2.345] = 2
d[3.456] = 3
d[4.567] = 4
d[5.678] = 5
d[6.789] = 6
d[1.234]
d[2.345]
d[3.456]
d[4.567]
d[5.678]
d[6.789]
d[1.234] = 1
d[2.345] = 2
d[3.456] = 3
d[4.567] = 4
d[5.678] = 5
d[6.789] = 6
d[1.234]
d[2.345]
d[3.456]
d[4.567]
d[5.678]
d[6.789]
def calibrate(self):
d = {}
for i in xrange(self.rounds):
pass
class DictWithIntegerKeys(Test):
version = 2.0
operations = 5*(6 + 6)
rounds = 200000
def test(self):
d = {}
for i in xrange(self.rounds):
d[1] = 1
d[2] = 2
d[3] = 3
d[4] = 4
d[5] = 5
d[6] = 6
d[1]
d[2]
d[3]
d[4]
d[5]
d[6]
d[1] = 1
d[2] = 2
d[3] = 3
d[4] = 4
d[5] = 5
d[6] = 6
d[1]
d[2]
d[3]
d[4]
d[5]
d[6]
d[1] = 1
d[2] = 2
d[3] = 3
d[4] = 4
d[5] = 5
d[6] = 6
d[1]
d[2]
d[3]
d[4]
d[5]
d[6]
d[1] = 1
d[2] = 2
d[3] = 3
d[4] = 4
d[5] = 5
d[6] = 6
d[1]
d[2]
d[3]
d[4]
d[5]
d[6]
d[1] = 1
d[2] = 2
d[3] = 3
d[4] = 4
d[5] = 5
d[6] = 6
d[1]
d[2]
d[3]
d[4]
d[5]
d[6]
def calibrate(self):
d = {}
for i in xrange(self.rounds):
pass
class SimpleDictManipulation(Test):
version = 2.0
operations = 5*(6 + 6 + 6 + 6)
rounds = 100000
def test(self):
d = {}
has_key = d.has_key
for i in xrange(self.rounds):
d[0] = 3
d[1] = 4
d[2] = 5
d[3] = 3
d[4] = 4
d[5] = 5
x = d[0]
x = d[1]
x = d[2]
x = d[3]
x = d[4]
x = d[5]
has_key(0)
has_key(2)
has_key(4)
has_key(6)
has_key(8)
has_key(10)
del d[0]
del d[1]
del d[2]
del d[3]
del d[4]
del d[5]
d[0] = 3
d[1] = 4
d[2] = 5
d[3] = 3
d[4] = 4
d[5] = 5
x = d[0]
x = d[1]
x = d[2]
x = d[3]
x = d[4]
x = d[5]
has_key(0)
has_key(2)
has_key(4)
has_key(6)
has_key(8)
has_key(10)
del d[0]
del d[1]
del d[2]
del d[3]
del d[4]
del d[5]
d[0] = 3
d[1] = 4
d[2] = 5
d[3] = 3
d[4] = 4
d[5] = 5
x = d[0]
x = d[1]
x = d[2]
x = d[3]
x = d[4]
x = d[5]
has_key(0)
has_key(2)
has_key(4)
has_key(6)
has_key(8)
has_key(10)
del d[0]
del d[1]
del d[2]
del d[3]
del d[4]
del d[5]
d[0] = 3
d[1] = 4
d[2] = 5
d[3] = 3
d[4] = 4
d[5] = 5
x = d[0]
x = d[1]
x = d[2]
x = d[3]
x = d[4]
x = d[5]
has_key(0)
has_key(2)
has_key(4)
has_key(6)
has_key(8)
has_key(10)
del d[0]
del d[1]
del d[2]
del d[3]
del d[4]
del d[5]
d[0] = 3
d[1] = 4
d[2] = 5
d[3] = 3
d[4] = 4
d[5] = 5
x = d[0]
x = d[1]
x = d[2]
x = d[3]
x = d[4]
x = d[5]
has_key(0)
has_key(2)
has_key(4)
has_key(6)
has_key(8)
has_key(10)
del d[0]
del d[1]
del d[2]
del d[3]
del d[4]
del d[5]
def calibrate(self):
d = {}
has_key = d.has_key
for i in xrange(self.rounds):
pass
from pybench import Test
class TryRaiseExcept(Test):
version = 2.0
operations = 2 + 3 + 3
rounds = 80000
def test(self):
error = ValueError
for i in xrange(self.rounds):
try:
raise error
except:
pass
try:
raise error
except:
pass
try:
raise error,"something"
except:
pass
try:
raise error,"something"
except:
pass
try:
raise error,"something"
except:
pass
try:
raise error("something")
except:
pass
try:
raise error("something")
except:
pass
try:
raise error("something")
except:
pass
def calibrate(self):
error = ValueError
for i in xrange(self.rounds):
pass
class TryExcept(Test):
version = 2.0
operations = 15 * 10
rounds = 150000
def test(self):
for i in xrange(self.rounds):
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
try:
pass
except:
pass
def calibrate(self):
for i in xrange(self.rounds):
pass
### Test to make Fredrik happy...
if __name__ == '__main__':
import timeit
timeit.TestClass = TryRaiseExcept
timeit.main(['-s', 'test = TestClass(); test.rounds = 1000',
'test.test()'])
from pybench import Test
# First imports:
import os
import package.submodule
class SecondImport(Test):
version = 2.0
operations = 5 * 5
rounds = 40000
def test(self):
for i in xrange(self.rounds):
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
import os
def calibrate(self):
for i in xrange(self.rounds):
pass
class SecondPackageImport(Test):
version = 2.0
operations = 5 * 5
rounds = 40000
def test(self):
for i in xrange(self.rounds):
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
import package
def calibrate(self):
for i in xrange(self.rounds):
pass
class SecondSubmoduleImport(Test):
version = 2.0
operations = 5 * 5
rounds = 40000
def test(self):
for i in xrange(self.rounds):
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
import package.submodule
def calibrate(self):
for i in xrange(self.rounds):
pass
from pybench import Test
class CreateInstances(Test):
version = 2.0
operations = 3 + 7 + 4
rounds = 80000
def test(self):
class c:
pass
class d:
def __init__(self,a,b,c):
self.a = a
self.b = b
self.c = c
class e:
def __init__(self,a,b,c=4):
self.a = a
self.b = b
self.c = c
self.d = a
self.e = b
self.f = c
for i in xrange(self.rounds):
o = c()
o1 = c()
o2 = c()
p = d(i,i,3)
p1 = d(i,i,3)
p2 = d(i,3,3)
p3 = d(3,i,3)
p4 = d(i,i,i)
p5 = d(3,i,3)
p6 = d(i,i,i)
q = e(i,i,3)
q1 = e(i,i,3)
q2 = e(i,i,3)
q3 = e(i,i)
def calibrate(self):
class c:
pass
class d:
def __init__(self,a,b,c):
self.a = a
self.b = b
self.c = c
class e:
def __init__(self,a,b,c=4):
self.a = a
self.b = b
self.c = c
self.d = a
self.e = b
self.f = c
for i in xrange(self.rounds):
pass
pybench License
---------------
This copyright notice and license applies to all files in the pybench
directory of the pybench distribution.
Copyright (c), 1997-2006, Marc-Andre Lemburg (mal@lemburg.com)
Copyright (c), 2000-2006, eGenix.com Software GmbH (info@egenix.com)
All Rights Reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee or royalty is hereby
granted, provided that the above copyright notice appear in all copies
and that both that copyright notice and this permission notice appear
in supporting documentation or portions thereof, including
modifications, that you make.
THE AUTHOR MARC-ANDRE LEMBURG DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE !
from pybench import Test
class SimpleListManipulation(Test):
version = 2.0
operations = 5* (6 + 6 + 6)
rounds = 130000
def test(self):
l = []
append = l.append
for i in xrange(self.rounds):
append(2)
append(3)
append(4)
append(2)
append(3)
append(4)
l[0] = 3
l[1] = 4
l[2] = 5
l[3] = 3
l[4] = 4
l[5] = 5
x = l[0]
x = l[1]
x = l[2]
x = l[3]
x = l[4]
x = l[5]
append(2)
append(3)
append(4)
append(2)
append(3)
append(4)
l[0] = 3
l[1] = 4
l[2] = 5
l[3] = 3
l[4] = 4
l[5] = 5
x = l[0]
x = l[1]
x = l[2]
x = l[3]
x = l[4]
x = l[5]
append(2)
append(3)
append(4)
append(2)
append(3)
append(4)
l[0] = 3
l[1] = 4
l[2] = 5
l[3] = 3
l[4] = 4
l[5] = 5
x = l[0]
x = l[1]
x = l[2]
x = l[3]
x = l[4]
x = l[5]
append(2)
append(3)
append(4)
append(2)
append(3)
append(4)
l[0] = 3
l[1] = 4
l[2] = 5
l[3] = 3
l[4] = 4
l[5] = 5
x = l[0]
x = l[1]
x = l[2]
x = l[3]
x = l[4]
x = l[5]
append(2)
append(3)
append(4)
append(2)
append(3)
append(4)
l[0] = 3
l[1] = 4
l[2] = 5
l[3] = 3
l[4] = 4
l[5] = 5
x = l[0]
x = l[1]
x = l[2]
x = l[3]
x = l[4]
x = l[5]
if len(l) > 10000:
# cut down the size
del l[:]
def calibrate(self):
l = []
append = l.append
for i in xrange(self.rounds):
pass
class ListSlicing(Test):
version = 2.0
operations = 25*(3+1+2+1)
rounds = 800
def test(self):
n = range(100)
r = range(25)
for i in xrange(self.rounds):
l = n[:]
for j in r:
m = l[50:]
m = l[:25]
m = l[50:55]
l[:3] = n
m = l[:-1]
m = l[1:]
l[-1:] = n
def calibrate(self):
n = range(100)
r = range(25)
for i in xrange(self.rounds):
for j in r:
pass
class SmallLists(Test):
version = 2.0
operations = 5*(1+ 6 + 6 + 3 + 1)
rounds = 80000
def test(self):
for i in xrange(self.rounds):
l = []
append = l.append
append(2)
append(3)
append(4)
append(2)
append(3)
append(4)
l[0] = 3
l[1] = 4
l[2] = 5
l[3] = 3
l[4] = 4
l[5] = 5
l[:3] = [1,2,3]
m = l[:-1]
m = l[1:]
l[-1:] = [4,5,6]
l = []
append = l.append
append(2)
append(3)
append(4)
append(2)
append(3)
append(4)
l[0] = 3
l[1] = 4
l[2] = 5
l[3] = 3
l[4] = 4
l[5] = 5
l[:3] = [1,2,3]
m = l[:-1]
m = l[1:]
l[-1:] = [4,5,6]
l = []
append = l.append
append(2)
append(3)
append(4)
append(2)
append(3)
append(4)
l[0] = 3
l[1] = 4
l[2] = 5
l[3] = 3
l[4] = 4
l[5] = 5
l[:3] = [1,2,3]
m = l[:-1]
m = l[1:]
l[-1:] = [4,5,6]
l = []
append = l.append
append(2)
append(3)
append(4)
append(2)
append(3)
append(4)
l[0] = 3
l[1] = 4
l[2] = 5
l[3] = 3
l[4] = 4
l[5] = 5
l[:3] = [1,2,3]
m = l[:-1]
m = l[1:]
l[-1:] = [4,5,6]
l = []
append = l.append
append(2)
append(3)
append(4)
append(2)
append(3)
append(4)
l[0] = 3
l[1] = 4
l[2] = 5
l[3] = 3
l[4] = 4
l[5] = 5
l[:3] = [1,2,3]
m = l[:-1]
m = l[1:]
l[-1:] = [4,5,6]
def calibrate(self):
for i in xrange(self.rounds):
pass
from pybench import Test
class SpecialClassAttribute(Test):
version = 2.0
operations = 5*(12 + 12)
rounds = 100000
def test(self):
class c:
pass
for i in xrange(self.rounds):
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
c.__a = 2
c.__b = 3
c.__c = 4
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
x = c.__a
x = c.__b
x = c.__c
def calibrate(self):
class c:
pass
for i in xrange(self.rounds):
pass
class NormalClassAttribute(Test):
version = 2.0
operations = 5*(12 + 12)
rounds = 100000
def test(self):
class c:
pass
for i in xrange(self.rounds):
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
c.a = 2
c.b = 3
c.c = 4
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
x = c.a
x = c.b
x = c.c
def calibrate(self):
class c:
pass
for i in xrange(self.rounds):
pass
class SpecialInstanceAttribute(Test):
version = 2.0
operations = 5*(12 + 12)
rounds = 100000
def test(self):
class c:
pass
o = c()
for i in xrange(self.rounds):
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
o.__a__ = 2
o.__b__ = 3
o.__c__ = 4
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
x = o.__a__
x = o.__b__
x = o.__c__
def calibrate(self):
class c:
pass
o = c()
for i in xrange(self.rounds):
pass
class NormalInstanceAttribute(Test):
version = 2.0
operations = 5*(12 + 12)
rounds = 100000
def test(self):
class c:
pass
o = c()
for i in xrange(self.rounds):
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
o.a = 2
o.b = 3
o.c = 4
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
x = o.a
x = o.b
x = o.c
def calibrate(self):
class c:
pass
o = c()
for i in xrange(self.rounds):
pass
class BuiltinMethodLookup(Test):
version = 2.0
operations = 5*(3*5 + 3*5)
rounds = 70000
def test(self):
l = []
d = {}
for i in xrange(self.rounds):
l.append
l.append
l.append
l.append
l.append
l.insert
l.insert
l.insert
l.insert
l.insert
l.sort
l.sort
l.sort
l.sort
l.sort
d.has_key
d.has_key
d.has_key
d.has_key
d.has_key
d.items
d.items
d.items
d.items
d.items
d.get
d.get
d.get
d.get
d.get
l.append
l.append
l.append
l.append
l.append
l.insert
l.insert
l.insert
l.insert
l.insert
l.sort
l.sort
l.sort
l.sort
l.sort
d.has_key
d.has_key
d.has_key
d.has_key
d.has_key
d.items
d.items
d.items
d.items
d.items
d.get
d.get
d.get
d.get
d.get
l.append
l.append
l.append
l.append
l.append
l.insert
l.insert
l.insert
l.insert
l.insert
l.sort
l.sort
l.sort
l.sort
l.sort
d.has_key
d.has_key
d.has_key
d.has_key
d.has_key
d.items
d.items
d.items
d.items
d.items
d.get
d.get
d.get
d.get
d.get
l.append
l.append
l.append
l.append
l.append
l.insert
l.insert
l.insert
l.insert
l.insert
l.sort
l.sort
l.sort
l.sort
l.sort
d.has_key
d.has_key
d.has_key
d.has_key
d.has_key
d.items
d.items
d.items
d.items
d.items
d.get
d.get
d.get
d.get
d.get
l.append
l.append
l.append
l.append
l.append
l.insert
l.insert
l.insert
l.insert
l.insert
l.sort
l.sort
l.sort
l.sort
l.sort
d.has_key
d.has_key
d.has_key
d.has_key
d.has_key
d.items
d.items
d.items
d.items
d.items
d.get
d.get
d.get
d.get
d.get
def calibrate(self):
l = []
d = {}
for i in xrange(self.rounds):
pass
from pybench import Test
# Check for new-style class support:
try:
class c(object):
pass
except NameError:
raise ImportError
###
class CreateNewInstances(Test):
version = 2.0
operations = 3 + 7 + 4
rounds = 60000
def test(self):
class c(object):
pass
class d(object):
def __init__(self,a,b,c):
self.a = a
self.b = b
self.c = c
class e(object):
def __init__(self,a,b,c=4):
self.a = a
self.b = b
self.c = c
self.d = a
self.e = b
self.f = c
for i in xrange(self.rounds):
o = c()
o1 = c()
o2 = c()
p = d(i,i,3)
p1 = d(i,i,3)
p2 = d(i,3,3)
p3 = d(3,i,3)
p4 = d(i,i,i)
p5 = d(3,i,3)
p6 = d(i,i,i)
q = e(i,i,3)
q1 = e(i,i,3)
q2 = e(i,i,3)
q3 = e(i,i)
def calibrate(self):
class c(object):
pass
class d(object):
def __init__(self,a,b,c):
self.a = a
self.b = b
self.c = c
class e(object):
def __init__(self,a,b,c=4):
self.a = a
self.b = b
self.c = c
self.d = a
self.e = b
self.f = c
for i in xrange(self.rounds):
pass
from pybench import Test
class CompareIntegers(Test):
version = 2.0
operations = 30 * 5
rounds = 120000
def test(self):
for i in xrange(self.rounds):
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
2 < 3
2 > 3
2 == 3
2 > 3
2 < 3
def calibrate(self):
for i in xrange(self.rounds):
pass
class CompareFloats(Test):
version = 2.0
operations = 30 * 5
rounds = 80000
def test(self):
for i in xrange(self.rounds):
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
2.1 < 3.31
2.1 > 3.31
2.1 == 3.31
2.1 > 3.31
2.1 < 3.31
def calibrate(self):
for i in xrange(self.rounds):
pass
class CompareFloatsIntegers(Test):
version = 2.0
operations = 30 * 5
rounds = 60000
def test(self):
for i in xrange(self.rounds):
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
2.1 < 4
2.1 > 4
2.1 == 4
2.1 > 4
2.1 < 4
def calibrate(self):
for i in xrange(self.rounds):
pass
class CompareLongs(Test):
version = 2.0
operations = 30 * 5
rounds = 70000
def test(self):
for i in xrange(self.rounds):
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
1234567890L < 3456789012345L
1234567890L > 3456789012345L
1234567890L == 3456789012345L
1234567890L > 3456789012345L
1234567890L < 3456789012345L
def calibrate(self):
for i in xrange(self.rounds):
pass
________________________________________________________________________
PYBENCH - A Python Benchmark Suite
________________________________________________________________________
Extendable suite of of low-level benchmarks for measuring
the performance of the Python implementation
(interpreter, compiler or VM).
pybench is a collection of tests that provides a standardized way to
measure the performance of Python implementations. It takes a very
close look at different aspects of Python programs and let's you
decide which factors are more important to you than others, rather
than wrapping everything up in one number, like the other performance
tests do (e.g. pystone which is included in the Python Standard
Library).
pybench has been used in the past by several Python developers to
track down performance bottlenecks or to demonstrate the impact of
optimizations and new features in Python.
The command line interface for pybench is the file pybench.py. Run
this script with option '--help' to get a listing of the possible
options. Without options, pybench will simply execute the benchmark
and then print out a report to stdout.
Micro-Manual
------------
Run 'pybench.py -h' to see the help screen. Run 'pybench.py' to run
the benchmark suite using default settings and 'pybench.py -f <file>'
to have it store the results in a file too.
It is usually a good idea to run pybench.py multiple times to see
whether the environment, timers and benchmark run-times are suitable
for doing benchmark tests.
You can use the comparison feature of pybench.py ('pybench.py -c
<file>') to check how well the system behaves in comparison to a
reference run.
If the differences are well below 10% for each test, then you have a
system that is good for doing benchmark testings. Of you get random
differences of more than 10% or significant differences between the
values for minimum and average time, then you likely have some
background processes running which cause the readings to become
inconsistent. Examples include: web-browsers, email clients, RSS
readers, music players, backup programs, etc.
If you are only interested in a few tests of the whole suite, you can
use the filtering option, e.g. 'pybench.py -t string' will only
run/show the tests that have 'string' in their name.
This is the current output of pybench.py --help:
"""
------------------------------------------------------------------------
PYBENCH - a benchmark test suite for Python interpreters/compilers.
------------------------------------------------------------------------
Synopsis:
pybench.py [option] files...
Options and default settings:
-n arg number of rounds (10)
-f arg save benchmark to file arg ()
-c arg compare benchmark with the one in file arg ()
-s arg show benchmark in file arg, then exit ()
-w arg set warp factor to arg (10)
-t arg run only tests with names matching arg ()
-C arg set the number of calibration runs to arg (20)
-d hide noise in comparisons (0)
-v verbose output (not recommended) (0)
--with-gc enable garbage collection (0)
--with-syscheck use default sys check interval (0)
--timer arg use given timer (time.time)
-h show this help text
--help show this help text
--debug enable debugging
--copyright show copyright
--examples show examples of usage
Version:
2.0
The normal operation is to run the suite and display the
results. Use -f to save them for later reuse or comparisons.
Available timers:
time.time
time.clock
systimes.processtime
Examples:
python2.1 pybench.py -f p21.pybench
python2.5 pybench.py -f p25.pybench
python pybench.py -s p25.pybench -c p21.pybench
"""
License
-------
See LICENSE file.
Sample output
-------------
"""
-------------------------------------------------------------------------------
PYBENCH 2.0
-------------------------------------------------------------------------------
* using Python 2.4.2
* disabled garbage collection
* system check interval set to maximum: 2147483647
* using timer: time.time
Calibrating tests. Please wait...
Running 10 round(s) of the suite at warp factor 10:
* Round 1 done in 6.388 seconds.
* Round 2 done in 6.485 seconds.
* Round 3 done in 6.786 seconds.
...
* Round 10 done in 6.546 seconds.
-------------------------------------------------------------------------------
Benchmark: 2006-06-12 12:09:25
-------------------------------------------------------------------------------
Rounds: 10
Warp: 10
Timer: time.time
Machine Details:
Platform ID: Linux-2.6.8-24.19-default-x86_64-with-SuSE-9.2-x86-64
Processor: x86_64
Python:
Executable: /usr/local/bin/python
Version: 2.4.2
Compiler: GCC 3.3.4 (pre 3.3.5 20040809)
Bits: 64bit
Build: Oct 1 2005 15:24:35 (#1)
Unicode: UCS2
Test minimum average operation overhead
-------------------------------------------------------------------------------
BuiltinFunctionCalls: 126ms 145ms 0.28us 0.274ms
BuiltinMethodLookup: 124ms 130ms 0.12us 0.316ms
CompareFloats: 109ms 110ms 0.09us 0.361ms
CompareFloatsIntegers: 100ms 104ms 0.12us 0.271ms
CompareIntegers: 137ms 138ms 0.08us 0.542ms
CompareInternedStrings: 124ms 127ms 0.08us 1.367ms
CompareLongs: 100ms 104ms 0.10us 0.316ms
CompareStrings: 111ms 115ms 0.12us 0.929ms
CompareUnicode: 108ms 128ms 0.17us 0.693ms
ConcatStrings: 142ms 155ms 0.31us 0.562ms
ConcatUnicode: 119ms 127ms 0.42us 0.384ms
CreateInstances: 123ms 128ms 1.14us 0.367ms
CreateNewInstances: 121ms 126ms 1.49us 0.335ms
CreateStringsWithConcat: 130ms 135ms 0.14us 0.916ms
CreateUnicodeWithConcat: 130ms 135ms 0.34us 0.361ms
DictCreation: 108ms 109ms 0.27us 0.361ms
DictWithFloatKeys: 149ms 153ms 0.17us 0.678ms
DictWithIntegerKeys: 124ms 126ms 0.11us 0.915ms
DictWithStringKeys: 114ms 117ms 0.10us 0.905ms
ForLoops: 110ms 111ms 4.46us 0.063ms
IfThenElse: 118ms 119ms 0.09us 0.685ms
ListSlicing: 116ms 120ms 8.59us 0.103ms
NestedForLoops: 125ms 137ms 0.09us 0.019ms
NormalClassAttribute: 124ms 136ms 0.11us 0.457ms
NormalInstanceAttribute: 110ms 117ms 0.10us 0.454ms
PythonFunctionCalls: 107ms 113ms 0.34us 0.271ms
PythonMethodCalls: 140ms 149ms 0.66us 0.141ms
Recursion: 156ms 166ms 3.32us 0.452ms
SecondImport: 112ms 118ms 1.18us 0.180ms
SecondPackageImport: 118ms 127ms 1.27us 0.180ms
SecondSubmoduleImport: 140ms 151ms 1.51us 0.180ms
SimpleComplexArithmetic: 128ms 139ms 0.16us 0.361ms
SimpleDictManipulation: 134ms 136ms 0.11us 0.452ms
SimpleFloatArithmetic: 110ms 113ms 0.09us 0.571ms
SimpleIntFloatArithmetic: 106ms 111ms 0.08us 0.548ms
SimpleIntegerArithmetic: 106ms 109ms 0.08us 0.544ms
SimpleListManipulation: 103ms 113ms 0.10us 0.587ms
SimpleLongArithmetic: 112ms 118ms 0.18us 0.271ms
SmallLists: 105ms 116ms 0.17us 0.366ms
SmallTuples: 108ms 128ms 0.24us 0.406ms
SpecialClassAttribute: 119ms 136ms 0.11us 0.453ms
SpecialInstanceAttribute: 143ms 155ms 0.13us 0.454ms
StringMappings: 115ms 121ms 0.48us 0.405ms
StringPredicates: 120ms 129ms 0.18us 2.064ms
StringSlicing: 111ms 127ms 0.23us 0.781ms
TryExcept: 125ms 126ms 0.06us 0.681ms
TryRaiseExcept: 133ms 137ms 2.14us 0.361ms
TupleSlicing: 117ms 120ms 0.46us 0.066ms
UnicodeMappings: 156ms 160ms 4.44us 0.429ms
UnicodePredicates: 117ms 121ms 0.22us 2.487ms
UnicodeProperties: 115ms 153ms 0.38us 2.070ms
UnicodeSlicing: 126ms 129ms 0.26us 0.689ms
-------------------------------------------------------------------------------
Totals: 6283ms 6673ms
"""
________________________________________________________________________
Writing New Tests
________________________________________________________________________
pybench tests are simple modules defining one or more pybench.Test
subclasses.
Writing a test essentially boils down to providing two methods:
.test() which runs .rounds number of .operations test operations each
and .calibrate() which does the same except that it doesn't actually
execute the operations.
Here's an example:
------------------
from pybench import Test
class IntegerCounting(Test):
# Version number of the test as float (x.yy); this is important
# for comparisons of benchmark runs - tests with unequal version
# number will not get compared.
version = 1.0
# The number of abstract operations done in each round of the
# test. An operation is the basic unit of what you want to
# measure. The benchmark will output the amount of run-time per
# operation. Note that in order to raise the measured timings
# significantly above noise level, it is often required to repeat
# sets of operations more than once per test round. The measured
# overhead per test round should be less than 1 second.
operations = 20
# Number of rounds to execute per test run. This should be
# adjusted to a figure that results in a test run-time of between
# 1-2 seconds (at warp 1).
rounds = 100000
def test(self):
""" Run the test.
The test needs to run self.rounds executing
self.operations number of operations each.
"""
# Init the test
a = 1
# Run test rounds
#
# NOTE: Use xrange() for all test loops unless you want to face
# a 20MB process !
#
for i in xrange(self.rounds):
# Repeat the operations per round to raise the run-time
# per operation significantly above the noise level of the
# for-loop overhead.
# Execute 20 operations (a += 1):
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
a += 1
def calibrate(self):
""" Calibrate the test.
This method should execute everything that is needed to
setup and run the test - except for the actual operations
that you intend to measure. pybench uses this method to
measure the test implementation overhead.
"""
# Init the test
a = 1
# Run test rounds (without actually doing any operation)
for i in xrange(self.rounds):
# Skip the actual execution of the operations, since we
# only want to measure the test's administration overhead.
pass
Registering a new test module
-----------------------------
To register a test module with pybench, the classes need to be
imported into the pybench.Setup module. pybench will then scan all the
symbols defined in that module for subclasses of pybench.Test and
automatically add them to the benchmark suite.
Breaking Comparability
----------------------
If a change is made to any individual test that means it is no
longer strictly comparable with previous runs, the '.version' class
variable should be updated. Therefafter, comparisons with previous
versions of the test will list as "n/a" to reflect the change.
Version History
---------------
2.0: rewrote parts of pybench which resulted in more repeatable
timings:
- made timer a parameter
- changed the platform default timer to use high-resolution
timers rather than process timers (which have a much lower
resolution)
- added option to select timer
- added process time timer (using systimes.py)
- changed to use min() as timing estimator (average
is still taken as well to provide an idea of the difference)
- garbage collection is turned off per default
- sys check interval is set to the highest possible value
- calibration is now a separate step and done using
a different strategy that allows measuring the test
overhead more accurately
- modified the tests to each give a run-time of between
100-200ms using warp 10
- changed default warp factor to 10 (from 20)
- compared results with timeit.py and confirmed measurements
- bumped all test versions to 2.0
- updated platform.py to the latest version
- changed the output format a bit to make it look
nicer
- refactored the APIs somewhat
1.3+: Steve Holden added the NewInstances test and the filtering
option during the NeedForSpeed sprint; this also triggered a long
discussion on how to improve benchmark timing and finally
resulted in the release of 2.0
1.3: initial checkin into the Python SVN repository
Have fun,
--
Marc-Andre Lemburg
mal@lemburg.com
#!python
# Setup file for pybench
#
# This file has to import all tests to be run; it is executed as
# Python source file, so you can do all kinds of manipulations here
# rather than having to edit the tests themselves.
#
# Note: Please keep this module compatible to Python 1.5.2.
#
# Tests may include features in later Python versions, but these
# should then be embedded in try-except clauses in this configuration
# module.
# Defaults
Number_of_rounds = 10
Warp_factor = 10
# Import tests
from Arithmetic import *
from Calls import *
from Constructs import *
from Lookups import *
from Instances import *
try:
from NewInstances import *
except ImportError:
pass
from Lists import *
from Tuples import *
from Dict import *
from Exceptions import *
from Imports import *
from Strings import *
from Numbers import *
try:
from Unicode import *
except (ImportError, SyntaxError):
pass
from pybench import Test
from string import join
class ConcatStrings(Test):
version = 2.0
operations = 10 * 5
rounds = 100000
def test(self):
# Make sure the strings are *not* interned
s = join(map(str,range(100)))
t = join(map(str,range(1,101)))
for i in xrange(self.rounds):
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
def calibrate(self):
s = join(map(str,range(100)))
t = join(map(str,range(1,101)))
for i in xrange(self.rounds):
pass
class CompareStrings(Test):
version = 2.0
operations = 10 * 5
rounds = 200000
def test(self):
# Make sure the strings are *not* interned
s = join(map(str,range(10)))
t = join(map(str,range(10))) + "abc"
for i in xrange(self.rounds):
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
def calibrate(self):
s = join(map(str,range(10)))
t = join(map(str,range(10))) + "abc"
for i in xrange(self.rounds):
pass
class CompareInternedStrings(Test):
version = 2.0
operations = 10 * 5
rounds = 300000
def test(self):
# Make sure the strings *are* interned
s = intern(join(map(str,range(10))))
t = s
for i in xrange(self.rounds):
t == s
t == s
t >= s
t > s
t < s
t == s
t == s
t >= s
t > s
t < s
t == s
t == s
t >= s
t > s
t < s
t == s
t == s
t >= s
t > s
t < s
t == s
t == s
t >= s
t > s
t < s
t == s
t == s
t >= s
t > s
t < s
t == s
t == s
t >= s
t > s
t < s
t == s
t == s
t >= s
t > s
t < s
t == s
t == s
t >= s
t > s
t < s
t == s
t == s
t >= s
t > s
t < s
def calibrate(self):
s = intern(join(map(str,range(10))))
t = s
for i in xrange(self.rounds):
pass
class CreateStringsWithConcat(Test):
version = 2.0
operations = 10 * 5
rounds = 200000
def test(self):
for i in xrange(self.rounds):
s = 'om'
s = s + 'xbx'
s = s + 'xcx'
s = s + 'xdx'
s = s + 'xex'
s = s + 'xax'
s = s + 'xbx'
s = s + 'xcx'
s = s + 'xdx'
s = s + 'xex'
s = s + 'xax'
s = s + 'xbx'
s = s + 'xcx'
s = s + 'xdx'
s = s + 'xex'
s = s + 'xax'
s = s + 'xbx'
s = s + 'xcx'
s = s + 'xdx'
s = s + 'xex'
s = s + 'xax'
s = s + 'xbx'
s = s + 'xcx'
s = s + 'xdx'
s = s + 'xex'
s = s + 'xax'
s = s + 'xbx'
s = s + 'xcx'
s = s + 'xdx'
s = s + 'xex'
s = s + 'xax'
s = s + 'xbx'
s = s + 'xcx'
s = s + 'xdx'
s = s + 'xex'
s = s + 'xax'
s = s + 'xbx'
s = s + 'xcx'
s = s + 'xdx'
s = s + 'xex'
s = s + 'xax'
s = s + 'xbx'
s = s + 'xcx'
s = s + 'xdx'
s = s + 'xex'
s = s + 'xax'
s = s + 'xbx'
s = s + 'xcx'
s = s + 'xdx'
s = s + 'xex'
def calibrate(self):
for i in xrange(self.rounds):
pass
class StringSlicing(Test):
version = 2.0
operations = 5 * 7
rounds = 160000
def test(self):
s = join(map(str,range(100)))
for i in xrange(self.rounds):
s[50:]
s[:25]
s[50:55]
s[-1:]
s[:1]
s[2:]
s[11:-11]
s[50:]
s[:25]
s[50:55]
s[-1:]
s[:1]
s[2:]
s[11:-11]
s[50:]
s[:25]
s[50:55]
s[-1:]
s[:1]
s[2:]
s[11:-11]
s[50:]
s[:25]
s[50:55]
s[-1:]
s[:1]
s[2:]
s[11:-11]
s[50:]
s[:25]
s[50:55]
s[-1:]
s[:1]
s[2:]
s[11:-11]
def calibrate(self):
s = join(map(str,range(100)))
for i in xrange(self.rounds):
pass
### String methods
if hasattr('', 'lower'):
class StringMappings(Test):
version = 2.0
operations = 3 * (5 + 4 + 2 + 1)
rounds = 70000
def test(self):
s = join(map(chr,range(20)),'')
t = join(map(chr,range(50)),'')
u = join(map(chr,range(100)),'')
v = join(map(chr,range(256)),'')
for i in xrange(self.rounds):
s.lower()
s.lower()
s.lower()
s.lower()
s.lower()
s.upper()
s.upper()
s.upper()
s.upper()
s.upper()
s.title()
s.title()
s.title()
s.title()
s.title()
t.lower()
t.lower()
t.lower()
t.lower()
t.upper()
t.upper()
t.upper()
t.upper()
t.title()
t.title()
t.title()
t.title()
u.lower()
u.lower()
u.upper()
u.upper()
u.title()
u.title()
v.lower()
v.upper()
v.title()
def calibrate(self):
s = join(map(chr,range(20)),'')
t = join(map(chr,range(50)),'')
u = join(map(chr,range(100)),'')
v = join(map(chr,range(256)),'')
for i in xrange(self.rounds):
pass
class StringPredicates(Test):
version = 2.0
operations = 10 * 7
rounds = 100000
def test(self):
data = ('abc', '123', ' ', '\xe4\xf6\xfc', '\xdf'*10)
len_data = len(data)
for i in xrange(self.rounds):
s = data[i % len_data]
s.isalnum()
s.isalpha()
s.isdigit()
s.islower()
s.isspace()
s.istitle()
s.isupper()
s.isalnum()
s.isalpha()
s.isdigit()
s.islower()
s.isspace()
s.istitle()
s.isupper()
s.isalnum()
s.isalpha()
s.isdigit()
s.islower()
s.isspace()
s.istitle()
s.isupper()
s.isalnum()
s.isalpha()
s.isdigit()
s.islower()
s.isspace()
s.istitle()
s.isupper()
s.isalnum()
s.isalpha()
s.isdigit()
s.islower()
s.isspace()
s.istitle()
s.isupper()
s.isalnum()
s.isalpha()
s.isdigit()
s.islower()
s.isspace()
s.istitle()
s.isupper()
s.isalnum()
s.isalpha()
s.isdigit()
s.islower()
s.isspace()
s.istitle()
s.isupper()
s.isalnum()
s.isalpha()
s.isdigit()
s.islower()
s.isspace()
s.istitle()
s.isupper()
s.isalnum()
s.isalpha()
s.isdigit()
s.islower()
s.isspace()
s.istitle()
s.isupper()
s.isalnum()
s.isalpha()
s.isdigit()
s.islower()
s.isspace()
s.istitle()
s.isupper()
def calibrate(self):
data = ('abc', '123', ' ', '\u1234\u2345\u3456', '\uFFFF'*10)
data = ('abc', '123', ' ', '\xe4\xf6\xfc', '\xdf'*10)
len_data = len(data)
for i in xrange(self.rounds):
s = data[i % len_data]
from pybench import Test
class TupleSlicing(Test):
version = 2.0
operations = 3 * 25 * 10 * 7
rounds = 500
def test(self):
r = range(25)
t = tuple(range(100))
for i in xrange(self.rounds):
for j in r:
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
m = t[50:]
m = t[:25]
m = t[50:55]
m = t[:-1]
m = t[1:]
m = t[-10:]
m = t[:10]
def calibrate(self):
r = range(25)
t = tuple(range(100))
for i in xrange(self.rounds):
for j in r:
pass
class SmallTuples(Test):
version = 2.0
operations = 5*(1 + 3 + 6 + 2)
rounds = 90000
def test(self):
for i in xrange(self.rounds):
t = (1,2,3,4,5,6)
a,b,c,d,e,f = t
a,b,c,d,e,f = t
a,b,c,d,e,f = t
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
l = list(t)
t = tuple(l)
t = (1,2,3,4,5,6)
a,b,c,d,e,f = t
a,b,c,d,e,f = t
a,b,c,d,e,f = t
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
l = list(t)
t = tuple(l)
t = (1,2,3,4,5,6)
a,b,c,d,e,f = t
a,b,c,d,e,f = t
a,b,c,d,e,f = t
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
l = list(t)
t = tuple(l)
t = (1,2,3,4,5,6)
a,b,c,d,e,f = t
a,b,c,d,e,f = t
a,b,c,d,e,f = t
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
l = list(t)
t = tuple(l)
t = (1,2,3,4,5,6)
a,b,c,d,e,f = t
a,b,c,d,e,f = t
a,b,c,d,e,f = t
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
a,b,c = t[:3]
l = list(t)
t = tuple(l)
def calibrate(self):
for i in xrange(self.rounds):
pass
try:
unicode
except NameError:
raise ImportError
from pybench import Test
from string import join
class ConcatUnicode(Test):
version = 2.0
operations = 10 * 5
rounds = 60000
def test(self):
# Make sure the strings are *not* interned
s = unicode(join(map(str,range(100))))
t = unicode(join(map(str,range(1,101))))
for i in xrange(self.rounds):
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
t + s
def calibrate(self):
s = unicode(join(map(str,range(100))))
t = unicode(join(map(str,range(1,101))))
for i in xrange(self.rounds):
pass
class CompareUnicode(Test):
version = 2.0
operations = 10 * 5
rounds = 150000
def test(self):
# Make sure the strings are *not* interned
s = unicode(join(map(str,range(10))))
t = unicode(join(map(str,range(10))) + "abc")
for i in xrange(self.rounds):
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
t < s
t > s
t == s
t > s
t < s
def calibrate(self):
s = unicode(join(map(str,range(10))))
t = unicode(join(map(str,range(10))) + "abc")
for i in xrange(self.rounds):
pass
class CreateUnicodeWithConcat(Test):
version = 2.0
operations = 10 * 5
rounds = 80000
def test(self):
for i in xrange(self.rounds):
s = u'om'
s = s + u'xbx'
s = s + u'xcx'
s = s + u'xdx'
s = s + u'xex'
s = s + u'xax'
s = s + u'xbx'
s = s + u'xcx'
s = s + u'xdx'
s = s + u'xex'
s = s + u'xax'
s = s + u'xbx'
s = s + u'xcx'
s = s + u'xdx'
s = s + u'xex'
s = s + u'xax'
s = s + u'xbx'
s = s + u'xcx'
s = s + u'xdx'
s = s + u'xex'
s = s + u'xax'
s = s + u'xbx'
s = s + u'xcx'
s = s + u'xdx'
s = s + u'xex'
s = s + u'xax'
s = s + u'xbx'
s = s + u'xcx'
s = s + u'xdx'
s = s + u'xex'
s = s + u'xax'
s = s + u'xbx'
s = s + u'xcx'
s = s + u'xdx'
s = s + u'xex'
s = s + u'xax'
s = s + u'xbx'
s = s + u'xcx'
s = s + u'xdx'
s = s + u'xex'
s = s + u'xax'
s = s + u'xbx'
s = s + u'xcx'
s = s + u'xdx'
s = s + u'xex'
s = s + u'xax'
s = s + u'xbx'
s = s + u'xcx'
s = s + u'xdx'
s = s + u'xex'
def calibrate(self):
for i in xrange(self.rounds):
pass
class UnicodeSlicing(Test):
version = 2.0
operations = 5 * 7
rounds = 140000
def test(self):
s = unicode(join(map(str,range(100))))
for i in xrange(self.rounds):
s[50:]
s[:25]
s[50:55]
s[-1:]
s[:1]
s[2:]
s[11:-11]
s[50:]
s[:25]
s[50:55]
s[-1:]
s[:1]
s[2:]
s[11:-11]
s[50:]
s[:25]
s[50:55]
s[-1:]
s[:1]
s[2:]
s[11:-11]
s[50:]
s[:25]
s[50:55]
s[-1:]
s[:1]
s[2:]
s[11:-11]
s[50:]
s[:25]
s[50:55]
s[-1:]
s[:1]
s[2:]
s[11:-11]
def calibrate(self):
s = unicode(join(map(str,range(100))))
for i in xrange(self.rounds):
pass
### String methods
class UnicodeMappings(Test):
version = 2.0
operations = 3 * (5 + 4 + 2 + 1)
rounds = 10000
def test(self):
s = join(map(unichr,range(20)),'')
t = join(map(unichr,range(100)),'')
u = join(map(unichr,range(500)),'')
v = join(map(unichr,range(1000)),'')
for i in xrange(self.rounds):
s.lower()
s.lower()
s.lower()
s.lower()
s.lower()
s.upper()
s.upper()
s.upper()
s.upper()
s.upper()
s.title()
s.title()
s.title()
s.title()
s.title()
t.lower()
t.lower()
t.lower()
t.lower()
t.upper()
t.upper()
t.upper()
t.upper()
t.title()
t.title()
t.title()
t.title()
u.lower()
u.lower()
u.upper()
u.upper()
u.title()
u.title()
v.lower()
v.upper()
v.title()
def calibrate(self):
s = join(map(unichr,range(20)),'')
t = join(map(unichr,range(100)),'')
u = join(map(unichr,range(500)),'')
v = join(map(unichr,range(1000)),'')
for i in xrange(self.rounds):
pass
class UnicodePredicates(Test):
version = 2.0
operations = 5 * 9
rounds = 120000
def test(self):
data = (u'abc', u'123', u' ', u'\u1234\u2345\u3456', u'\uFFFF'*10)
len_data = len(data)
for i in xrange(self.rounds):
s = data[i % len_data]
s.isalnum()
s.isalpha()
s.isdecimal()
s.isdigit()
s.islower()
s.isnumeric()
s.isspace()
s.istitle()
s.isupper()
s.isalnum()
s.isalpha()
s.isdecimal()
s.isdigit()
s.islower()
s.isnumeric()
s.isspace()
s.istitle()
s.isupper()
s.isalnum()
s.isalpha()
s.isdecimal()
s.isdigit()
s.islower()
s.isnumeric()
s.isspace()
s.istitle()
s.isupper()
s.isalnum()
s.isalpha()
s.isdecimal()
s.isdigit()
s.islower()
s.isnumeric()
s.isspace()
s.istitle()
s.isupper()
s.isalnum()
s.isalpha()
s.isdecimal()
s.isdigit()
s.islower()
s.isnumeric()
s.isspace()
s.istitle()
s.isupper()
def calibrate(self):
data = (u'abc', u'123', u' ', u'\u1234\u2345\u3456', u'\uFFFF'*10)
len_data = len(data)
for i in xrange(self.rounds):
s = data[i % len_data]
try:
import unicodedata
except ImportError:
pass
else:
class UnicodeProperties(Test):
version = 2.0
operations = 5 * 8
rounds = 100000
def test(self):
data = (u'a', u'1', u' ', u'\u1234', u'\uFFFF')
len_data = len(data)
digit = unicodedata.digit
numeric = unicodedata.numeric
decimal = unicodedata.decimal
category = unicodedata.category
bidirectional = unicodedata.bidirectional
decomposition = unicodedata.decomposition
mirrored = unicodedata.mirrored
combining = unicodedata.combining
for i in xrange(self.rounds):
c = data[i % len_data]
digit(c, None)
numeric(c, None)
decimal(c, None)
category(c)
bidirectional(c)
decomposition(c)
mirrored(c)
combining(c)
digit(c, None)
numeric(c, None)
decimal(c, None)
category(c)
bidirectional(c)
decomposition(c)
mirrored(c)
combining(c)
digit(c, None)
numeric(c, None)
decimal(c, None)
category(c)
bidirectional(c)
decomposition(c)
mirrored(c)
combining(c)
digit(c, None)
numeric(c, None)
decimal(c, None)
category(c)
bidirectional(c)
decomposition(c)
mirrored(c)
combining(c)
digit(c, None)
numeric(c, None)
decimal(c, None)
category(c)
bidirectional(c)
decomposition(c)
mirrored(c)
combining(c)
def calibrate(self):
data = (u'a', u'1', u' ', u'\u1234', u'\uFFFF')
len_data = len(data)
digit = unicodedata.digit
numeric = unicodedata.numeric
decimal = unicodedata.decimal
category = unicodedata.category
bidirectional = unicodedata.bidirectional
decomposition = unicodedata.decomposition
mirrored = unicodedata.mirrored
combining = unicodedata.combining
for i in xrange(self.rounds):
c = data[i % len_data]
#!/usr/bin/env python
""" clockres - calculates the resolution in seconds of a given timer.
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
TEST_TIME = 1.0
def clockres(timer):
d = {}
wallclock = time.time
start = wallclock()
stop = wallclock() + TEST_TIME
spin_loops = range(1000)
while 1:
now = wallclock()
if now >= stop:
break
for i in spin_loops:
d[timer()] = 1
values = d.keys()
values.sort()
min_diff = TEST_TIME
for i in range(len(values) - 1):
diff = values[i+1] - values[i]
if diff < min_diff:
min_diff = diff
return min_diff
if __name__ == '__main__':
print 'Clock resolution of various timer implementations:'
print 'time.clock: %10.3fus' % (clockres(time.clock) * 1e6)
print 'time.time: %10.3fus' % (clockres(time.time) * 1e6)
try:
import systimes
print 'systimes.processtime: %10.3fus' % (clockres(systimes.processtime) * 1e6)
except ImportError:
pass
#!/usr/bin/env python
""" This module tries to retrieve as much platform-identifying data as
possible. It makes this information available via function APIs.
If called from the command line, it prints the platform
information concatenated as single string to stdout. The output
format is useable as part of a filename.
"""
# This module is maintained by Marc-Andre Lemburg <mal@egenix.com>.
# If you find problems, please submit bug reports/patches via the
# Python SourceForge Project Page and assign them to "lemburg".
#
# Note: Please keep this module compatible to Python 1.5.2.
#
# Still needed:
# * more support for WinCE
# * support for MS-DOS (PythonDX ?)
# * support for Amiga and other still unsupported platforms running Python
# * support for additional Linux distributions
#
# Many thanks to all those who helped adding platform-specific
# checks (in no particular order):
#
# Charles G Waldman, David Arnold, Gordon McMillan, Ben Darnell,
# Jeff Bauer, Cliff Crawford, Ivan Van Laningham, Josef
# Betancourt, Randall Hopper, Karl Putland, John Farrell, Greg
# Andruk, Just van Rossum, Thomas Heller, Mark R. Levinson, Mark
# Hammond, Bill Tutt, Hans Nowak, Uwe Zessin (OpenVMS support),
# Colin Kong, Trent Mick, Guido van Rossum
#
# History:
#
# <see CVS and SVN checkin messages for history>
#
# 1.0.3 - added normalization of Windows system name
# 1.0.2 - added more Windows support
# 1.0.1 - reformatted to make doc.py happy
# 1.0.0 - reformatted a bit and checked into Python CVS
# 0.8.0 - added sys.version parser and various new access
# APIs (python_version(), python_compiler(), etc.)
# 0.7.2 - fixed architecture() to use sizeof(pointer) where available
# 0.7.1 - added support for Caldera OpenLinux
# 0.7.0 - some fixes for WinCE; untabified the source file
# 0.6.2 - support for OpenVMS - requires version 1.5.2-V006 or higher and
# vms_lib.getsyi() configured
# 0.6.1 - added code to prevent 'uname -p' on platforms which are
# known not to support it
# 0.6.0 - fixed win32_ver() to hopefully work on Win95,98,NT and Win2k;
# did some cleanup of the interfaces - some APIs have changed
# 0.5.5 - fixed another type in the MacOS code... should have
# used more coffee today ;-)
# 0.5.4 - fixed a few typos in the MacOS code
# 0.5.3 - added experimental MacOS support; added better popen()
# workarounds in _syscmd_ver() -- still not 100% elegant
# though
# 0.5.2 - fixed uname() to return '' instead of 'unknown' in all
# return values (the system uname command tends to return
# 'unknown' instead of just leaving the field emtpy)
# 0.5.1 - included code for slackware dist; added exception handlers
# to cover up situations where platforms don't have os.popen
# (e.g. Mac) or fail on socket.gethostname(); fixed libc
# detection RE
# 0.5.0 - changed the API names referring to system commands to *syscmd*;
# added java_ver(); made syscmd_ver() a private
# API (was system_ver() in previous versions) -- use uname()
# instead; extended the win32_ver() to also return processor
# type information
# 0.4.0 - added win32_ver() and modified the platform() output for WinXX
# 0.3.4 - fixed a bug in _follow_symlinks()
# 0.3.3 - fixed popen() and "file" command invokation bugs
# 0.3.2 - added architecture() API and support for it in platform()
# 0.3.1 - fixed syscmd_ver() RE to support Windows NT
# 0.3.0 - added system alias support
# 0.2.3 - removed 'wince' again... oh well.
# 0.2.2 - added 'wince' to syscmd_ver() supported platforms
# 0.2.1 - added cache logic and changed the platform string format
# 0.2.0 - changed the API to use functions instead of module globals
# since some action take too long to be run on module import
# 0.1.0 - first release
#
# You can always get the latest version of this module at:
#
# http://www.egenix.com/files/python/platform.py
#
# If that URL should fail, try contacting the author.
__copyright__ = """
Copyright (c) 1999-2000, Marc-Andre Lemburg; mailto:mal@lemburg.com
Copyright (c) 2000-2003, eGenix.com Software GmbH; mailto:info@egenix.com
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee or royalty is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation or portions thereof, including modifications,
that you make.
EGENIX.COM SOFTWARE GMBH DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE !
"""
__version__ = '1.0.4'
import sys,string,os,re
### Platform specific APIs
_libc_search = re.compile(r'(__libc_init)'
'|'
'(GLIBC_([0-9.]+))'
'|'
'(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)')
def libc_ver(executable=sys.executable,lib='',version='',
chunksize=2048):
""" Tries to determine the libc version that the file executable
(which defaults to the Python interpreter) is linked against.
Returns a tuple of strings (lib,version) which default to the
given parameters in case the lookup fails.
Note that the function has intimate knowledge of how different
libc versions add symbols to the executable and thus is probably
only useable for executables compiled using gcc.
The file is read and scanned in chunks of chunksize bytes.
"""
f = open(executable,'rb')
binary = f.read(chunksize)
pos = 0
while 1:
m = _libc_search.search(binary,pos)
if not m:
binary = f.read(chunksize)
if not binary:
break
pos = 0
continue
libcinit,glibc,glibcversion,so,threads,soversion = m.groups()
if libcinit and not lib:
lib = 'libc'
elif glibc:
if lib != 'glibc':
lib = 'glibc'
version = glibcversion
elif glibcversion > version:
version = glibcversion
elif so:
if lib != 'glibc':
lib = 'libc'
if soversion > version:
version = soversion
if threads and version[-len(threads):] != threads:
version = version + threads
pos = m.end()
f.close()
return lib,version
def _dist_try_harder(distname,version,id):
""" Tries some special tricks to get the distribution
information in case the default method fails.
Currently supports older SuSE Linux, Caldera OpenLinux and
Slackware Linux distributions.
"""
if os.path.exists('/var/adm/inst-log/info'):
# SuSE Linux stores distribution information in that file
info = open('/var/adm/inst-log/info').readlines()
distname = 'SuSE'
for line in info:
tv = string.split(line)
if len(tv) == 2:
tag,value = tv
else:
continue
if tag == 'MIN_DIST_VERSION':
version = string.strip(value)
elif tag == 'DIST_IDENT':
values = string.split(value,'-')
id = values[2]
return distname,version,id
if os.path.exists('/etc/.installed'):
# Caldera OpenLinux has some infos in that file (thanks to Colin Kong)
info = open('/etc/.installed').readlines()
for line in info:
pkg = string.split(line,'-')
if len(pkg) >= 2 and pkg[0] == 'OpenLinux':
# XXX does Caldera support non Intel platforms ? If yes,
# where can we find the needed id ?
return 'OpenLinux',pkg[1],id
if os.path.isdir('/usr/lib/setup'):
# Check for slackware verson tag file (thanks to Greg Andruk)
verfiles = os.listdir('/usr/lib/setup')
for n in range(len(verfiles)-1, -1, -1):
if verfiles[n][:14] != 'slack-version-':
del verfiles[n]
if verfiles:
verfiles.sort()
distname = 'slackware'
version = verfiles[-1][14:]
return distname,version,id
return distname,version,id
_release_filename = re.compile(r'(\w+)[-_](release|version)')
_release_version = re.compile(r'([\d.]+)[^(]*(?:\((.+)\))?')
# Note:In supported_dists below we need 'fedora' before 'redhat' as in
# Fedora redhat-release is a link to fedora-release.
def dist(distname='',version='',id='',
supported_dists=('SuSE', 'debian', 'fedora', 'redhat', 'mandrake')):
""" Tries to determine the name of the Linux OS distribution name.
The function first looks for a distribution release file in
/etc and then reverts to _dist_try_harder() in case no
suitable files are found.
Returns a tuple (distname,version,id) which default to the
args given as parameters.
"""
try:
etc = os.listdir('/etc')
except os.error:
# Probably not a Unix system
return distname,version,id
for file in etc:
m = _release_filename.match(file)
if m:
_distname,dummy = m.groups()
if _distname in supported_dists:
distname = _distname
break
else:
return _dist_try_harder(distname,version,id)
f = open('/etc/'+file,'r')
firstline = f.readline()
f.close()
m = _release_version.search(firstline)
if m:
_version,_id = m.groups()
if _version:
version = _version
if _id:
id = _id
else:
# Unkown format... take the first two words
l = string.split(string.strip(firstline))
if l:
version = l[0]
if len(l) > 1:
id = l[1]
return distname,version,id
class _popen:
""" Fairly portable (alternative) popen implementation.
This is mostly needed in case os.popen() is not available, or
doesn't work as advertised, e.g. in Win9X GUI programs like
PythonWin or IDLE.
Writing to the pipe is currently not supported.
"""
tmpfile = ''
pipe = None
bufsize = None
mode = 'r'
def __init__(self,cmd,mode='r',bufsize=None):
if mode != 'r':
raise ValueError,'popen()-emulation only supports read mode'
import tempfile
self.tmpfile = tmpfile = tempfile.mktemp()
os.system(cmd + ' > %s' % tmpfile)
self.pipe = open(tmpfile,'rb')
self.bufsize = bufsize
self.mode = mode
def read(self):
return self.pipe.read()
def readlines(self):
if self.bufsize is not None:
return self.pipe.readlines()
def close(self,
remove=os.unlink,error=os.error):
if self.pipe:
rc = self.pipe.close()
else:
rc = 255
if self.tmpfile:
try:
remove(self.tmpfile)
except error:
pass
return rc
# Alias
__del__ = close
def popen(cmd, mode='r', bufsize=None):
""" Portable popen() interface.
"""
# Find a working popen implementation preferring win32pipe.popen
# over os.popen over _popen
popen = None
if os.environ.get('OS','') == 'Windows_NT':
# On NT win32pipe should work; on Win9x it hangs due to bugs
# in the MS C lib (see MS KnowledgeBase article Q150956)
try:
import win32pipe
except ImportError:
pass
else:
popen = win32pipe.popen
if popen is None:
if hasattr(os,'popen'):
popen = os.popen
# Check whether it works... it doesn't in GUI programs
# on Windows platforms
if sys.platform == 'win32': # XXX Others too ?
try:
popen('')
except os.error:
popen = _popen
else:
popen = _popen
if bufsize is None:
return popen(cmd,mode)
else:
return popen(cmd,mode,bufsize)
def _norm_version(version,build=''):
""" Normalize the version and build strings and return a single
version string using the format major.minor.build (or patchlevel).
"""
l = string.split(version,'.')
if build:
l.append(build)
try:
ints = map(int,l)
except ValueError:
strings = l
else:
strings = map(str,ints)
version = string.join(strings[:3],'.')
return version
_ver_output = re.compile(r'(?:([\w ]+) ([\w.]+) '
'.*'
'Version ([\d.]+))')
def _syscmd_ver(system='',release='',version='',
supported_platforms=('win32','win16','dos','os2')):
""" Tries to figure out the OS version used and returns
a tuple (system,release,version).
It uses the "ver" shell command for this which is known
to exists on Windows, DOS and OS/2. XXX Others too ?
In case this fails, the given parameters are used as
defaults.
"""
if sys.platform not in supported_platforms:
return system,release,version
# Try some common cmd strings
for cmd in ('ver','command /c ver','cmd /c ver'):
try:
pipe = popen(cmd)
info = pipe.read()
if pipe.close():
raise os.error,'command failed'
# XXX How can I supress shell errors from being written
# to stderr ?
except os.error,why:
#print 'Command %s failed: %s' % (cmd,why)
continue
except IOError,why:
#print 'Command %s failed: %s' % (cmd,why)
continue
else:
break
else:
return system,release,version
# Parse the output
info = string.strip(info)
m = _ver_output.match(info)
if m:
system,release,version = m.groups()
# Strip trailing dots from version and release
if release[-1] == '.':
release = release[:-1]
if version[-1] == '.':
version = version[:-1]
# Normalize the version and build strings (eliminating additional
# zeros)
version = _norm_version(version)
return system,release,version
def _win32_getvalue(key,name,default=''):
""" Read a value for name from the registry key.
In case this fails, default is returned.
"""
from win32api import RegQueryValueEx
try:
return RegQueryValueEx(key,name)
except:
return default
def win32_ver(release='',version='',csd='',ptype=''):
""" Get additional version information from the Windows Registry
and return a tuple (version,csd,ptype) referring to version
number, CSD level and OS type (multi/single
processor).
As a hint: ptype returns 'Uniprocessor Free' on single
processor NT machines and 'Multiprocessor Free' on multi
processor machines. The 'Free' refers to the OS version being
free of debugging code. It could also state 'Checked' which
means the OS version uses debugging code, i.e. code that
checks arguments, ranges, etc. (Thomas Heller).
Note: this function only works if Mark Hammond's win32
package is installed and obviously only runs on Win32
compatible platforms.
"""
# XXX Is there any way to find out the processor type on WinXX ?
# XXX Is win32 available on Windows CE ?
#
# Adapted from code posted by Karl Putland to comp.lang.python.
#
# The mappings between reg. values and release names can be found
# here: http://msdn.microsoft.com/library/en-us/sysinfo/base/osversioninfo_str.asp
# Import the needed APIs
try:
import win32api
except ImportError:
return release,version,csd,ptype
from win32api import RegQueryValueEx,RegOpenKeyEx,RegCloseKey,GetVersionEx
from win32con import HKEY_LOCAL_MACHINE,VER_PLATFORM_WIN32_NT,\
VER_PLATFORM_WIN32_WINDOWS
# Find out the registry key and some general version infos
maj,min,buildno,plat,csd = GetVersionEx()
version = '%i.%i.%i' % (maj,min,buildno & 0xFFFF)
if csd[:13] == 'Service Pack ':
csd = 'SP' + csd[13:]
if plat == VER_PLATFORM_WIN32_WINDOWS:
regkey = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion'
# Try to guess the release name
if maj == 4:
if min == 0:
release = '95'
elif min == 10:
release = '98'
elif min == 90:
release = 'Me'
else:
release = 'postMe'
elif maj == 5:
release = '2000'
elif plat == VER_PLATFORM_WIN32_NT:
regkey = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion'
if maj <= 4:
release = 'NT'
elif maj == 5:
if min == 0:
release = '2000'
elif min == 1:
release = 'XP'
elif min == 2:
release = '2003Server'
else:
release = 'post2003'
else:
if not release:
# E.g. Win3.1 with win32s
release = '%i.%i' % (maj,min)
return release,version,csd,ptype
# Open the registry key
try:
keyCurVer = RegOpenKeyEx(HKEY_LOCAL_MACHINE,regkey)
# Get a value to make sure the key exists...
RegQueryValueEx(keyCurVer,'SystemRoot')
except:
return release,version,csd,ptype
# Parse values
#subversion = _win32_getvalue(keyCurVer,
# 'SubVersionNumber',
# ('',1))[0]
#if subversion:
# release = release + subversion # 95a, 95b, etc.
build = _win32_getvalue(keyCurVer,
'CurrentBuildNumber',
('',1))[0]
ptype = _win32_getvalue(keyCurVer,
'CurrentType',
(ptype,1))[0]
# Normalize version
version = _norm_version(version,build)
# Close key
RegCloseKey(keyCurVer)
return release,version,csd,ptype
def _mac_ver_lookup(selectors,default=None):
from gestalt import gestalt
import MacOS
l = []
append = l.append
for selector in selectors:
try:
append(gestalt(selector))
except (RuntimeError, MacOS.Error):
append(default)
return l
def _bcd2str(bcd):
return hex(bcd)[2:]
def mac_ver(release='',versioninfo=('','',''),machine=''):
""" Get MacOS version information and return it as tuple (release,
versioninfo, machine) with versioninfo being a tuple (version,
dev_stage, non_release_version).
Entries which cannot be determined are set to the paramter values
which default to ''. All tuple entries are strings.
Thanks to Mark R. Levinson for mailing documentation links and
code examples for this function. Documentation for the
gestalt() API is available online at:
http://www.rgaros.nl/gestalt/
"""
# Check whether the version info module is available
try:
import gestalt
import MacOS
except ImportError:
return release,versioninfo,machine
# Get the infos
sysv,sysu,sysa = _mac_ver_lookup(('sysv','sysu','sysa'))
# Decode the infos
if sysv:
major = (sysv & 0xFF00) >> 8
minor = (sysv & 0x00F0) >> 4
patch = (sysv & 0x000F)
release = '%s.%i.%i' % (_bcd2str(major),minor,patch)
if sysu:
major = int((sysu & 0xFF000000L) >> 24)
minor = (sysu & 0x00F00000) >> 20
bugfix = (sysu & 0x000F0000) >> 16
stage = (sysu & 0x0000FF00) >> 8
nonrel = (sysu & 0x000000FF)
version = '%s.%i.%i' % (_bcd2str(major),minor,bugfix)
nonrel = _bcd2str(nonrel)
stage = {0x20:'development',
0x40:'alpha',
0x60:'beta',
0x80:'final'}.get(stage,'')
versioninfo = (version,stage,nonrel)
if sysa:
machine = {0x1: '68k',
0x2: 'PowerPC',
0xa: 'i386'}.get(sysa,'')
return release,versioninfo,machine
def _java_getprop(name,default):
from java.lang import System
try:
return System.getProperty(name)
except:
return default
def java_ver(release='',vendor='',vminfo=('','',''),osinfo=('','','')):
""" Version interface for Jython.
Returns a tuple (release,vendor,vminfo,osinfo) with vminfo being
a tuple (vm_name,vm_release,vm_vendor) and osinfo being a
tuple (os_name,os_version,os_arch).
Values which cannot be determined are set to the defaults
given as parameters (which all default to '').
"""
# Import the needed APIs
try:
import java.lang
except ImportError:
return release,vendor,vminfo,osinfo
vendor = _java_getprop('java.vendor',vendor)
release = _java_getprop('java.version',release)
vm_name,vm_release,vm_vendor = vminfo
vm_name = _java_getprop('java.vm.name',vm_name)
vm_vendor = _java_getprop('java.vm.vendor',vm_vendor)
vm_release = _java_getprop('java.vm.version',vm_release)
vminfo = vm_name,vm_release,vm_vendor
os_name,os_version,os_arch = osinfo
os_arch = _java_getprop('java.os.arch',os_arch)
os_name = _java_getprop('java.os.name',os_name)
os_version = _java_getprop('java.os.version',os_version)
osinfo = os_name,os_version,os_arch
return release,vendor,vminfo,osinfo
### System name aliasing
def system_alias(system,release,version):
""" Returns (system,release,version) aliased to common
marketing names used for some systems.
It also does some reordering of the information in some cases
where it would otherwise cause confusion.
"""
if system == 'Rhapsody':
# Apple's BSD derivative
# XXX How can we determine the marketing release number ?
return 'MacOS X Server',system+release,version
elif system == 'SunOS':
# Sun's OS
if release < '5':
# These releases use the old name SunOS
return system,release,version
# Modify release (marketing release = SunOS release - 3)
l = string.split(release,'.')
if l:
try:
major = int(l[0])
except ValueError:
pass
else:
major = major - 3
l[0] = str(major)
release = string.join(l,'.')
if release < '6':
system = 'Solaris'
else:
# XXX Whatever the new SunOS marketing name is...
system = 'Solaris'
elif system == 'IRIX64':
# IRIX reports IRIX64 on platforms with 64-bit support; yet it
# is really a version and not a different platform, since 32-bit
# apps are also supported..
system = 'IRIX'
if version:
version = version + ' (64bit)'
else:
version = '64bit'
elif system in ('win32','win16'):
# In case one of the other tricks
system = 'Windows'
return system,release,version
### Various internal helpers
def _platform(*args):
""" Helper to format the platform string in a filename
compatible format e.g. "system-version-machine".
"""
# Format the platform string
platform = string.join(
map(string.strip,
filter(len,args)),
'-')
# Cleanup some possible filename obstacles...
replace = string.replace
platform = replace(platform,' ','_')
platform = replace(platform,'/','-')
platform = replace(platform,'\\','-')
platform = replace(platform,':','-')
platform = replace(platform,';','-')
platform = replace(platform,'"','-')
platform = replace(platform,'(','-')
platform = replace(platform,')','-')
# No need to report 'unknown' information...
platform = replace(platform,'unknown','')
# Fold '--'s and remove trailing '-'
while 1:
cleaned = replace(platform,'--','-')
if cleaned == platform:
break
platform = cleaned
while platform[-1] == '-':
platform = platform[:-1]
return platform
def _node(default=''):
""" Helper to determine the node name of this machine.
"""
try:
import socket
except ImportError:
# No sockets...
return default
try:
return socket.gethostname()
except socket.error:
# Still not working...
return default
# os.path.abspath is new in Python 1.5.2:
if not hasattr(os.path,'abspath'):
def _abspath(path,
isabs=os.path.isabs,join=os.path.join,getcwd=os.getcwd,
normpath=os.path.normpath):
if not isabs(path):
path = join(getcwd(), path)
return normpath(path)
else:
_abspath = os.path.abspath
def _follow_symlinks(filepath):
""" In case filepath is a symlink, follow it until a
real file is reached.
"""
filepath = _abspath(filepath)
while os.path.islink(filepath):
filepath = os.path.normpath(
os.path.join(filepath,os.readlink(filepath)))
return filepath
def _syscmd_uname(option,default=''):
""" Interface to the system's uname command.
"""
if sys.platform in ('dos','win32','win16','os2'):
# XXX Others too ?
return default
try:
f = os.popen('uname %s 2> /dev/null' % option)
except (AttributeError,os.error):
return default
output = string.strip(f.read())
rc = f.close()
if not output or rc:
return default
else:
return output
def _syscmd_file(target,default=''):
""" Interface to the system's file command.
The function uses the -b option of the file command to have it
ommit the filename in its output and if possible the -L option
to have the command follow symlinks. It returns default in
case the command should fail.
"""
target = _follow_symlinks(target)
try:
f = os.popen('file %s 2> /dev/null' % target)
except (AttributeError,os.error):
return default
output = string.strip(f.read())
rc = f.close()
if not output or rc:
return default
else:
return output
### Information about the used architecture
# Default values for architecture; non-empty strings override the
# defaults given as parameters
_default_architecture = {
'win32': ('','WindowsPE'),
'win16': ('','Windows'),
'dos': ('','MSDOS'),
}
_architecture_split = re.compile(r'[\s,]').split
def architecture(executable=sys.executable,bits='',linkage=''):
""" Queries the given executable (defaults to the Python interpreter
binary) for various architecture information.
Returns a tuple (bits,linkage) which contains information about
the bit architecture and the linkage format used for the
executable. Both values are returned as strings.
Values that cannot be determined are returned as given by the
parameter presets. If bits is given as '', the sizeof(pointer)
(or sizeof(long) on Python version < 1.5.2) is used as
indicator for the supported pointer size.
The function relies on the system's "file" command to do the
actual work. This is available on most if not all Unix
platforms. On some non-Unix platforms where the "file" command
does not exist and the executable is set to the Python interpreter
binary defaults from _default_architecture are used.
"""
# Use the sizeof(pointer) as default number of bits if nothing
# else is given as default.
if not bits:
import struct
try:
size = struct.calcsize('P')
except struct.error:
# Older installations can only query longs
size = struct.calcsize('l')
bits = str(size*8) + 'bit'
# Get data from the 'file' system command
output = _syscmd_file(executable,'')
if not output and \
executable == sys.executable:
# "file" command did not return anything; we'll try to provide
# some sensible defaults then...
if _default_architecture.has_key(sys.platform):
b,l = _default_architecture[sys.platform]
if b:
bits = b
if l:
linkage = l
return bits,linkage
# Split the output into a list of strings omitting the filename
fileout = _architecture_split(output)[1:]
if 'executable' not in fileout:
# Format not supported
return bits,linkage
# Bits
if '32-bit' in fileout:
bits = '32bit'
elif 'N32' in fileout:
# On Irix only
bits = 'n32bit'
elif '64-bit' in fileout:
bits = '64bit'
# Linkage
if 'ELF' in fileout:
linkage = 'ELF'
elif 'PE' in fileout:
# E.g. Windows uses this format
if 'Windows' in fileout:
linkage = 'WindowsPE'
else:
linkage = 'PE'
elif 'COFF' in fileout:
linkage = 'COFF'
elif 'MS-DOS' in fileout:
linkage = 'MSDOS'
else:
# XXX the A.OUT format also falls under this class...
pass
return bits,linkage
### Portable uname() interface
_uname_cache = None
def uname():
""" Fairly portable uname interface. Returns a tuple
of strings (system,node,release,version,machine,processor)
identifying the underlying platform.
Note that unlike the os.uname function this also returns
possible processor information as an additional tuple entry.
Entries which cannot be determined are set to ''.
"""
global _uname_cache
if _uname_cache is not None:
return _uname_cache
# Get some infos from the builtin os.uname API...
try:
system,node,release,version,machine = os.uname()
except AttributeError:
# Hmm, no uname... we'll have to poke around the system then.
system = sys.platform
release = ''
version = ''
node = _node()
machine = ''
processor = ''
use_syscmd_ver = 1
# Try win32_ver() on win32 platforms
if system == 'win32':
release,version,csd,ptype = win32_ver()
if release and version:
use_syscmd_ver = 0
# Try the 'ver' system command available on some
# platforms
if use_syscmd_ver:
system,release,version = _syscmd_ver(system)
# Normalize system to what win32_ver() normally returns
# (_syscmd_ver() tends to return the vendor name as well)
if system == 'Microsoft Windows':
system = 'Windows'
# In case we still don't know anything useful, we'll try to
# help ourselves
if system in ('win32','win16'):
if not version:
if system == 'win32':
version = '32bit'
else:
version = '16bit'
system = 'Windows'
elif system[:4] == 'java':
release,vendor,vminfo,osinfo = java_ver()
system = 'Java'
version = string.join(vminfo,', ')
if not version:
version = vendor
elif os.name == 'mac':
release,(version,stage,nonrel),machine = mac_ver()
system = 'MacOS'
else:
# System specific extensions
if system == 'OpenVMS':
# OpenVMS seems to have release and version mixed up
if not release or release == '0':
release = version
version = ''
# Get processor information
try:
import vms_lib
except ImportError:
pass
else:
csid, cpu_number = vms_lib.getsyi('SYI$_CPU',0)
if (cpu_number >= 128):
processor = 'Alpha'
else:
processor = 'VAX'
else:
# Get processor information from the uname system command
processor = _syscmd_uname('-p','')
# 'unknown' is not really any useful as information; we'll convert
# it to '' which is more portable
if system == 'unknown':
system = ''
if node == 'unknown':
node = ''
if release == 'unknown':
release = ''
if version == 'unknown':
version = ''
if machine == 'unknown':
machine = ''
if processor == 'unknown':
processor = ''
_uname_cache = system,node,release,version,machine,processor
return _uname_cache
### Direct interfaces to some of the uname() return values
def system():
""" Returns the system/OS name, e.g. 'Linux', 'Windows' or 'Java'.
An empty string is returned if the value cannot be determined.
"""
return uname()[0]
def node():
""" Returns the computer's network name (which may not be fully
qualified)
An empty string is returned if the value cannot be determined.
"""
return uname()[1]
def release():
""" Returns the system's release, e.g. '2.2.0' or 'NT'
An empty string is returned if the value cannot be determined.
"""
return uname()[2]
def version():
""" Returns the system's release version, e.g. '#3 on degas'
An empty string is returned if the value cannot be determined.
"""
return uname()[3]
def machine():
""" Returns the machine type, e.g. 'i386'
An empty string is returned if the value cannot be determined.
"""
return uname()[4]
def processor():
""" Returns the (true) processor name, e.g. 'amdk6'
An empty string is returned if the value cannot be
determined. Note that many platforms do not provide this
information or simply return the same value as for machine(),
e.g. NetBSD does this.
"""
return uname()[5]
### Various APIs for extracting information from sys.version
_sys_version_parser = re.compile(r'([\w.+]+)\s*'
'\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
'\[([^\]]+)\]?')
_sys_version_cache = None
def _sys_version():
""" Returns a parsed version of Python's sys.version as tuple
(version, buildno, builddate, compiler) referring to the Python
version, build number, build date/time as string and the compiler
identification string.
Note that unlike the Python sys.version, the returned value
for the Python version will always include the patchlevel (it
defaults to '.0').
"""
global _sys_version_cache
if _sys_version_cache is not None:
return _sys_version_cache
version, buildno, builddate, buildtime, compiler = \
_sys_version_parser.match(sys.version).groups()
builddate = builddate + ' ' + buildtime
l = string.split(version, '.')
if len(l) == 2:
l.append('0')
version = string.join(l, '.')
_sys_version_cache = (version, buildno, builddate, compiler)
return _sys_version_cache
def python_version():
""" Returns the Python version as string 'major.minor.patchlevel'
Note that unlike the Python sys.version, the returned value
will always include the patchlevel (it defaults to 0).
"""
return _sys_version()[0]
def python_version_tuple():
""" Returns the Python version as tuple (major, minor, patchlevel)
of strings.
Note that unlike the Python sys.version, the returned value
will always include the patchlevel (it defaults to 0).
"""
return string.split(_sys_version()[0], '.')
def python_build():
""" Returns a tuple (buildno, builddate) stating the Python
build number and date as strings.
"""
return _sys_version()[1:3]
def python_compiler():
""" Returns a string identifying the compiler used for compiling
Python.
"""
return _sys_version()[3]
### The Opus Magnum of platform strings :-)
_platform_cache = {}
def platform(aliased=0, terse=0):
""" Returns a single string identifying the underlying platform
with as much useful information as possible (but no more :).
The output is intended to be human readable rather than
machine parseable. It may look different on different
platforms and this is intended.
If "aliased" is true, the function will use aliases for
various platforms that report system names which differ from
their common names, e.g. SunOS will be reported as
Solaris. The system_alias() function is used to implement
this.
Setting terse to true causes the function to return only the
absolute minimum information needed to identify the platform.
"""
result = _platform_cache.get((aliased, terse), None)
if result is not None:
return result
# Get uname information and then apply platform specific cosmetics
# to it...
system,node,release,version,machine,processor = uname()
if machine == processor:
processor = ''
if aliased:
system,release,version = system_alias(system,release,version)
if system == 'Windows':
# MS platforms
rel,vers,csd,ptype = win32_ver(version)
if terse:
platform = _platform(system,release)
else:
platform = _platform(system,release,version,csd)
elif system in ('Linux',):
# Linux based systems
distname,distversion,distid = dist('')
if distname and not terse:
platform = _platform(system,release,machine,processor,
'with',
distname,distversion,distid)
else:
# If the distribution name is unknown check for libc vs. glibc
libcname,libcversion = libc_ver(sys.executable)
platform = _platform(system,release,machine,processor,
'with',
libcname+libcversion)
elif system == 'Java':
# Java platforms
r,v,vminfo,(os_name,os_version,os_arch) = java_ver()
if terse:
platform = _platform(system,release,version)
else:
platform = _platform(system,release,version,
'on',
os_name,os_version,os_arch)
elif system == 'MacOS':
# MacOS platforms
if terse:
platform = _platform(system,release)
else:
platform = _platform(system,release,machine)
else:
# Generic handler
if terse:
platform = _platform(system,release)
else:
bits,linkage = architecture(sys.executable)
platform = _platform(system,release,machine,processor,bits,linkage)
_platform_cache[(aliased, terse)] = platform
return platform
### Command line interface
if __name__ == '__main__':
# Default is to print the aliased verbose platform string
terse = ('terse' in sys.argv or '--terse' in sys.argv)
aliased = (not 'nonaliased' in sys.argv and not '--nonaliased' in sys.argv)
print platform(aliased,terse)
sys.exit(0)
#!/usr/local/bin/python -O
""" A Python Benchmark Suite
"""
#
# Note: Please keep this module compatible to Python 1.5.2.
#
# Tests may include features in later Python versions, but these
# should then be embedded in try-except clauses in the configuration
# module Setup.py.
#
# pybench Copyright
__copyright__ = """\
Copyright (c), 1997-2006, Marc-Andre Lemburg (mal@lemburg.com)
Copyright (c), 2000-2006, eGenix.com Software GmbH (info@egenix.com)
All Rights Reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee or royalty is hereby
granted, provided that the above copyright notice appear in all copies
and that both that copyright notice and this permission notice appear
in supporting documentation or portions thereof, including
modifications, that you make.
THE AUTHOR MARC-ANDRE LEMBURG DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE !
"""
import sys, time, operator, string
from CommandLine import *
try:
import cPickle
pickle = cPickle
except ImportError:
import pickle
# Version number; version history: see README file !
__version__ = '2.0'
### Constants
# Second fractions
MILLI_SECONDS = 1e3
MICRO_SECONDS = 1e6
# Percent unit
PERCENT = 100
# Horizontal line length
LINE = 79
# Minimum test run-time
MIN_TEST_RUNTIME = 1e-3
# Number of calibration runs to use for calibrating the tests
CALIBRATION_RUNS = 20
# Number of calibration loops to run for each calibration run
CALIBRATION_LOOPS = 20
# Allow skipping calibration ?
ALLOW_SKIPPING_CALIBRATION = 1
# Timer types
TIMER_TIME_TIME = 'time.time'
TIMER_TIME_CLOCK = 'time.clock'
TIMER_SYSTIMES_PROCESSTIME = 'systimes.processtime'
# Choose platform default timer
if sys.platform[:3] == 'win':
# On WinXP this has 2.5ms resolution
TIMER_PLATFORM_DEFAULT = TIMER_TIME_CLOCK
else:
# On Linux this has 1ms resolution
TIMER_PLATFORM_DEFAULT = TIMER_TIME_TIME
# Print debug information ?
_debug = 0
### Helpers
def get_timer(timertype):
if timertype == TIMER_TIME_TIME:
return time.time
elif timertype == TIMER_TIME_CLOCK:
return time.clock
elif timertype == TIMER_SYSTIMES_PROCESSTIME:
import systimes
return systimes.processtime
else:
raise TypeError('unknown timer type: %s' % timertype)
def get_machine_details():
import platform
if _debug:
print 'Getting machine details...'
buildno, builddate = platform.python_build()
python = platform.python_version()
if python > '2.0':
try:
unichr(100000)
except ValueError:
# UCS2 build (standard)
unicode = 'UCS2'
else:
# UCS4 build (most recent Linux distros)
unicode = 'UCS4'
else:
unicode = None
bits, linkage = platform.architecture()
return {
'platform': platform.platform(),
'processor': platform.processor(),
'executable': sys.executable,
'python': platform.python_version(),
'compiler': platform.python_compiler(),
'buildno': buildno,
'builddate': builddate,
'unicode': unicode,
'bits': bits,
}
def print_machine_details(d, indent=''):
l = ['Machine Details:',
' Platform ID: %s' % d.get('platform', 'n/a'),
' Processor: %s' % d.get('processor', 'n/a'),
'',
'Python:',
' Executable: %s' % d.get('executable', 'n/a'),
' Version: %s' % d.get('python', 'n/a'),
' Compiler: %s' % d.get('compiler', 'n/a'),
' Bits: %s' % d.get('bits', 'n/a'),
' Build: %s (#%s)' % (d.get('builddate', 'n/a'),
d.get('buildno', 'n/a')),
' Unicode: %s' % d.get('unicode', 'n/a'),
]
print indent + string.join(l, '\n' + indent) + '\n'
### Test baseclass
class Test:
""" All test must have this class as baseclass. It provides
the necessary interface to the benchmark machinery.
The tests must set .rounds to a value high enough to let the
test run between 20-50 seconds. This is needed because
clock()-timing only gives rather inaccurate values (on Linux,
for example, it is accurate to a few hundreths of a
second). If you don't want to wait that long, use a warp
factor larger than 1.
It is also important to set the .operations variable to a
value representing the number of "virtual operations" done per
call of .run().
If you change a test in some way, don't forget to increase
it's version number.
"""
### Instance variables that each test should override
# Version number of the test as float (x.yy); this is important
# for comparisons of benchmark runs - tests with unequal version
# number will not get compared.
version = 2.0
# The number of abstract operations done in each round of the
# test. An operation is the basic unit of what you want to
# measure. The benchmark will output the amount of run-time per
# operation. Note that in order to raise the measured timings
# significantly above noise level, it is often required to repeat
# sets of operations more than once per test round. The measured
# overhead per test round should be less than 1 second.
operations = 1
# Number of rounds to execute per test run. This should be
# adjusted to a figure that results in a test run-time of between
# 1-2 seconds.
rounds = 100000
### Internal variables
# Mark this class as implementing a test
is_a_test = 1
# Last timing: (real, run, overhead)
last_timing = (0.0, 0.0, 0.0)
# Warp factor to use for this test
warp = 1
# Number of calibration runs to use
calibration_runs = CALIBRATION_RUNS
# List of calibration timings
overhead_times = None
# List of test run timings
times = []
# Timer used for the benchmark
timer = TIMER_PLATFORM_DEFAULT
def __init__(self, warp=None, calibration_runs=None, timer=None):
# Set parameters
if warp is not None:
self.rounds = int(self.rounds / warp)
if self.rounds == 0:
raise ValueError('warp factor set too high')
self.warp = warp
if calibration_runs is not None:
if (not ALLOW_SKIPPING_CALIBRATION and
calibration_runs < 1):
raise ValueError('at least one calibration run is required')
self.calibration_runs = calibration_runs
if timer is not None:
timer = timer
# Init variables
self.times = []
self.overhead_times = []
# We want these to be in the instance dict, so that pickle
# saves them
self.version = self.version
self.operations = self.operations
self.rounds = self.rounds
def get_timer(self):
""" Return the timer function to use for the test.
"""
return get_timer(self.timer)
def compatible(self, other):
""" Return 1/0 depending on whether the test is compatible
with the other Test instance or not.
"""
if self.version != other.version:
return 0
if self.rounds != other.rounds:
return 0
return 1
def calibrate_test(self):
if self.calibration_runs == 0:
self.overhead_times = [0.0]
return
calibrate = self.calibrate
timer = self.get_timer()
calibration_loops = range(CALIBRATION_LOOPS)
# Time the calibration loop overhead
prep_times = []
for i in range(self.calibration_runs):
t = timer()
for i in calibration_loops:
pass
t = timer() - t
prep_times.append(t)
min_prep_time = min(prep_times)
if _debug:
print
print 'Calib. prep time = %.6fms' % (
min_prep_time * MILLI_SECONDS)
# Time the calibration runs (doing CALIBRATION_LOOPS loops of
# .calibrate() method calls each)
for i in range(self.calibration_runs):
t = timer()
for i in calibration_loops:
calibrate()
t = timer() - t
self.overhead_times.append(t / CALIBRATION_LOOPS
- min_prep_time)
# Check the measured times
min_overhead = min(self.overhead_times)
max_overhead = max(self.overhead_times)
if _debug:
print 'Calib. overhead time = %.6fms' % (
min_overhead * MILLI_SECONDS)
if min_overhead < 0.0:
raise ValueError('calibration setup did not work')
if max_overhead - min_overhead > 0.1:
raise ValueError(
'overhead calibration timing range too inaccurate: '
'%r - %r' % (min_overhead, max_overhead))
def run(self):
""" Run the test in two phases: first calibrate, then
do the actual test. Be careful to keep the calibration
timing low w/r to the test timing.
"""
test = self.test
timer = self.get_timer()
# Get calibration
min_overhead = min(self.overhead_times)
# Test run
t = timer()
test()
t = timer() - t
if t < MIN_TEST_RUNTIME:
raise ValueError('warp factor too high: '
'test times are < 10ms')
eff_time = t - min_overhead
if eff_time < 0:
raise ValueError('wrong calibration')
self.last_timing = (eff_time, t, min_overhead)
self.times.append(eff_time)
def calibrate(self):
""" Calibrate the test.
This method should execute everything that is needed to
setup and run the test - except for the actual operations
that you intend to measure. pybench uses this method to
measure the test implementation overhead.
"""
return
def test(self):
""" Run the test.
The test needs to run self.rounds executing
self.operations number of operations each.
"""
return
def stat(self):
""" Return test run statistics as tuple:
(minimum run time,
average run time,
total run time,
average time per operation,
minimum overhead time)
"""
runs = len(self.times)
if runs == 0:
return 0.0, 0.0, 0.0, 0.0
min_time = min(self.times)
total_time = reduce(operator.add, self.times, 0.0)
avg_time = total_time / float(runs)
operation_avg = total_time / float(runs
* self.rounds
* self.operations)
if self.overhead_times:
min_overhead = min(self.overhead_times)
else:
min_overhead = self.last_timing[2]
return min_time, avg_time, total_time, operation_avg, min_overhead
### Load Setup
# This has to be done after the definition of the Test class, since
# the Setup module will import subclasses using this class.
import Setup
### Benchmark base class
class Benchmark:
# Name of the benchmark
name = ''
# Number of benchmark rounds to run
rounds = 1
# Warp factor use to run the tests
warp = 1 # Warp factor
# Average benchmark round time
roundtime = 0
# Benchmark version number as float x.yy
version = 2.0
# Produce verbose output ?
verbose = 0
# Dictionary with the machine details
machine_details = None
# Timer used for the benchmark
timer = TIMER_PLATFORM_DEFAULT
def __init__(self, name, verbose=None, timer=None, warp=None,
calibration_runs=None):
if name:
self.name = name
else:
self.name = '%04i-%02i-%02i %02i:%02i:%02i' % \
(time.localtime(time.time())[:6])
if verbose is not None:
self.verbose = verbose
if timer is not None:
self.timer = timer
if warp is not None:
self.warp = warp
if calibration_runs is not None:
self.calibration_runs = calibration_runs
# Init vars
self.tests = {}
if _debug:
print 'Getting machine details...'
self.machine_details = get_machine_details()
# Make .version an instance attribute to have it saved in the
# Benchmark pickle
self.version = self.version
def get_timer(self):
""" Return the timer function to use for the test.
"""
return get_timer(self.timer)
def compatible(self, other):
""" Return 1/0 depending on whether the benchmark is
compatible with the other Benchmark instance or not.
"""
if self.version != other.version:
return 0
if (self.machine_details == other.machine_details and
self.timer != other.timer):
return 0
if (self.calibration_runs == 0 and
other.calibration_runs != 0):
return 0
if (self.calibration_runs != 0 and
other.calibration_runs == 0):
return 0
return 1
def load_tests(self, setupmod, limitnames=None):
# Add tests
if self.verbose:
print 'Searching for tests ...'
print '--------------------------------------'
for testclass in setupmod.__dict__.values():
if not hasattr(testclass, 'is_a_test'):
continue
name = testclass.__name__
if name == 'Test':
continue
if (limitnames is not None and
limitnames.search(name) is None):
continue
self.tests[name] = testclass(
warp=self.warp,
calibration_runs=self.calibration_runs,
timer=self.timer)
l = self.tests.keys()
l.sort()
if self.verbose:
for name in l:
print ' %s' % name
print '--------------------------------------'
print ' %i tests found' % len(l)
print
def calibrate(self):
print 'Calibrating tests. Please wait...'
if self.verbose:
print
print 'Test min max'
print '-' * LINE
tests = self.tests.items()
tests.sort()
for i in range(len(tests)):
name, test = tests[i]
test.calibrate_test()
if self.verbose:
print '%30s: %6.3fms %6.3fms' % \
(name,
min(test.overhead_times) * MILLI_SECONDS,
max(test.overhead_times) * MILLI_SECONDS)
print
def run(self):
tests = self.tests.items()
tests.sort()
timer = self.get_timer()
print 'Running %i round(s) of the suite at warp factor %i:' % \
(self.rounds, self.warp)
print
self.roundtimes = []
for i in range(self.rounds):
if self.verbose:
print ' Round %-25i effective absolute overhead' % (i+1)
total_eff_time = 0.0
for j in range(len(tests)):
name, test = tests[j]
if self.verbose:
print '%30s:' % name,
test.run()
(eff_time, abs_time, min_overhead) = test.last_timing
total_eff_time = total_eff_time + eff_time
if self.verbose:
print ' %5.0fms %5.0fms %7.3fms' % \
(eff_time * MILLI_SECONDS,
abs_time * MILLI_SECONDS,
min_overhead * MILLI_SECONDS)
self.roundtimes.append(total_eff_time)
if self.verbose:
print (' '
' ------------------------------')
print (' '
' Totals: %6.0fms' %
(total_eff_time * MILLI_SECONDS))
print
else:
print '* Round %i done in %.3f seconds.' % (i+1,
total_eff_time)
print
def stat(self):
""" Return benchmark run statistics as tuple:
(minimum round time,
average round time,
maximum round time)
XXX Currently not used, since the benchmark does test
statistics across all rounds.
"""
runs = len(self.roundtimes)
if runs == 0:
return 0.0, 0.0
min_time = min(self.roundtimes)
total_time = reduce(operator.add, self.roundtimes, 0.0)
avg_time = total_time / float(runs)
max_time = max(self.roundtimes)
return (min_time, avg_time, max_time)
def print_header(self, title='Benchmark'):
print '-' * LINE
print '%s: %s' % (title, self.name)
print '-' * LINE
print
print ' Rounds: %s' % self.rounds
print ' Warp: %s' % self.warp
print ' Timer: %s' % self.timer
print
if self.machine_details:
print_machine_details(self.machine_details, indent=' ')
print
def print_benchmark(self, hidenoise=0, limitnames=None):
print ('Test '
' minimum average operation overhead')
print '-' * LINE
tests = self.tests.items()
tests.sort()
total_min_time = 0.0
total_avg_time = 0.0
for name, test in tests:
if (limitnames is not None and
limitnames.search(name) is None):
continue
(min_time,
avg_time,
total_time,
op_avg,
min_overhead) = test.stat()
total_min_time = total_min_time + min_time
total_avg_time = total_avg_time + avg_time
print '%30s: %5.0fms %5.0fms %6.2fus %7.3fms' % \
(name,
min_time * MILLI_SECONDS,
avg_time * MILLI_SECONDS,
op_avg * MICRO_SECONDS,
min_overhead *MILLI_SECONDS)
print '-' * LINE
print ('Totals: '
' %6.0fms %6.0fms' %
(total_min_time * MILLI_SECONDS,
total_avg_time * MILLI_SECONDS,
))
print
def print_comparison(self, compare_to, hidenoise=0, limitnames=None):
# Check benchmark versions
if compare_to.version != self.version:
print ('* Benchmark versions differ: '
'cannot compare this benchmark to "%s" !' %
compare_to.name)
print
self.print_benchmark(hidenoise=hidenoise,
limitnames=limitnames)
return
# Print header
compare_to.print_header('Comparing with')
print ('Test '
' minimum run-time average run-time')
print (' '
' this other diff this other diff')
print '-' * LINE
# Print test comparisons
tests = self.tests.items()
tests.sort()
total_min_time = other_total_min_time = 0.0
total_avg_time = other_total_avg_time = 0.0
benchmarks_compatible = self.compatible(compare_to)
tests_compatible = 1
for name, test in tests:
if (limitnames is not None and
limitnames.search(name) is None):
continue
(min_time,
avg_time,
total_time,
op_avg,
min_overhead) = test.stat()
total_min_time = total_min_time + min_time
total_avg_time = total_avg_time + avg_time
try:
other = compare_to.tests[name]
except KeyError:
other = None
if other is None:
# Other benchmark doesn't include the given test
min_diff, avg_diff = 'n/a', 'n/a'
other_min_time = 0.0
other_avg_time = 0.0
tests_compatible = 0
else:
(other_min_time,
other_avg_time,
other_total_time,
other_op_avg,
other_min_overhead) = other.stat()
other_total_min_time = other_total_min_time + other_min_time
other_total_avg_time = other_total_avg_time + other_avg_time
if (benchmarks_compatible and
test.compatible(other)):
# Both benchmark and tests are comparible
min_diff = ((min_time * self.warp) /
(other_min_time * other.warp) - 1.0)
avg_diff = ((avg_time * self.warp) /
(other_avg_time * other.warp) - 1.0)
if hidenoise and abs(min_diff) < 10.0:
min_diff = ''
else:
min_diff = '%+5.1f%%' % (min_diff * PERCENT)
if hidenoise and abs(avg_diff) < 10.0:
avg_diff = ''
else:
avg_diff = '%+5.1f%%' % (avg_diff * PERCENT)
else:
# Benchmark or tests are not comparible
min_diff, avg_diff = 'n/a', 'n/a'
tests_compatible = 0
print '%30s: %5.0fms %5.0fms %7s %5.0fms %5.0fms %7s' % \
(name,
min_time * MILLI_SECONDS,
other_min_time * MILLI_SECONDS * compare_to.warp / self.warp,
min_diff,
avg_time * MILLI_SECONDS,
other_avg_time * MILLI_SECONDS * compare_to.warp / self.warp,
avg_diff)
print '-' * LINE
# Summarise test results
if not benchmarks_compatible or not tests_compatible:
min_diff, avg_diff = 'n/a', 'n/a'
else:
if other_total_min_time != 0.0:
min_diff = '%+5.1f%%' % (
((total_min_time * self.warp) /
(other_total_min_time * compare_to.warp) - 1.0) * PERCENT)
else:
min_diff = 'n/a'
if other_total_avg_time != 0.0:
avg_diff = '%+5.1f%%' % (
((total_avg_time * self.warp) /
(other_total_avg_time * compare_to.warp) - 1.0) * PERCENT)
else:
avg_diff = 'n/a'
print ('Totals: '
' %5.0fms %5.0fms %7s %5.0fms %5.0fms %7s' %
(total_min_time * MILLI_SECONDS,
(other_total_min_time * compare_to.warp/self.warp
* MILLI_SECONDS),
min_diff,
total_avg_time * MILLI_SECONDS,
(other_total_avg_time * compare_to.warp/self.warp
* MILLI_SECONDS),
avg_diff
))
print
print '(this=%s, other=%s)' % (self.name,
compare_to.name)
print
class PyBenchCmdline(Application):
header = ("PYBENCH - a benchmark test suite for Python "
"interpreters/compilers.")
version = __version__
debug = _debug
options = [ArgumentOption('-n',
'number of rounds',
Setup.Number_of_rounds),
ArgumentOption('-f',
'save benchmark to file arg',
''),
ArgumentOption('-c',
'compare benchmark with the one in file arg',
''),
ArgumentOption('-s',
'show benchmark in file arg, then exit',
''),
ArgumentOption('-w',
'set warp factor to arg',
Setup.Warp_factor),
ArgumentOption('-t',
'run only tests with names matching arg',
''),
ArgumentOption('-C',
'set the number of calibration runs to arg',
CALIBRATION_RUNS),
SwitchOption('-d',
'hide noise in comparisons',
0),
SwitchOption('-v',
'verbose output (not recommended)',
0),
SwitchOption('--with-gc',
'enable garbage collection',
0),
SwitchOption('--with-syscheck',
'use default sys check interval',
0),
ArgumentOption('--timer',
'use given timer',
TIMER_PLATFORM_DEFAULT),
]
about = """\
The normal operation is to run the suite and display the
results. Use -f to save them for later reuse or comparisons.
Available timers:
time.time
time.clock
systimes.processtime
Examples:
python2.1 pybench.py -f p21.pybench
python2.5 pybench.py -f p25.pybench
python pybench.py -s p25.pybench -c p21.pybench
"""
copyright = __copyright__
def main(self):
rounds = self.values['-n']
reportfile = self.values['-f']
show_bench = self.values['-s']
compare_to = self.values['-c']
hidenoise = self.values['-d']
warp = int(self.values['-w'])
withgc = self.values['--with-gc']
limitnames = self.values['-t']
if limitnames:
if _debug:
print '* limiting test names to one with substring "%s"' % \
limitnames
limitnames = re.compile(limitnames, re.I)
else:
limitnames = None
verbose = self.verbose
withsyscheck = self.values['--with-syscheck']
calibration_runs = self.values['-C']
timer = self.values['--timer']
print '-' * LINE
print 'PYBENCH %s' % __version__
print '-' * LINE
print '* using Python %s' % (string.split(sys.version)[0])
# Switch off garbage collection
if not withgc:
try:
import gc
except ImportError:
print '* Python version doesn\'t support garbage collection'
else:
gc.disable()
print '* disabled garbage collection'
# "Disable" sys check interval
if not withsyscheck:
# Too bad the check interval uses an int instead of a long...
value = 2147483647
sys.setcheckinterval(value)
print '* system check interval set to maximum: %s' % value
if timer == TIMER_SYSTIMES_PROCESSTIME:
import systimes
print '* using timer: systimes.processtime (%s)' % \
systimes.SYSTIMES_IMPLEMENTATION
else:
print '* using timer: %s' % timer
print
if compare_to:
try:
f = open(compare_to,'rb')
bench = pickle.load(f)
bench.name = compare_to
f.close()
compare_to = bench
except IOError, reason:
print '* Error opening/reading file %s: %s' % (
repr(compare_to),
reason)
compare_to = None
if show_bench:
try:
f = open(show_bench,'rb')
bench = pickle.load(f)
bench.name = show_bench
f.close()
bench.print_header()
if compare_to:
bench.print_comparison(compare_to,
hidenoise=hidenoise,
limitnames=limitnames)
else:
bench.print_benchmark(hidenoise=hidenoise,
limitnames=limitnames)
except IOError:
print '* Error opening/reading file %s: %s' % (
repr(show_bench),
reason)
print
return
if reportfile:
print 'Creating benchmark: %s (rounds=%i, warp=%i)' % \
(reportfile, rounds, warp)
print
# Create benchmark object
bench = Benchmark(reportfile,
verbose=verbose,
timer=timer,
warp=warp,
calibration_runs=calibration_runs)
bench.rounds = rounds
bench.load_tests(Setup, limitnames=limitnames)
try:
bench.calibrate()
bench.run()
except KeyboardInterrupt:
print
print '*** KeyboardInterrupt -- Aborting'
print
return
bench.print_header()
if compare_to:
bench.print_comparison(compare_to,
hidenoise=hidenoise,
limitnames=limitnames)
else:
bench.print_benchmark(hidenoise=hidenoise,
limitnames=limitnames)
# Ring bell
sys.stderr.write('\007')
if reportfile:
try:
f = open(reportfile,'wb')
bench.name = reportfile
pickle.dump(bench,f)
f.close()
except IOError:
print '* Error opening/writing reportfile'
if __name__ == '__main__':
PyBenchCmdline()
#!/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-clock 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-clock)'
USE_WALL_TIME_TIME = 'time.time() (wall-clock)'
if sys.platform[:3] == 'win':
# Windows platform
try:
import win32process
except ImportError:
try:
import ctypes
except ImportError:
# Use the wall-clock 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-clock 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_clock_clock_systimes():
return (time.clock(), 0.0)
def wall_clock_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 100ns intervals on
# Windows XP. However, the process times are only updated with every
# clock tick and the frequency of these is somewhat lower: depending
# on the OS version between 10ms and 15ms. Even worse, the process
# time seems to be allocated to process currently running when the
# clock interrupt arrives, ie. it is possible that the current time
# slice gets accounted to a different process.
WIN32_PROCESS_TIMES_TICKS_PER_SECOND = 1e7
def win32process_getprocesstimes_systimes():
d = win32process.GetProcessTimes(win32process.GetCurrentProcess())
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_clock_clock_systimes
elif SYSTIMES_IMPLEMENTATION is USE_WALL_TIME_TIME:
systimes = wall_clock_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')
def processtime():
""" Return the total time spent on the process.
This is the sum of user and system time as returned by
systimes().
"""
user, system = systimes()
return user + system
### 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()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment