import py import csv from optparse import OptionParser import threading import time #executables = ["../goal/pyprolog-c", "sicstus compiled", "sicstus", "xpce"] #executables = ["../goal/pyprolog-c", "swipl"] # executables = ['../branch/continuation-based/prolog/pyrolog-c-nojit', '../branch/continuation-based/prolog/pyrolog-c'] #['../branch/continuation-based/prolog/pyrolog-c', 'java -server -cp ./2p-3.0-alpha.jar alice.tuprologx.ide.CUIConsole'] # executables = ['sicstus', 'sicstus compiled'] # class('java.lang.System') <- currentTimeMillis returns T. - tuprolog # rlwrap java -cp 2p-3.0-alpha.jar alice.tuprologx.ide.CUIConsole # rlwrap java -cp alice.tuprologx.ide.CUIConsolepha.jar al executables = {'sicstus-interpreted' : ('sicstus', 'sics_time', "load_files('%s', [compilation_mode(consult)]).\n\n"), 'sicstus-compiled': ('sicstus', 'sics_time', "load_files('%s', [compilation_mode(compile)]).\n\n"), 'pyrolog-no-jit': ('../branch/continuation-based/prolog/pyrolog-c-nojit', 'pyrologtime.pl'), 'pyrolog-jit': ('../branch/continuation-based/prolog/pyrolog-c-jit', 'pyrologtime.pl'), 'tuprolog': ('java -server -cp ./2p-3.0-alpha.jar alice.tuprologx.ide.CUIConsole', 'tuprolog_time.pl'), 'ciao': ('ciao', 'ciao_time', "compile('%s').\n\n"), 'swi': ('swipl -L0 -G0', 'swi_time')} class MemoryUsageFuture(threading.Thread): """Continuously sample a process's memory usage for its lifetime. Example: future = MemoryUsageFuture(some_pid) ... usage = future.GetMemoryUsage() print max(usage) Note that calls to GetMemoryUsage() will block until the process exits. """ def __init__(self, pid, track_memory): import psutil super(MemoryUsageFuture, self).__init__() self._process = psutil.Process(pid) self._usage = [] self._done = threading.Event() self.daemon = True # if track_memory is false, the thread is only used to catch runaway # processes if track_memory: self._sleeptime = 0.001 else: self._sleeptime = 1 self.start() def run(self): import psutil sleeptime = self._sleeptime maxusage = 1 * 1024 * 1024 * 1024 # one gigabyte try: while True: usage = self._process.get_memory_info()[0] if usage > maxusage: print "trying to use too much memory: %s MB" % (usage / 1024 / 1024, ) self._process.kill() self._usage.append(usage) time.sleep(sleeptime) except (psutil.NoSuchProcess, IOError): pass finally: self._done.set() def memory_usage(self): self._done.wait() return self._usage def main(): parser = setup_optparser() (options, args) = parser.parse_args() if options.executables is None: options.executables = [ ] exec_opts = [executables[x] for x in options.executables] if len(exec_opts) == 0: print 'FAIL' if len(args) > 0: benchmarks = [py.path.local(p) for p in args] else: benchmarks = [p for p in py.path.local(__file__).dirpath().listdir() if p.ext == ".pl"] benchmarks.sort() f = open(options.filename, 'w') w = csv.writer(f, quoting=csv.QUOTE_MINIMAL) try: run(benchmarks, exec_opts, w, options) finally: f.close() def run_single(benchmark, executable, track_memory=False, verbose=True): import subprocess cmd = executable[0] if cmd.startswith("."): cmd = str(py.path.local(executable[0])) cmd = cmd.split() process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) future = MemoryUsageFuture(process.pid, track_memory) if len(executable) == 2: c = "consult('%s').\n\n" else: c = executable[2] input = [] input.append(c % ("support/%s" % (executable[1], ))) input.append(c % (benchmark, )) input.append("initialize(D), benchmark(D, _), bench_time(X), benchmark(D, Out), bench_time(Y), bench_result(X, Y).\n\n") input.append("halt.\n") s, _ = process.communicate("".join(input)) if verbose: print s usage = future.memory_usage() memusage = max(usage) / 1024.0 / 1024.0 try: runtime = extract_result(s) except ValueError: print "output of the prolog:" print s print "no result" print "memory usage", memusage return '0' if track_memory: return memusage else: return runtime def run(benchmarks, executables, csv_writer, options=None): header = ['Benchmark'] header.extend(options.executables) if options.csv: csv_writer.writerow(header) for benchmark in benchmarks: print "----------------------\n%s," % (benchmark.purebasename, ) last = None line = [benchmark.purebasename] for executable in executables: result = run_single(benchmark, executable, track_memory=options.track_memory, verbose=options.verbose) line.append(result) if result != '0': print "%s," % result, if len(executables) == 2: if last is not None: print last / (result), else: last = result py.std.sys.stdout.flush() if options.csv: csv_writer.writerow(line) print def setup_optparser(): parser = OptionParser() parser.add_option("-v", "--verbose", action="store_true", help='Verbose benchmark ouptup', dest="verbose", default=False) parser.add_option("--track-memory", action="store_true", help='Track the memory usage of the proccess. No timing will be done.', dest="track_memory", default=False) parser.add_option("--csv-file", action='store', dest='filename', default="bench.csv") parser.add_option("--csv", action="store_true", help="Write benchmark output to a csv file", default=False, dest='csv') for interpreter in executables: parser.add_option("--%s" % interpreter, action='append_const', const=interpreter, dest='executables') return parser def extract_result(res): import re r = re.search(r'result\((.+)\)', res) if r is not None: return float(r.group(1)) raise ValueError("couldn't get result!") if __name__ == '__main__': main()