From 3d0a328dd6dea7b4a83aac340044257c6fda29e2 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 11 Mar 2013 19:08:49 -0700 Subject: [PATCH] Add options to help benchmark SDT These are secret, undocumented, for developer use only. Use stap inception-style as the -c CMD of a stap which probes the SDT mark process.provider("stap").mark("benchmark"). --benchmark-sdt-loops=N Loop over the SDT probe point N times. --benchmark-sdt-threads=N Run the loop simultaneously in N threads. --- cmdline.cxx | 2 ++ cmdline.h | 2 ++ main.cxx | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ session.cxx | 44 +++++++++++++++++++++++++++++++++++++------- session.h | 4 ++++ 5 files changed, 93 insertions(+), 7 deletions(-) diff --git a/cmdline.cxx b/cmdline.cxx index d7a2c607a..8fe12f1ef 100644 --- a/cmdline.cxx +++ b/cmdline.cxx @@ -54,5 +54,7 @@ struct option stap_long_options[] = { { "suppress-time-limits", 0, NULL, LONG_OPT_SUPPRESS_TIME_LIMITS }, { "runtime", 1, NULL, LONG_OPT_RUNTIME }, { "dyninst", 0, NULL, LONG_OPT_RUNTIME_DYNINST }, + { "benchmark-sdt-loops", 1, NULL, LONG_OPT_BENCHMARK_SDT_LOOPS }, + { "benchmark-sdt-threads", 1, NULL, LONG_OPT_BENCHMARK_SDT_THREADS }, { NULL, 0, NULL, 0 } }; diff --git a/cmdline.h b/cmdline.h index 6d38586d6..775012850 100644 --- a/cmdline.h +++ b/cmdline.h @@ -53,6 +53,8 @@ enum { LONG_OPT_SUPPRESS_TIME_LIMITS, LONG_OPT_RUNTIME, LONG_OPT_RUNTIME_DYNINST, + LONG_OPT_BENCHMARK_SDT_LOOPS, + LONG_OPT_BENCHMARK_SDT_THREADS, }; // NB: when adding new options, consider very carefully whether they diff --git a/main.cxx b/main.cxx index 0c8f17376..e1e864e15 100644 --- a/main.cxx +++ b/main.cxx @@ -305,6 +305,50 @@ setup_signals (sighandler_t handler) } +static void* +sdt_benchmark_thread(void* p) +{ + unsigned long i = *(unsigned long*)p; + while (i--) + PROBE(stap, benchmark); + return NULL; +} + + +static int +run_sdt_benchmark(systemtap_session& s) +{ + unsigned long loops = s.benchmark_sdt_loops ?: 10000000; + unsigned long threads = s.benchmark_sdt_threads ?: 1; + + clog << _F("Beginning SDT benchmark with %lu loops in %lu threads.", + loops, threads) << endl; + + struct tms tms_before, tms_after; + struct timeval tv_before, tv_after; + unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK); + times (& tms_before); + gettimeofday (&tv_before, NULL); + + pthread_t pthreads[threads]; + for (unsigned long i = 0; i < threads; ++i) + pthread_create(&pthreads[i], NULL, sdt_benchmark_thread, &loops); + for (unsigned long i = 0; i < threads; ++i) + pthread_join(pthreads[i], NULL); + + times (& tms_after); + gettimeofday (&tv_after, NULL); + clog << _F("Completed SDT benchmark in %ldusr/%ldsys/%ldreal ms.", + (tms_after.tms_utime - tms_before.tms_utime) * 1000 / _sc_clk_tck, + (tms_after.tms_stime - tms_before.tms_stime) * 1000 / _sc_clk_tck, + ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + + ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000)) + << endl; + + return EXIT_SUCCESS; +} + + // Compilation passes 0 through 4 static int passes_0_4 (systemtap_session &s) @@ -1007,6 +1051,10 @@ main (int argc, char * const argv []) if (rc == 0 && s.verbose>1) clog << _F("Created temporary directory \"%s\"", s.tmpdir.c_str()) << endl; + // Run the benchmark and quit right away. + if (s.benchmark_sdt_loops || s.benchmark_sdt_threads) + return run_sdt_benchmark(s); + // Prepare connections for each specified remote target. vector targets; bool fake_remote=false; diff --git a/session.cxx b/session.cxx index ecb016a1e..40dde6e58 100644 --- a/session.cxx +++ b/session.cxx @@ -86,6 +86,8 @@ systemtap_session::systemtap_session (): sym_kprobes_text_end (0), sym_stext (0), module_cache (0), + benchmark_sdt_loops(0), + benchmark_sdt_threads(0), last_token (0) { struct utsname buf; @@ -260,6 +262,8 @@ systemtap_session::systemtap_session (const systemtap_session& other, sym_kprobes_text_end (0), sym_stext (0), module_cache (0), + benchmark_sdt_loops(other.benchmark_sdt_loops), + benchmark_sdt_threads(other.benchmark_sdt_threads), last_token (0) { release = kernel_release = kern; @@ -1259,6 +1263,16 @@ systemtap_session::parse_cmdline (int argc, char * const argv []) return 1; break; + case LONG_OPT_BENCHMARK_SDT_LOOPS: + // XXX This option is secret, not supported, subject to change at our whim + benchmark_sdt_loops = strtoul(optarg, NULL, 10); + break; + + case LONG_OPT_BENCHMARK_SDT_THREADS: + // XXX This option is secret, not supported, subject to change at our whim + benchmark_sdt_threads = strtoul(optarg, NULL, 10); + break; + case '?': // Invalid/unrecognized option given or argument required, but // not given. In both cases getopt_long() will have printed the @@ -1321,17 +1335,33 @@ systemtap_session::check_options (int argc, char * const argv []) args.push_back (string (argv[i])); } - // need a user file - // NB: this is also triggered if stap is invoked with no arguments at all - if (! have_script) + // We don't need a script with --list-servers, --trust-servers, or --dump-probe-types. + bool need_script = server_status_strings.empty () && server_trust_spec.empty () && ! dump_probe_types; + + if (benchmark_sdt_loops > 0 || benchmark_sdt_threads > 0) { - // We don't need a script if --list-servers, --trust-servers or --dump-probe-types was - // specified. - if (server_status_strings.empty () && server_trust_spec.empty () && ! dump_probe_types) + // Secret benchmarking options are for local use only, not servers or --remote + if (client_options || !remote_uris.empty()) { - cerr << _("A script must be specified.") << endl; + cerr << _("Benchmark options are only for local use.") << endl; usage(1); } + + // Fill defaults if either is unset. + if (benchmark_sdt_loops == 0) + benchmark_sdt_loops = 10000000; + if (benchmark_sdt_threads == 0) + benchmark_sdt_threads = 1; + + need_script = false; + } + + // need a user file + // NB: this is also triggered if stap is invoked with no arguments at all + if (need_script && ! have_script) + { + cerr << _("A script must be specified.") << endl; + usage(1); } #if ! HAVE_NSS diff --git a/session.h b/session.h index b604009b0..5e65beb47 100644 --- a/session.h +++ b/session.h @@ -343,6 +343,10 @@ public: struct module_cache* module_cache; std::vector build_ids; + // Secret benchmarking options + unsigned long benchmark_sdt_loops; + unsigned long benchmark_sdt_threads; + // NB: It is very important for all of the above (and below) fields // to be cleared in the systemtap_session ctor (session.cxx). -- 2.43.5