Commit ea6bb4da authored by Kevin Modzelewski's avatar Kevin Modzelewski

Updates to the measure_loc tool

parent 9959d155
...@@ -46,6 +46,7 @@ import os ...@@ -46,6 +46,7 @@ import os
import runpy import runpy
import signal import signal
import sys import sys
import time
import traceback import traceback
class SamplingProfiler(object): class SamplingProfiler(object):
...@@ -74,23 +75,44 @@ class SamplingProfiler(object): ...@@ -74,23 +75,44 @@ class SamplingProfiler(object):
signal.signal(sig, signal.SIG_DFL) signal.signal(sig, signal.SIG_DFL)
return self.dumper() return self.dumper()
# Try to prevent / notice if someone else sets a debugger.
# (Note: removing sys.settrace is not sufficient since one can set
# frame.f_trace)
sys_settrace = sys.settrace
sys.settrace = None
import bdb
bdb.Bdb.set_trace = None
bdb.set_trace = None
import pdb
pdb.set_trace = None
pdb.Pdb.set_trace = None
class TracingProfiler(object): class TracingProfiler(object):
def __init__(self, tracefunc, dumper): def __init__(self, tracefunc, dumper):
self.tracefunc = tracefunc self.tracefunc = tracefunc
self.dumper = dumper self.dumper = dumper
def start(self): def start(self):
sys.settrace(self.tracefunc) sys_settrace(self.tracefunc)
def stop(self): def stop(self):
assert sys.gettrace() == self.tracefunc, "Problem! Someone/something removed our tracer. It's now: %r" % sys.gettrace() assert sys.gettrace() == self.tracefunc, "Problem! Someone/something removed our tracer. It's now: %r" % sys.gettrace()
sys.settrace(None) sys_settrace(None)
return self.dumper() return self.dumper()
times = {} times = {}
start_time = time.time()
SKIP_WARMUP = 0
def signal_handler(sig, frame): def signal_handler(sig, frame):
loc = frame.f_code.co_filename, frame.f_lineno if time.time() >= start_time + SKIP_WARMUP:
times[loc] = times.get(loc, 0) + 1 print "Starting sampling"
def real_signal_handler(sig, frame):
loc = frame.f_code.co_filename, frame.f_lineno
times[loc] = times.get(loc, 0) + 1
signal.signal(sig, real_signal_handler)
real_signal_handler(sig, frame)
return
def trace_count(frame, event, arg): def trace_count(frame, event, arg):
if event == "line": if event == "line":
...@@ -125,10 +147,13 @@ def run(sampler, kind): ...@@ -125,10 +147,13 @@ def run(sampler, kind):
except KeyboardInterrupt: except KeyboardInterrupt:
print "Interrupted!" print "Interrupted!"
traceback.print_exc() traceback.print_exc()
except SystemExit:
pass
except: except:
print "ERROR!" print "ERROR!"
traceback.print_exc() traceback.print_exc()
print "Stopping timer and tallying statistics..."
times = sampler.stop() times = sampler.stop()
times.sort(key=lambda (l, t): t, reverse=True) times.sort(key=lambda (l, t): t, reverse=True)
...@@ -177,7 +202,7 @@ def run(sampler, kind): ...@@ -177,7 +202,7 @@ def run(sampler, kind):
for i in xrange(len(frac_counts)): for i in xrange(len(frac_counts)):
print "Picked %d lines out of %d to reach %.2f%%" % (frac_counts[i], len(times), frac_fracs[i] / total * 100.0) print "Picked %d lines out of %d to reach %.2f%%" % (frac_counts[i], len(times), frac_fracs[i] / total * 100.0)
python_sampler = SamplingProfiler(signal_handler, get_times, "real", interval=0.00001) python_sampler = SamplingProfiler(signal_handler, get_times, "real", interval=0.0001)
python_trace_counter = TracingProfiler(trace_count, get_times) python_trace_counter = TracingProfiler(trace_count, get_times)
try: try:
import measure_loc_ext import measure_loc_ext
...@@ -186,6 +211,9 @@ except ImportError: ...@@ -186,6 +211,9 @@ except ImportError:
print "(extension module not available)" print "(extension module not available)"
if __name__ == "__main__": if __name__ == "__main__":
run(python_sampler, "count") if sys.argv[1] == '-t':
del sys.argv[1]
run(cext_trace_timer, "time")
else:
run(python_sampler, "count")
# run(python_trace_counter, "count") # run(python_trace_counter, "count")
# run(cext_trace_timer, "time")
...@@ -25,6 +25,7 @@ typedef std::pair<const char*, int> Position; ...@@ -25,6 +25,7 @@ typedef std::pair<const char*, int> Position;
static std::unordered_map<Position, double> times; static std::unordered_map<Position, double> times;
static double* next_time = NULL; static double* next_time = NULL;
static double prev_time; static double prev_time;
static double start_time;
static std::vector<Position> call_stack; static std::vector<Position> call_stack;
...@@ -38,12 +39,23 @@ static double time_to_log = 0.0; ...@@ -38,12 +39,23 @@ static double time_to_log = 0.0;
// Run calibrate.py and divide the time accounted to calibrate.py:2 by the loop count (10M) // Run calibrate.py and divide the time accounted to calibrate.py:2 by the loop count (10M)
#define CALIBRATION_CONSTANT 0.0000001 #define CALIBRATION_CONSTANT 0.0000001
// Some benchmarks remove their warmup time from their results, so make sure to match that:
#define WARMUP_TIME 0
static PyObject * static PyObject *
trace(PyObject *self, PyObject *args) trace(PyObject *self, PyObject *args)
{ {
double curtime = floattime();
#if WARMUP_TIME > 0
if (curtime < start_time + WARMUP_TIME) {
Py_INCREF(trace_func);
return trace_func;
}
#endif
bool log = false; bool log = false;
if (next_time) { if (next_time) {
double f = (floattime() - prev_time); double f = (curtime - prev_time);
f -= CALIBRATION_CONSTANT; f -= CALIBRATION_CONSTANT;
*next_time += f; *next_time += f;
...@@ -120,6 +132,7 @@ static PyMethodDef MeasureLocMethods[] = { ...@@ -120,6 +132,7 @@ static PyMethodDef MeasureLocMethods[] = {
PyMODINIT_FUNC PyMODINIT_FUNC
initmeasure_loc_ext(void) initmeasure_loc_ext(void)
{ {
start_time = floattime();
PyObject *m; PyObject *m;
m = Py_InitModule("measure_loc_ext", MeasureLocMethods); m = Py_InitModule("measure_loc_ext", MeasureLocMethods);
......
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