[pypy-svn] r58279 - in pypy/build/benchmem: . benchmark testing
hpk at codespeak.net
hpk at codespeak.net
Sat Sep 20 18:57:38 CEST 2008
Author: hpk
Date: Sat Sep 20 18:57:37 2008
New Revision: 58279
Modified:
pypy/build/benchmem/benchmark/create_recursive_tuples.py
pypy/build/benchmem/benchtool.py
pypy/build/benchmem/smaps.py
pypy/build/benchmem/testing/test_benchtool.py
Log:
always append benchmark results to a file, use denser format
Modified: pypy/build/benchmem/benchmark/create_recursive_tuples.py
==============================================================================
--- pypy/build/benchmem/benchmark/create_recursive_tuples.py (original)
+++ pypy/build/benchmem/benchmark/create_recursive_tuples.py Sat Sep 20 18:57:37 2008
@@ -5,4 +5,11 @@
checkpoint()
for j in range(iter2):
x = (x,)
+ x = (x,)
+ x = (x,)
+ x = (x,)
+ x = (x,)
+ x = (x,)
+ x = (x,)
+ x = (x,)
Modified: pypy/build/benchmem/benchtool.py
==============================================================================
--- pypy/build/benchmem/benchtool.py (original)
+++ pypy/build/benchmem/benchtool.py Sat Sep 20 18:57:37 2008
@@ -1,5 +1,6 @@
+#!/usr/bin/env python
"""
- benchtool.py [--benchlog=logfile] [--executable=path1] [benchname1.py] [benchname2.py]
+ benchtool.py [options] [benchname1.py] [benchname2.py]
record memory usage for given benchmarks (or all if none specified).
@@ -13,8 +14,11 @@
class BenchRunner(object):
+ SEPBENCH = "=" * 80
+
def __init__(self, executable, benchlog):
- self.benchlog = py.path.local(benchlog)
+ self.benchlogpath = py.path.local(benchlog)
+ self.logstream = self.benchlogpath.open("a")
self.executable = executable
self.tmpdir = py.path.local.make_numbered_dir(prefix="bench")
@@ -31,31 +35,33 @@
arglist = ",".join(map(str, args))
source = py.code.Source(path.read(), """
+
+ def write(c):
+ sys.stdout.write(c)
+ sys.stdout.flush()
+
def checkpoint():
- sys.stdout.write("c")
+ write("c")
sys.stdin.read(1)
if __name__ == "__main__":
import os, sys
pid = os.getpid()
- sys.stdout.write(str(pid))
- sys.stdout.write("\\n")
+ write(str(pid) + "\\n")
checkpoint()
%s(checkpoint, %s)
checkpoint()
- sys.stdout.write("F")
- sys.stdout.close()
+ write("F")
+ sys.stdin.close()
""" %(name, arglist))
p = self.tmpdir.join(path.basename)
p.write(source)
return p
- def writeexecinfo(self, benchname):
- f = self.benchlog.open("a")
- print >>f, "=" * 80
- print >>f, "#executable=%r" %(str(self.executable ),)
- print >>f, "#benchname=%r" %(benchname,)
- f.close()
- # xxx add more
+ def writeexecinfo(self, benchname, args):
+ print >>self.logstream, self.SEPBENCH
+ print >>self.logstream, "#executable=%r" %(str(self.executable ),)
+ print >>self.logstream, "#benchname=%r" %(benchname,)
+ print >>self.logstream, "#benchargs=%r" %(args,)
def run_checkpointed_bench(self, filename, args):
benchpyfile = self._preparebench(filename, args)
@@ -65,39 +71,94 @@
stdout, stdin = os.popen2(cmd)
pid = int(stdin.readline())
- self.writeexecinfo(benchpyfile.basename)
- rec = smaps.SmapsRecorder(pid, self.benchlog)
- stdout.write(".")
- stdout.flush()
+ self.writeexecinfo(benchpyfile.basename, args)
+ rec = smaps.SmapsRecorder(pid, self.logstream)
+ self.interact_with_child_checkpoints(rec, stdout, stdin)
+
+ def interact_with_child_checkpoints(self, rec, stdout, stdin):
+ def write(c):
+ stdout.write(c)
+ stdout.flush()
while not stdin.closed:
c = stdin.read(1)
if c == "F":
+ stdin.close()
+ stdout.close()
break
rec.snapshot()
stdout.write(".")
stdout.flush()
#sys.stdout.write(".")
#sys.stdout.flush()
- rec.finish()
- self.log("finished", cmd)
-class BenchResult:
- pass
-
-class BenchlogReader(object):
- def __init__(self, logpath):
- self.logpath = logpath
-
- def getname2results(self):
- name2results = {}
- for result in self.readresults():
- l = name2results.setdefault(result.benchname, [])
- l.append(result)
- return name2results
+#
+# ================ reading a benchmark log file =======================
+#
- def readresults(self):
- xxx
+class Benchresults(object):
+ def __init__(self):
+ self.name2results = {}
+
+ def parse_logfile(self, logpath):
+ f = logpath.open()
+ for result in BenchmarkResult.parse(f):
+ #print "parsed", result
+ l = self.name2results.setdefault(result.benchname, [])
+ l.append(result)
+ f.close()
+class BenchmarkResult:
+ def __init__(self, snapshots, executable, benchname, benchargs):
+ assert snapshots
+ self.snapshots = snapshots
+ self.executable = executable
+ self.benchname = benchname
+ self.benchargs = benchargs
+
+ @classmethod
+ def parse(cls, f):
+ while not f.closed:
+ line = f.readline()
+ if not line.strip():
+ break
+ if not line.startswith("#executable"):
+ print "ignoring", line
+ continue
+ executable = eval(line.split("=", 1)[1])
+ benchname = eval(f.readline().split("=", 1)[1])
+ benchargs = eval(f.readline().split("=", 1)[1])
+
+ snapshots = []
+ line = f.readline()
+ while 1:
+ mappings = []
+ while line != smaps.SmapsRecorder.SEPSNAPSHOT:
+ mappings.append(smaps.Mapping(line))
+ line = f.readline()
+ #print "reading", line.strip()
+ snapshots.append(Snapshot(mappings))
+ line = f.readline()
+ if not line or line == BenchRunner.SEPBENCH:
+ break
+ yield BenchmarkResult(snapshots, executable=executable,
+ benchname=benchname, benchargs=benchargs)
+
+ def _verify_integrity(self):
+ for snap in self.snapshots:
+ for mapping in snap.mappings:
+ clean = mapping.shared_clean + mapping.private_clean
+ dirty = mapping.private_dirty + mapping.shared_dirty
+ assert mapping.rss == dirty + clean
+
+class Snapshot(object):
+ def __init__(self, mappings):
+ assert mappings
+ self.mappings = mappings
+ for name in smaps.Mapping._attrnames:
+ setattr(self, name, sum([getattr(x, name) for x in mappings]))
+
+ def memusage(self):
+ return "privdirty: %d, shadirty: %d" %(self.private_dirty, self.shared_dirty)
#
# ==============================================================================
@@ -146,3 +207,4 @@
runner = BenchRunner(executable, benchlog)
for name in names:
runner.run_checkpointed_bench(name, (100, 100))
+ print "bench results append to -->>>", benchlog
Modified: pypy/build/benchmem/smaps.py
==============================================================================
--- pypy/build/benchmem/smaps.py (original)
+++ pypy/build/benchmem/smaps.py Sat Sep 20 18:57:37 2008
@@ -2,99 +2,55 @@
import py
class SmapsRecorder:
- SEPLINE = "-"*80 + "\n"
+ SEPSNAPSHOT = "-"*80 + "\n"
- def __init__(self, pid, logpath):
- self.logpath = py.path.local(logpath)
- self._file = self.logpath.open("a")
+ def __init__(self, pid, stream):
+ self.stream = stream
self.pid = pid
self.smapspath = py.path.local("/proc/%d/smaps" %(pid,))
assert self.smapspath.check()
def snapshot(self):
- s = self.smapspath.read()
- self._file.write(s)
- self._file.write(self.SEPLINE)
- self._file.flush()
-
- def finish(self):
- self._file.close()
-
-class SmapsReader:
- def __init__(self, snapshots):
- self.snapshots = snapshots
-
- @classmethod
- def parse(cls, path):
- """ parse a file previously recorded through SmapsRecorder. """
- s = path.read()
- parts = filter(None, map(str.strip, s.split(SmapsRecorder.SEPLINE)))
- snapshots = [SmapsSnapshot.parse(s) for s in parts]
- return cls(snapshots)
-
- def _verify_integrity(self):
- for snap in self.snapshots:
- for mapping in snap.mappings:
- clean = mapping.shared_clean + mapping.private_clean
- dirty = mapping.private_dirty + mapping.shared_dirty
- assert mapping.rss == dirty + clean
-
-
-class SmapsMapping:
- def __init__(self, headvars, bodyvars):
- self.__dict__.update(headvars)
- self.__dict__.update(bodyvars)
+ f = self.smapspath.open()
+ headline = f.readline()
+ while not f.closed:
+ attrs = []
+ while not f.closed:
+ sizeline = f.readline()
+ if not sizeline: # EOF
+ break
+ parts = sizeline.split()
+ if len(parts) != 3:
+ headline = sizeline
+ break
+ value = int(parts[1])
+ attrs.append(value)
+ attrs = attrs[:6] # not interested in "Referenced"
+ sizes = ",".join(map(str, attrs))
+ assert sizes
+ self.stream.write("%-24s %s" %(sizes, headline))
+ if not sizeline:
+ break
+ f.close()
+ self.stream.write(self.SEPSNAPSHOT)
+ self.stream.flush()
+
+
+#
+# objects gained from reading of the logfile
+#
+class Mapping:
+ _attrnames = ("size rss shared_clean shared_dirty "
+ "private_clean private_dirty".split())
+ # example '402c1000-402c2000 rw-p 00011000 1f:04 1110 /lib/libnsl-2.5.so'
+ _headattrnames = "virtualaddress mode page dev inode filename".split()
+
+ def __init__(self, line):
+ parts = line.split()
+ attrs = parts.pop(0)
+ for name, value in zip(self._attrnames, map(int, attrs.split(","))):
+ setattr(self, name, value)
+ for name, value in zip(self._headattrnames, parts):
+ setattr(self, name, value)
self.inode = int(self.inode)
-class SmapsSnapshot(object):
- # example '402c1000-402c2000 rw-p 00011000 1f:04 1110 /lib/libnsl-2.5.so'
- headrex = re.compile(r"""
- (?P<virtualaddress>\w+-\w+)\s+
- (?P<mode>[rwxps-]+)\s+
- (?P<page>\w+)\s+
- (?P<dev>\w\w:\w\w)\s+
- (?P<inode>\w+)\s+
- (?P<filename>\S*)""",
- re.VERBOSE)
- # example 'Size: 4648 kB'
- linerex = re.compile(r"(\S+):\s+(\d+)\skB")
-
- def __init__(self, mappings):
- self.mappings = mappings
- self.UNIT = "kB"
- for name in ("size rss shared_clean shared_dirty "
- "private_clean private_dirty".split()):
- setattr(self, name, sum([getattr(x, name) for x in mappings]))
-
- def memusage(self):
- return "privdirty: %d, shadirty: %d" %(self.private_dirty, self.shared_dirty)
-
- @classmethod
- def parse(cls, string):
- lines = string.split("\n")
- mappings = []
- while lines:
- line = lines.pop(0)
- if not line.strip():
- continue
- m = cls.headrex.match(line)
- if m is None:
- print "ignoring", line
- continue
- headvars = m.groupdict()
- bodyvars = {}
- while lines:
- line = lines.pop(0)
- m = cls.linerex.match(line)
- if m is None:
- lines.insert(0, line)
- mappings.append(SmapsMapping(headvars, bodyvars))
- break
- name, num = m.groups()
- name = name.lower()
- num = int(num)
- assert name not in bodyvars
- bodyvars[name] = num
- else:
- mappings.append(SmapsMapping(headvars, bodyvars))
- return cls(mappings)
Modified: pypy/build/benchmem/testing/test_benchtool.py
==============================================================================
--- pypy/build/benchmem/testing/test_benchtool.py (original)
+++ pypy/build/benchmem/testing/test_benchtool.py Sat Sep 20 18:57:37 2008
@@ -12,155 +12,85 @@
tmpdir = py.test.ensuretemp("smapsrecorder")
logpath = tmpdir.join("logfile")
pid = os.getpid()
- rec = smaps.SmapsRecorder(pid=pid, logpath=logpath)
+ f = logpath.open("w")
+ rec = smaps.SmapsRecorder(pid=pid, stream=f)
s = logpath.read()
- assert s.count(smaps.SmapsRecorder.SEPLINE) == 0
+ assert s.count(smaps.SmapsRecorder.SEPSNAPSHOT) == 0
rec.snapshot()
rec.snapshot()
del rec
s = logpath.read()
- assert s.count(smaps.SmapsRecorder.SEPLINE) == 2
+ assert s.count(smaps.SmapsRecorder.SEPSNAPSHOT) == 2
def test_benchrunner_functional():
tmpdir = py.test.ensuretemp("benchrunner")
log=tmpdir.join("log")
- runner = benchtool.BenchRunner(executable="python2.5", benchlog=log)
def checker(path, *args):
if log.check():
log.remove()
+ runner = benchtool.BenchRunner(executable="python2.5", benchlog=log)
runner.run_checkpointed_bench(path, args)
assert log.check()
- reader = smaps.SmapsReader.parse(log)
+ benchresult = benchtool.Benchresults()
+ benchresult.parse_logfile(log)
#assert reader.executable
#assert reader.executable
- assert len(reader.snapshots) == 10 + 2
- reader._verify_integrity()
+ assert len(benchresult.name2results) == 1
+ results = benchresult.name2results.values()[0]
+ assert len(results) == 1
+ assert len(results[0].snapshots) == 10 + 2
for path in benchtool.benchmarkdir.listdir("*.py"):
if path.basename[0] != "_":
yield checker, path, 10, 10
-class TestSmapsSnapshot:
- def setup_class(cls):
- cls.s = py.std.textwrap.dedent("""\
- 08048000-0813f000 r-xp 00000000 fd:00 75457 sometext
- Size: 988 kB
- Rss: 796 kB
- Shared_Clean: 0 kB
- Shared_Dirty: 0 kB
- Private_Clean: 796 kB
- Private_Dirty: 0 kB
- 402c2000-402c4000 rw-p 402c2000 00:00 0
- Size: 16 kB
- Rss: 8 kB
- Shared_Clean: 0 kB
- Shared_Dirty: 0 kB
- Private_Clean: 0 kB
- Private_Dirty: 8 kB""")
-
- def test_parse_mappings(self):
- smapsreader = smaps.SmapsSnapshot.parse(self.s)
- mappings = smapsreader.mappings
- assert len(mappings) == 2
- mapping = mappings[0]
- assert mapping.virtualaddress == "08048000-0813f000"
- assert mapping.mode == "r-xp"
- assert mapping.dev == "fd:00"
- assert mapping.inode == 75457
- assert mapping.filename == "sometext"
- assert mapping.size == 988
- assert mapping.rss == 796
- assert mapping.shared_clean == 0
- assert mapping.shared_dirty == 0
- assert mapping.private_clean == 796
- assert mapping.private_dirty == 0
- #assert mapping.referenced is None
-
- mapping = mappings[1]
- assert mapping.virtualaddress == "402c2000-402c4000"
- assert mapping.mode == "rw-p"
- assert mapping.dev == "00:00"
- assert mapping.inode == 0
- assert not mapping.filename
- assert mapping.size == 16
- assert mapping.rss == 8
- assert mapping.shared_clean == 0
- assert mapping.shared_dirty == 0
- assert mapping.private_clean == 0
- assert mapping.private_dirty == 8
- #assert mapping.referenced == 12
-
- def test_summing(self):
- snap = smaps.SmapsSnapshot.parse(self.s)
- for name in ('size rss shared_clean shared_dirty '
- 'private_clean private_dirty').split():
- sumval = getattr(snap, name)
- val1 = getattr(snap.mappings[0], name)
- val2 = getattr(snap.mappings[1], name)
- assert sumval == val1 + val2
-
-example_data2 = '''
-08048000-0813f000 r-xp 00000000 fd:00 75457 /usr/bin/python2.5
-Size: 988 kB
-Rss: 796 kB
-Shared_Clean: 0 kB
-Shared_Dirty: 0 kB
-Private_Clean: 796 kB
-Private_Dirty: 0 kB
-0813f000-08164000 rw-p 000f6000 fd:00 75457 /usr/bin/python2.5
-Size: 148 kB
-Rss: 120 kB
-Shared_Clean: 0 kB
-Shared_Dirty: 0 kB
-Private_Clean: 12 kB
-Private_Dirty: 108 kB
-08164000-0825c000 rw-p 08164000 00:00 0 [heap]
-Size: 992 kB
-Rss: 924 kB
-Shared_Clean: 0 kB
-Shared_Dirty: 0 kB
-Private_Clean: 0 kB
-Private_Dirty: 924 kB
-b7baf000-b7beb000 r-xp 00000000 08:01 218 /lib/libncurses.so.5.6
-Size: 240 kB
-Rss: 60 kB
-Shared_Clean: 60 kB
-Shared_Dirty: 0 kB
-Private_Clean: 0 kB
-Private_Dirty: 0 kB
-'''
-
-example_data = '''
-08048000-0813f000 r-xp 00000000 fd:00 75457 /usr/bin/python2.5
-Size: 988 kB
-Rss: 796 kB
-Shared_Clean: 0 kB
-Shared_Dirty: 0 kB
-Private_Clean: 796 kB
-Private_Dirty: 0 kB
-Referenced: 796 kB
-0813f000-08164000 rw-p 000f6000 fd:00 75457 /usr/bin/python2.5
-Size: 148 kB
-Rss: 120 kB
-Shared_Clean: 0 kB
-Shared_Dirty: 0 kB
-Private_Clean: 12 kB
-Private_Dirty: 108 kB
-Referenced: 120 kB
-08164000-0825c000 rw-p 08164000 00:00 0 [heap]
-Size: 992 kB
-Rss: 924 kB
-Shared_Clean: 0 kB
-Shared_Dirty: 0 kB
-Private_Clean: 0 kB
-Private_Dirty: 924 kB
-Referenced: 924 kB
-b7baf000-b7beb000 r-xp 00000000 08:01 218 /lib/libncurses.so.5.6
-Size: 240 kB
-Rss: 60 kB
-Shared_Clean: 60 kB
-Shared_Dirty: 0 kB
-Private_Clean: 0 kB
-Private_Dirty: 0 kB
-Referenced: 60 kB
-'''
+def test_log_mapping():
+ s = py.std.textwrap.dedent("""\
+ 402c2000-402c4000 rw-p 402c2000 00:00 0
+ Size: 16 kB
+ Rss: 8 kB
+ Shared_Clean: 0 kB
+ Shared_Dirty: 0 kB
+ Private_Clean: 0 kB
+ Private_Dirty: 8 kB""")
+ basedir = py.test.ensuretemp("log_mapping")
+ p = basedir.join("smaps.example")
+ p.write(s)
+
+ io = py.std.StringIO.StringIO()
+ rec = smaps.SmapsRecorder(os.getpid(), io)
+ rec.smapspath = p
+ rec.snapshot()
+ result = io.getvalue()
+ lines = result.split("\n")
+ l0 = " ".join(lines[0].split())
+ assert l0 == "16,8,0,0,0,8 402c2000-402c4000 rw-p 402c2000 00:00 0"
+ assert lines[1] == smaps.SmapsRecorder.SEPSNAPSHOT.strip()
+
+def test_parse_mapping():
+ line = ("988,796,0,0,796,0 08048000-0813f000 "
+ "r-xp 00000000 fd:00 75457 sometext")
+ mapping = smaps.Mapping(line)
+ assert mapping.virtualaddress == "08048000-0813f000"
+ assert mapping.mode == "r-xp"
+ assert mapping.dev == "fd:00"
+ assert mapping.inode == 75457
+ assert mapping.filename == "sometext"
+ assert mapping.size == 988
+ assert mapping.rss == 796
+ assert mapping.shared_clean == 0
+ assert mapping.shared_dirty == 0
+ assert mapping.private_clean == 796
+ assert mapping.private_dirty == 0
+
+def test_summing():
+ line = ("988,796,0,0,796,0 08048000-0813f000 "
+ "r-xp 00000000 fd:00 75457 sometext")
+ snap = benchtool.Snapshot([smaps.Mapping(line), smaps.Mapping(line)])
+ for name in ('size rss shared_clean shared_dirty '
+ 'private_clean private_dirty').split():
+ sumval = getattr(snap, name)
+ val1 = getattr(snap.mappings[0], name)
+ val2 = getattr(snap.mappings[1], name)
+ assert sumval == val1 + val2
+
More information about the Pypy-commit
mailing list