// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- #include "config.h" #include "base/basictypes.h" #include "gperftools/stacktrace.h" #include #include #include #include #if HAVE_LIBUNWIND_H #include #endif #include "run_benchmark.h" extern "C" void getcontext_light(ucontext_t *ctx); #define MAX_FRAMES 1024 static void *frames[MAX_FRAMES]; enum measure_mode { MODE_NOOP, MODE_WITH_CONTEXT, MODE_WITHOUT_CONTEXT }; static int ATTRIBUTE_NOINLINE measure_unwind(int maxlevel, int mode) { int n; if (mode == MODE_NOOP) return 0; if (mode == MODE_WITH_CONTEXT) { ucontext_t uc; getcontext_light(&uc); n = GetStackTraceWithContext(frames, MAX_FRAMES, 0, &uc); } else { n = GetStackTrace(frames, MAX_FRAMES, 0); } if (n < maxlevel) { fprintf(stderr, "Expected at least %d frames, got %d\n", maxlevel, n); abort(); } return 0; } static int ATTRIBUTE_NOINLINE frame_forcer(int rv) { return rv; } static int ATTRIBUTE_NOINLINE f1(int level, int maxlevel, int mode) { if (level == maxlevel) return frame_forcer(measure_unwind(maxlevel, mode)); return frame_forcer(f1(level + 1, maxlevel, mode)); } static void bench_unwind_no_op(long iterations, uintptr_t param) { do { f1(0, param, MODE_NOOP); iterations -= param; } while (iterations > 0); } static void bench_unwind_context(long iterations, uintptr_t param) { do { f1(0, param, MODE_WITH_CONTEXT); iterations -= param; } while (iterations > 0); } static void bench_unwind_no_context(long iterations, uintptr_t param) { do { f1(0, param, MODE_WITHOUT_CONTEXT); iterations -= param; } while (iterations > 0); } int main(void) { report_benchmark("unwind_no_op", bench_unwind_no_op, 100); report_benchmark("unwind_context", bench_unwind_context, 100); report_benchmark("unwind_no_context", bench_unwind_no_context, 100); //// TODO: somehow this fails at linking step. Figure out why this is missing // #if HAVE_LIBUNWIND_H // unw_set_caching_policy(unw_local_addr_space, UNW_CACHE_PER_THREAD); // #endif return 0; }