From 3c6bae613ee55f949693dc8ca43141d3024d7d96 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Tue, 23 Aug 2011 13:19:29 -0400 Subject: [PATCH] Improve benchmark systems and add create/destroy session Signed-off-by: David Goulet --- .gitignore | 2 + benchmark/Makefile.am | 8 +++ benchmark/bench-sessions.c | 131 +++++++++++++++++++++++++++++++++++++ benchmark/benchmark.c | 103 ++++++++++++++++++++++------- benchmark/benchmark.h | 20 ++++-- benchmark/cpu.c | 6 ++ benchmark/measures.h | 8 +++ benchmark/run-boot-time.sh | 51 +++++++++++++++ benchmark/run-sessions.sh | 28 ++++++++ benchmark/runall.sh | 45 ++++++------- benchmark/utils.h | 26 ++++++++ configure.ac | 5 ++ ltt-sessiond/main.c | 12 +++- 13 files changed, 390 insertions(+), 55 deletions(-) create mode 100644 benchmark/bench-sessions.c create mode 100755 benchmark/run-boot-time.sh create mode 100755 benchmark/run-sessions.sh create mode 100644 benchmark/utils.h diff --git a/.gitignore b/.gitignore index 08d44e8e8..37f95a402 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,5 @@ tests/test_sessions tests/test_kernel_data_trace tests/kernel_all_events_basic tests/kernel_event_basic + +benchmark/bench_sessions diff --git a/benchmark/Makefile.am b/benchmark/Makefile.am index d1a353df0..59c88fe2f 100644 --- a/benchmark/Makefile.am +++ b/benchmark/Makefile.am @@ -2,7 +2,15 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LTLIBRARIES = liblttng-benchmark.la +noinst_PROGRAMS = bench_sessions + +UTILS=utils.h +SESSIONS=$(top_srcdir)/ltt-sessiond/session.c + liblttng_benchmark_la_SOURCES = benchmark.c benchmark.h cpu.c cpu.h +bench_sessions_SOURCES = bench-sessions.c $(SESSIONS) $(UTILS) +bench_sessions_LDADD = $(top_builddir)/benchmark/liblttng-benchmark.la + bench: ./runall.sh diff --git a/benchmark/bench-sessions.c b/benchmark/bench-sessions.c new file mode 100644 index 000000000..872b596b6 --- /dev/null +++ b/benchmark/bench-sessions.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2011 David Goulet + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * as published by the Free Software Foundation; only version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#include "ltt-sessiond/session.h" +#include "utils.h" +#include "benchmark.h" + +#define SESSION1 "test1" + +/* This path will NEVER be created in this test */ +#define PATH1 "/tmp/.test-junk-lttng" + +/* For lttngerr.h */ +int opt_quiet = 1; +int opt_verbose = 0; + +static const char alphanum[] = + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + +/* + * Return random string of 10 characters. + */ +static char *get_random_string(void) +{ + int i; + char *str = malloc(11); + + for (i = 0; i < 10; i++) { + str[i] = alphanum[rand() % (sizeof(alphanum) - 1)]; + } + + str[10] = '\0'; + + return str; +} + +int main(int argc, char **argv) +{ + int ret, i, nb_iter; + char **names; + double value, total = 0; + + if (getuid() != 0) { + printf("Aborting test. Must be uid 0 to drop_caches\n"); + return 1; + } + + if (argc < 2) { + printf("Missing arguments\n"); + return 1; + } + + nb_iter = atoi(argv[1]); + + names = malloc(sizeof(char*) * nb_iter); + + srand(time(NULL)); + bench_init(); + + fprintf(fp, "--- Create tracing session ---\n"); + for (i = 0; i < nb_iter; i++) { + names[i] = get_random_string(); + ret = system("echo 3 >/proc/sys/vm/drop_caches"); + tracepoint(create_session_start); + ret = create_session(names[i], PATH1); + tracepoint(create_session_end); + if (ret < 0) { + printf("Create session went wrong. Aborting\n"); + goto error; + } + value = bench_get_create_session(); + fprintf(fp, "%.20f\n", value); + total += value; + } + + fprintf(fp, "--> Average: %.20f\n\n", total/nb_iter); + total = 0; + + fprintf(fp, "--- Destroy tracing session ---\n"); + for (i = 0; i < nb_iter; i++) { + ret = system("echo 3 >/proc/sys/vm/drop_caches"); + tracepoint(destroy_session_start); + ret = destroy_session(names[i]); + tracepoint(destroy_session_end); + if (ret < 0) { + printf("Destroy session went wrong. Aborting\n"); + goto error; + } + value = bench_get_destroy_session(); + fprintf(fp, "%.20f\n", value); + total += value; + free(names[i]); + } + fprintf(fp, "--> Average: %.20f\n\n", total/nb_iter); + + /* Success */ + bench_close(); + return 0; + +error: + bench_close(); + free(names); + + return 1; +} diff --git a/benchmark/benchmark.c b/benchmark/benchmark.c index 72a75c619..eda40b215 100644 --- a/benchmark/benchmark.c +++ b/benchmark/benchmark.c @@ -23,57 +23,116 @@ #include "benchmark.h" -static FILE *fp; +FILE *fp; +static double g_freq; -void benchmark_print_boot_results(void) +static double calibrate_cpu_freq(void) { - uint64_t freq = 0; - double res; int i, nb_calib = 10; - double global_boot_time = 0.0; + double freq; + + printf("CPU frequency calibration, this should take 10 seconds\n"); + + /* CPU Frequency calibration */ + for (i = 0; i < nb_calib; i++) { + freq += (double) get_cpu_freq(); + } + return (freq / (double)nb_calib); +} + +static void close_logs(void) +{ + fclose(fp); +} - fp = fopen(RESULTS_FILE_NAME, "w"); +static void open_logs(void) +{ + fp = fopen(RESULTS_FILE_NAME, "a"); if (fp == NULL) { perror("fopen benchmark"); - return; } +} - /* CPU Frequency calibration */ - for (i = 0; i < nb_calib; i++) { - freq += get_cpu_freq(); +static double get_bench_time(cycles_t before, cycles_t after) +{ + double ret; + + ret = (((double)(after - before) / (g_freq / 1000.0)) / 1000000000.0); + + return ret; +} + +void bench_init(void) +{ + open_logs(); + if (g_freq == 0) { + g_freq = calibrate_cpu_freq(); + //fprintf(fp, "CPU frequency %f Ghz\n\n", g_freq); + } +} + +void bench_close(void) +{ + close_logs(); + printf("Benchmark results in %s\n", RESULTS_FILE_NAME); +} + +double bench_get_create_session(void) +{ + if ((time_create_session_start == 0) && + (time_create_session_end == 0)) { + fprintf(fp, "NO DATA\n"); + return 0; + } + + return get_bench_time(time_create_session_start, time_create_session_end); +} + +double bench_get_destroy_session(void) +{ + if ((time_destroy_session_start == 0) && + (time_destroy_session_end == 0)) { + fprintf(fp, "NO DATA\n"); + return 0; } - freq = freq / nb_calib; - fprintf(fp, "CPU frequency %lu Ghz\n\n", freq); + return get_bench_time(time_destroy_session_start, time_destroy_session_end); +} - fprintf(fp, "Results:\n----------\n"); +/* + * Log results of the sessiond boot process. + * + * Uses all time_sessiond_* values (see measures.h) + */ +void bench_print_boot_process(void) +{ + double res; + double global_boot_time = 0.0; + + fprintf(fp, "--- Session daemon boot process ---\n"); - res = (double) (((double)(time_sessiond_boot_end - time_sessiond_boot_start) - / (((double)freq) / 1000)) / 1000000000); + res = get_bench_time(time_sessiond_boot_start, time_sessiond_boot_end); fprintf(fp, "Boot time inside main() from start to first pthread_join (blocking state)\n"); fprintf(fp, "Time: %.20f sec.\n", res); global_boot_time += res; - res = (double) (((double)(time_sessiond_th_kern_poll - time_sessiond_th_kern_start) - / (((double)freq) / 1000)) / 1000000000); + res = get_bench_time(time_sessiond_th_kern_start, time_sessiond_th_kern_poll); fprintf(fp, "Boot time of the kernel thread from start to poll() (ready state)\n"); fprintf(fp, "Time: %.20f sec.\n", res); global_boot_time += res; - res = (double) (((double)(time_sessiond_th_apps_poll - time_sessiond_th_apps_start) - / (((double)freq) / 1000)) / 1000000000); + res = get_bench_time(time_sessiond_th_apps_start, time_sessiond_th_apps_poll); fprintf(fp, "Boot time of the application thread from start to poll() (ready state)\n"); fprintf(fp, "Time: %.20f sec.\n", res); global_boot_time += res; - res = (double) (((double)(time_sessiond_th_cli_poll - time_sessiond_th_cli_start) - / (((double)freq) / 1000)) / 1000000000); + res = get_bench_time(time_sessiond_th_cli_start, time_sessiond_th_cli_poll); fprintf(fp, "Boot time of the client thread from start to poll() (ready state)\n"); fprintf(fp, "Time: %.20f sec.\n", res); @@ -81,6 +140,4 @@ void benchmark_print_boot_results(void) global_boot_time += res; fprintf(fp, "Global Boot Time of ltt-sessiond: %0.20f sec.\n", global_boot_time); - - fclose(fp); } diff --git a/benchmark/benchmark.h b/benchmark/benchmark.h index 6232dee8c..c02822e80 100644 --- a/benchmark/benchmark.h +++ b/benchmark/benchmark.h @@ -27,14 +27,22 @@ #define RESULTS_FILE_NAME "/tmp/lttng-bench-results.txt" -void benchmark_print_boot_results(void); +extern FILE *fp; -#define record_cycles(name) \ - time_##name = get_cycles(); +void bench_init(void); +void bench_close(void); +void bench_print_boot_process(void); +double bench_get_create_session(void); +double bench_get_destroy_session(void); -#define tracepoint(name, args...) \ - do { \ - record_cycles(name); \ +#define record_cycles(name) \ + do { \ + time_##name = get_cycles(); \ + } while (0) + +#define tracepoint(name, args...) \ + do { \ + record_cycles(name); \ } while (0) #endif /* _BENCHMARK_H */ diff --git a/benchmark/cpu.c b/benchmark/cpu.c index efaea3878..02a8d99d3 100644 --- a/benchmark/cpu.c +++ b/benchmark/cpu.c @@ -23,11 +23,17 @@ #include "cpu.h" +/* + * Return cpu cycle counter + */ cycles_t get_cycles(void) { return caa_get_cycles(); } +/* + * Calculate CPU frequency. + */ uint64_t get_cpu_freq(void) { struct timezone tz; diff --git a/benchmark/measures.h b/benchmark/measures.h index 80cb16780..f67f1c49b 100644 --- a/benchmark/measures.h +++ b/benchmark/measures.h @@ -39,4 +39,12 @@ cycles_t time_sessiond_th_apps_poll; cycles_t time_sessiond_th_cli_start; cycles_t time_sessiond_th_cli_poll; +/* Create tracing session values */ +cycles_t time_create_session_start; +cycles_t time_create_session_end; + +/* Destroy tracing session values */ +cycles_t time_destroy_session_start; +cycles_t time_destroy_session_end; + #endif /* _MEASURES_H */ diff --git a/benchmark/run-boot-time.sh b/benchmark/run-boot-time.sh new file mode 100755 index 000000000..dabb707b9 --- /dev/null +++ b/benchmark/run-boot-time.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# +# Copyright (C) 2011 - David Goulet +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; only version 2 +# of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +SESSIOND_BIN="ltt-sessiond" +RESULTS_PATH="/tmp/lttng-bench-results.txt" +BASEDIR=`dirname $0` + +echo "Session daemon boot process benchmark" + +$BASEDIR/../ltt-sessiond/$SESSIOND_BIN --daemonize --quiet +if [ $? -ne 0 ]; then + echo -e '\e[1;31mFAILED\e[0m' + exit 1 +else + echo -e "\e[1;32mOK\e[0m" +fi + +PID_SESSIOND=`pidof lt-$SESSIOND_BIN` + +# Wait for the benchmark to run +echo -n "Waiting." +sleep 1 +echo -n "." +sleep 1 +echo -n "." +sleep 1 + +kill $PID_SESSIOND + +echo -e "\nResults will be available shortly in $RESULTS_PATH" +echo "" + +tail -F $RESULTS_PATH --pid $PID_SESSIOND 2>/dev/null + +exit 0 diff --git a/benchmark/run-sessions.sh b/benchmark/run-sessions.sh new file mode 100755 index 000000000..6db0c855c --- /dev/null +++ b/benchmark/run-sessions.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# +# Copyright (C) 2011 - David Goulet +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; only version 2 +# of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +RESULTS_PATH="/tmp/lttng-bench-results.txt" +BASEDIR=`dirname $0` +NR_ITER=100 + +echo "Create/Destroy benchmarking..." + +$BASEDIR/bench_sessions $NR_ITER + +exit 0 diff --git a/benchmark/runall.sh b/benchmark/runall.sh index 51e9f4d53..eaf4980b8 100755 --- a/benchmark/runall.sh +++ b/benchmark/runall.sh @@ -17,38 +17,33 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # -SESSIOND_BIN="ltt-sessiond" +#### ADD TESTS HERE #### + +test_suite=( "run-boot-time.sh" "run-sessions.sh" ) + +#### END TESTS HERE #### + RESULTS_PATH="/tmp/lttng-bench-results.txt" BASEDIR=`dirname $0` if [ -e $RESULTS_PATH ]; then - mv $RESULTS_PATH $RESULTS_PATH.`date +%s` -fi - -echo -n "Starting session daemon... " -$BASEDIR/../ltt-sessiond/$SESSIOND_BIN --daemonize --quiet -if [ $? -ne 0 ]; then - echo -e '\e[1;31mFAILED\e[0m' - exit 1 -else - echo -e "\e[1;32mOK\e[0m" + mv -v $RESULTS_PATH $RESULTS_PATH.`date +%s` fi -PID_SESSIOND=`pidof lt-$SESSIOND_BIN` - -# Wait for the benchmark to run -echo -n "Waiting." -sleep 1 -echo -n "." -sleep 1 -echo -n "." -sleep 1 - -kill $PID_SESSIOND - -echo -e "\nResults will be available shortly in $RESULTS_PATH" echo "" -tail -F $RESULTS_PATH --pid $PID_SESSIOND 2>/dev/null +for bin in ${test_suite[@]}; +do + $BASEDIR/$bin + # Test must return 0 to pass. + if [ $? -ne 0 ]; then + echo -e '\e[1;31mFAIL\e[0m' + echo "" + exit 1 + fi + echo "" +done + +mv -v $RESULTS_PATH results-`date +%d%m%Y.%H%M%S`.txt exit 0 diff --git a/benchmark/utils.h b/benchmark/utils.h new file mode 100644 index 000000000..52893b207 --- /dev/null +++ b/benchmark/utils.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2011 David Goulet + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * as published by the Free Software Foundation; only version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#define BRIGHT 1 +#define GREEN 32 +#define RED 31 + +#define PRINT_OK() printf("%c[%d;%dmOK%c[%dm\n", 0x1B, BRIGHT, GREEN, 0x1B, 0); +#define PRINT_FAIL() printf("%c[%d;%dmFAIL%c[%dm\n", 0x1B, BRIGHT, RED, 0x1B, 0); diff --git a/configure.ac b/configure.ac index 24c1b7cb1..7af39997a 100644 --- a/configure.ac +++ b/configure.ac @@ -27,6 +27,11 @@ AC_CHECK_DECL([cds_list_add], [], [AC_MSG_ERROR([liburcu 0.5.4 or newer is needed])], [[#include ]] ) +# Check liburcu +AC_CHECK_DECL([caa_get_cycles], [], + [AC_MSG_ERROR([liburcu 0.5.4 or newer is needed])], [[#include ]] +) + AC_PROG_CC AC_PROG_LIBTOOL diff --git a/ltt-sessiond/main.c b/ltt-sessiond/main.c index ab6d315f3..8d9cfdfbc 100644 --- a/ltt-sessiond/main.c +++ b/ltt-sessiond/main.c @@ -234,7 +234,13 @@ static void cleanup(void) DBG("Unloading kernel modules"); modprobe_remove_kernel_modules(); - benchmark_print_boot_results(); + /* OUTPUT BENCHMARK RESULTS */ + bench_init(); + + bench_print_boot_process(); + + bench_close(); + /* END BENCHMARK */ } /* @@ -2073,7 +2079,9 @@ static int process_client_msg(struct command_ctx *cmd_ctx) goto setup_error; } + tracepoint(create_session_start); ret = create_session(cmd_ctx->lsm->session.name, cmd_ctx->lsm->session.path); + tracepoint(create_session_end); if (ret < 0) { if (ret == -EEXIST) { ret = LTTCOMM_EXIST_SESS; @@ -2097,7 +2105,9 @@ static int process_client_msg(struct command_ctx *cmd_ctx) /* Clean kernel session teardown */ teardown_kernel_session(cmd_ctx->session); + tracepoint(destroy_session_start); ret = destroy_session(cmd_ctx->lsm->session.name); + tracepoint(destroy_session_end); if (ret < 0) { ret = LTTCOMM_FATAL; goto error; -- 2.34.1