int benchmark(int n_sets, struct LFreeSet2D *sets, double *rays, int algorithm) { int rval = 0; log_info("Running benchmark...\n"); double total_initial_time = get_user_time(); stats_printf("cpu_time:\n"); for (int j = 0; j < n_sets; j++) { log_debug("Set %d...\n", j); double set_initial_time = get_user_time(); struct LFreeSet2D *set = &sets[j]; double *pre_m = &PRE_M[j * 4]; double center = CENTER[j]; rval = LFREE_2D_print_set(set); abort_if(rval, "LFREE_2D_print_set failed"); int wrong_answer = 0; rval = benchmark_set(algorithm, j, set, rays, pre_m, center, &wrong_answer); abort_if(rval, "benchmark_set failed"); double set_duration = get_user_time() - set_initial_time; double avg = (set_duration / N_SAMPLES_PER_SET) * 1000; if(wrong_answer) avg = 1000000; stats_printf(" %d: %.8lf\n", j, avg); log_info(" %3d: %12.3lf ms\n", j, avg); } double total_duration = get_user_time() - total_initial_time; log_info(" %.3lf ms per set \n", total_duration / (n_sets * N_SAMPLES_PER_SET) * 1000); if(algorithm == ALGORITHM_MIP) { log_info(" %.3lf s spent on LP_create\n", MIP_TIME_CREATE); log_info(" %.3lf s spent on LP_optimize\n", MIP_TIME_OPTIMIZE); } CLEANUP: return rval; }
static void stats_dump(void) { float top[STATLINES]; char* top_names[STATLINES]; int i, j, k=0; PyObject *key, *value; for (i=0; i<STATLINES; i++) top[i] = -1.0f; while (PyDict_Next(codestats_dict, &k, &key, &value)) { PyCodeStats* cs = (PyCodeStats*) key; PyCodeObject* co; extra_assert(PyCStruct_Check(key)); extra_assert(PyCode_Check(cs->cs_key)); co = (PyCodeObject*) cs->cs_key; for (i=0; i<STATLINES; i++) { if (cs->st_charge > top[i]) { for (j=STATLINES-1; j>i; j--) { top [j] = top [j-1]; top_names[j] = top_names[j-1]; } top [i] = cs->st_charge; top_names[i] = PyCodeObject_NAME(co); break; } } } for (i=0; i<STATLINES; i++) { if (top[i] < 0.0f) break; stats_printf(("stats: #%d %18g %s\n", i, top[i], top_names[i])); } }
static PyObject* do_fullcompile(PyFrameObject* frame, PyObject* arg) { PyCodeStats* cs; cs = PyCodeStats_Get(frame->f_code); if (cs->st_codebuf == NULL) { /* not already compiled, compile it now */ PyObject* g = frame->f_globals; int rec, module; stats_printf(("stats: full compile code: %s\n", PyCodeObject_NAME(frame->f_code))); if (cs->st_globals && PyInt_Check(cs->st_globals)) rec = PyInt_AS_LONG(cs->st_globals); else rec = DEFAULT_RECURSION; module = frame->f_globals == frame->f_locals; cs->st_codebuf = PsycoCode_CompileCode(frame->f_code, g, rec, module); if (cs->st_codebuf == Py_None) g = NULL; /* failed */ else { Py_INCREF(g); extra_assert(CodeBuffer_Check(cs->st_codebuf)); } Py_XDECREF(cs->st_globals); cs->st_globals = g; } /* already compiled a Psyco version, run it if the globals match */ extra_assert(frame->f_globals != NULL); if (cs->st_globals == frame->f_globals) { Py_INCREF(cs->st_codebuf); return cs->st_codebuf; } return NULL; }
DEFINEFN void psyco_profile_threads(int start) { PyInterpreterState* istate; PyThreadState* tstate; if (!profile_function) return; istate = PyThreadState_Get()->interp; for (tstate=istate->tstate_head; tstate; tstate=tstate->next) { ceval_events_t* cev; if (!measuring_state(tstate)) continue; cev = get_cevents(tstate); if (start == !cev->current_hook) { stats_printf(("stats: %s hooks on thread %p\n", start?"adding":"removing", tstate)); profile_function(cev, start); if (!update_ceval_hooks(cev) && start) { /* cannot start, stop again */ profile_function(cev, 0); } } } }
static PyObject* turbo_go(PyFrameObject* frame, PyObject* target_frame) { PyObject* result; ceval_events_t* cev = get_cevents(frame->f_tstate); /* single-shooting callback */ unset_ceval_hook(cev, PyTrace_LINE, &turbo_go, target_frame); if ((PyObject*) frame == target_frame) { /* the target is the current frame, compile it now */ stats_printf(("stats: compile frame: %s\n", PyCodeObject_NAME(frame->f_code))); result = PsycoCode_CompileFrame(frame, DEFAULT_RECURSION); if (result == Py_None) { Py_DECREF(result); result = NULL; } } else { /* hey, where is my frame? */ PyFrameObject* f = frame->f_back; stats_printf(("stats: where is my frame?\n")); for (; f; f = f->f_back) { if ((PyObject*) f == target_frame) { /* it is lower in the stack, wait until we return to it */ stats_printf(("stats: lower in the stack.\n")); set_ceval_hook(cev, PyTrace_RETURN, &turbo_wait, target_frame); break; } } /* if nowhere to be seen, forget it */ result = NULL; } if (!update_ceval_hooks(cev)) unset_ceval_hook(cev, PyTrace_RETURN, &turbo_wait, target_frame); return result; }
static PyObject* profile_call(PyFrameObject* frame, PyObject* arg) { PyCodeStats* cs; psyco_stats_append(frame->f_tstate, frame->f_back); cs = PyCodeStats_Get(frame->f_code); if (cs->st_globals != NULL) { /* we want to accelerate this code object */ if (cs->st_codebuf == NULL) { /* not already compiled, compile it now */ PyObject* codebuf; PyObject* g = frame->f_globals; int rec, module; stats_printf(("stats: compile code: %s\n", PyCodeObject_NAME(frame->f_code))); if (PyInt_Check(cs->st_globals)) rec = PyInt_AS_LONG(cs->st_globals); else rec = DEFAULT_RECURSION; module = frame->f_globals == frame->f_locals; codebuf = PsycoCode_CompileCode(frame->f_code, g, rec, module); /* rare race condition: 'cs' might have been mutated during the call to PsycoCode_CompileCode(), so cs->st_codebuf might no longer be NULL, or cs->st_globals might be NULL again */ Py_XDECREF(cs->st_codebuf); cs->st_codebuf = codebuf; if (cs->st_codebuf == Py_None) g = NULL; /* failed */ else { Py_INCREF(g); extra_assert (CodeBuffer_Check(cs->st_codebuf)); } Py_XDECREF(cs->st_globals); cs->st_globals = g; } /* already compiled a Psyco version, run it if the globals match */ extra_assert(frame->f_globals != NULL); if (cs->st_globals == frame->f_globals) { Py_INCREF(cs->st_codebuf); return cs->st_codebuf; } } return NULL; }
PSY_INLINE bool call_ceval_hooks(ceval_events_t* cev, int what, PyFrameObject* f) { bool r = true; int n; struct cevents_s* events; PyObject* codebuf; PyObject* obj; extra_assert(what >= 0); if (what >= PyTrace_TOTAL) return true; /* Python >= 2.4 defines PyTrace_C_xxx */ #if VERBOSE_LEVEL >= 3 stats_printf(("hook: %d %s\n", what, PyCodeObject_NAME(f->f_code))); #endif events = cev->events + what; n = events->count; do { if (n == 0) return true; /* done */ n--; extra_assert(n < events->count); codebuf = events->items[n].fn(f, events->items[n].arg); if (events->items[n].fn == &deleted_ceval_hook) { events->items[n] = events->items[--events->count]; } } while (codebuf == NULL); /* call the other hooks, if any */ while (n != 0) { n--; extra_assert(n < events->count); obj = events->items[n].fn(f, events->items[n].arg); Py_XDECREF(obj); if (events->items[n].fn == &deleted_ceval_hook) { events->items[n] = events->items[--events->count]; } } /* enable recursive calls to call_ceval_hooks() */ f->f_tstate->use_tracing = 1; f->f_tstate->tracing--; /* run the compiled code */ r = PsycoCode_Run(codebuf, f, what == PyTrace_CALL); f->f_tstate->tracing++; Py_DECREF(codebuf); #if (PY_VERSION_HEX >= 0x02030000) && (PY_VERSION_HEX < 0x020300f0) if (!r) f->f_stacktop = NULL; /* work around a bug in Python 2.3b1 */ #endif return r; }
static bool update_ceval_hooks(ceval_events_t* cev) { char needed; if (cev->events_total == 0) { needed = 0; } else if (cev->events[PyTrace_LINE].count == 0) { needed = 'P'; /* profile hook only, no line-by-line tracing */ } else { needed = 'T'; /* line-by-line tracing hook */ } if (cev->current_hook != needed) { PyThreadState* tstate = cev->tstate; switch (cev->current_hook) { case 'P': pstopprofile(tstate); break; case 'T': pstoptrace(tstate); break; } switch (needed) { case 'P': if (pstartprofile(tstate)) break; /* ok */ needed = 'T'; /* cannot use profile hook, try to fall through to trace hook */ debug_printf(1, ("profiler hooks busy, " "trying with the slower trace hooks")); case 'T': if (pstarttrace(tstate)) break; /* ok */ cev->current_hook = 0; stats_printf(("stats: update_ceval_hooks() cancel\n")); return false; } cev->current_hook = needed; } return true; }
DEFINEFN void psyco_stats_reset(void) { /* reset all stats */ int i = 0; PyObject *key, *value, *d; stats_printf(("stats: reset\n")); /* reset the charge of all PyCodeStats, keep only the used ones */ RECLIMIT_SAFE_ENTER(); d = PyDict_New(); if (d == NULL) OUT_OF_MEMORY(); while (PyDict_Next(codestats_dict, &i, &key, &value)) { PyCodeStats* cs = (PyCodeStats*) key; if (cs->st_mergepoints) { /* clear the charge and keep alive */ cs->st_charge = 0.0f; if (PyDict_SetItem(d, key, value)) OUT_OF_MEMORY(); } } RECLIMIT_SAFE_LEAVE(); Py_DECREF(codestats_dict); codestats_dict = d; charge_total = 0.0; charge_prelimit = 0.0f; /* reset the time measure in all threads */ { #if MEASURE_ALL_THREADS PyInterpreterState* istate = PyThreadState_Get()->interp; PyThreadState* tstate; for (tstate=istate->tstate_head; tstate; tstate=tstate->next) { (void) get_measure(tstate); } #else (void) get_measure(NULL); #endif } }
DEFINEFN bool psyco_turbo_frame(PyFrameObject* frame) { if (frame->f_lasti >= 0) { /* turbo-run the frame at the next possible occasion unless the frame is actually emulated from a Psyco frame */ ceval_events_t* cev = get_cevents(frame->f_tstate); stats_printf(("stats: turbo frame: %s\n", PyCodeObject_NAME(frame->f_code))); /* if (frame->f_tstate != PyThreadState_GET()) { */ /* stats_printf(("stats: TSTATE = %p, F_TSTATE=%p\n", */ /* PyThreadState_GET(), */ /* frame->f_tstate)); */ /* } */ set_ceval_hook(cev, PyTrace_LINE, &turbo_go, (PyObject*) frame); if (!update_ceval_hooks(cev)) { unset_ceval_hook(cev, PyTrace_LINE, &turbo_go, (PyObject*) frame); return false; } } return true; }