From: David Goulet Date: Mon, 30 Jan 2012 20:43:33 +0000 (-0500) Subject: Merge branch 'master' into benchmark X-Git-Url: http://git.lttng.org./?a=commitdiff_plain;h=7bb1478af7d1567a6842d0fc73c46315b65bbaf7;hp=5c73c59bd972bf4d60cacaa968fef72e5109fbd9;p=lttng-tools.git Merge branch 'master' into benchmark Signed-off-by: David Goulet --- diff --git a/.gitignore b/.gitignore index 0eacb03bb..776aa78ef 100644 --- a/.gitignore +++ b/.gitignore @@ -44,4 +44,4 @@ tests/ust_global_event_basic tests/ust-nevents/gen-nevents tests/ust-nprocesses/gen-events-time -benchmark/ +benchmark/bench_sessions diff --git a/Makefile.am b/Makefile.am index 7184340a9..b6c5a7a0d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,11 @@ ACLOCAL_AMFLAGS = -I config -SUBDIRS = src \ +SUBDIRS = src/common/ \ + benchmark \ + src \ tests \ include \ doc + +bench: + ./benchmark/runall.sh diff --git a/benchmark/Makefile.am b/benchmark/Makefile.am new file mode 100644 index 000000000..ae5bb91a9 --- /dev/null +++ b/benchmark/Makefile.am @@ -0,0 +1,17 @@ +AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src + +noinst_LTLIBRARIES = liblttng-benchmark.la + +noinst_PROGRAMS = bench_sessions + +UTILS=utils.h +SESSIONS=$(top_srcdir)/src/bin/lttng-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 \ + $(top_builddir)/src/common/libcommon.la + +bench: + ./runall.sh diff --git a/benchmark/bench-sessions.c b/benchmark/bench-sessions.c new file mode 100644 index 000000000..440b26e78 --- /dev/null +++ b/benchmark/bench-sessions.c @@ -0,0 +1,133 @@ +/* + * 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 +#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; + struct ltt_session *session; + + 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 = session_create(names[i], PATH1, getuid(), getgid()); + 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++) { + session = session_find_by_name(names[i]); + ret = system("echo 3 >/proc/sys/vm/drop_caches"); + tracepoint(destroy_session_start); + ret = session_destroy(session); + 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 new file mode 100644 index 000000000..9100fae57 --- /dev/null +++ b/benchmark/benchmark.c @@ -0,0 +1,295 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#include "benchmark.h" + +FILE *fp; +static double g_freq; + +static double calibrate_cpu_freq(void) +{ + int i, nb_calib = 10; + 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); +} + +static void open_logs(void) +{ + fp = fopen(RESULTS_FILE_NAME, "a"); + if (fp == NULL) { + perror("fopen benchmark"); + } +} + +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; + } + + return get_bench_time(time_destroy_session_start, time_destroy_session_end); +} + +/* + * Complete UST notification process time break down in different actions. + */ +void bench_print_ust_notification(void) +{ + double res, total = 0; + + fprintf(fp, "--- UST notification time ---\n"); + + if (time_ust_notify_mmap_start == 0 || time_ust_notify_mmap_stop == 0) { + goto no_data; + } + + res = get_bench_time(time_ust_notify_mmap_start, + time_ust_notify_mmap_stop); + fprintf(fp, "mmap() call time\n"); + fprintf(fp, "Time: %.20f sec.\n", res); + + total += res; + + if (time_ust_notify_perms_start == 0 || time_ust_notify_perms_stop == 0) { + goto no_data; + } + + res = get_bench_time(time_ust_notify_perms_start, + time_ust_notify_perms_stop); + fprintf(fp, "Setting permissions (chown/chmod)\n"); + fprintf(fp, "Time: %.20f sec.\n", res); + + total += res; + + if (time_ust_notify_shm_start == 0 || time_ust_notify_shm_stop == 0) { + goto no_data; + } + + res = get_bench_time(time_ust_notify_shm_start, + time_ust_notify_shm_stop); + fprintf(fp, "shm_open/ftruncate/fchmod\n"); + fprintf(fp, "Time: %.20f sec.\n", res); + + total += res; + + fprintf(fp, "Global UST nonification time\n"); + fprintf(fp, "Time: %.20f sec.\n", total); + return; + +no_data: + fprintf(fp, "NO DATA\n"); + return; +} + +/* + * Time taken by an UST apps to unregister. + */ +void bench_print_ust_unregister(void) +{ + double res; + + fprintf(fp, "--- UST unregister time ---\n"); + + if (time_ust_unregister_start == 0 || time_ust_unregister_stop == 0) { + goto no_data; + } + + res = get_bench_time(time_ust_unregister_start, time_ust_unregister_stop); + fprintf(fp, "UST unregister time\n"); + fprintf(fp, "Time: %.20f sec.\n", res); + return; + +no_data: + fprintf(fp, "NO DATA\n"); + return; +} + +/* + * This time value is only coherent is an UST application registered. + */ +void bench_print_ust_register(void) +{ + double res, total = 0; + + fprintf(fp, "--- UST registration time ---\n"); + + if (time_ust_register_start == 0 || time_ust_register_stop == 0) { + goto no_data; + } + + res = get_bench_time(time_ust_register_start, time_ust_register_stop); + fprintf(fp, "UST registration received and send to dispatch time\n"); + fprintf(fp, "Time: %.20f sec.\n", res); + + total += res; + + if (time_ust_dispatch_register_start == 0 || + time_ust_dispatch_register_stop == 0) { + goto no_data; + } + + res = get_bench_time(time_ust_dispatch_register_start, + time_ust_dispatch_register_stop); + fprintf(fp, "Dispatch UST registration request time\n"); + fprintf(fp, "Time: %.20f sec.\n", res); + + total += res; + + fprintf(fp, "--> Manage registration breakdown\n"); + + res = get_bench_time(time_ust_register_read_start, + time_ust_register_read_stop); + fprintf(fp, "read() from pipe time\n"); + fprintf(fp, "Time: %.20f sec.\n", res); + + total += res; + + res = get_bench_time(time_ust_register_add_start, + time_ust_register_add_stop); + fprintf(fp, "register_traceable_app time\n"); + fprintf(fp, "Time: %.20f sec.\n", res); + + total += res; + + res = get_bench_time(time_ust_register_done_start, + time_ust_register_done_stop); + fprintf(fp, "send register done command time\n"); + fprintf(fp, "Time: %.20f sec.\n", res); + + total += res; + + fprintf(fp, "Global time of an UST application registration\n"); + fprintf(fp, "Time: %.20f sec.\n", total); + return; + +no_data: + fprintf(fp, "NO DATA\n"); + return; +} + + +/* + * 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 = get_bench_time(time_sessiond_boot_start, time_sessiond_boot_end); + + fprintf(fp, "Inside main() from start to first pthread_join" + "(blocking state)\n"); + fprintf(fp, "Time: %.20f sec.\n", res); + + global_boot_time += res; + + res = get_bench_time(time_sessiond_th_kern_start, + time_sessiond_th_kern_poll); + + fprintf(fp, "Kernel thread from start to poll() (ready state)\n"); + fprintf(fp, "Time: %.20f sec.\n", res); + + global_boot_time += res; + + res = get_bench_time(time_sessiond_th_apps_start, + time_sessiond_th_apps_poll); + + fprintf(fp, "Application thread from start to poll() (ready state)\n"); + fprintf(fp, "Time: %.20f sec.\n", res); + + global_boot_time += res; + + res = get_bench_time(time_sessiond_th_cli_start, + time_sessiond_th_cli_poll); + + fprintf(fp, "Client thread from start to poll() (ready state)\n"); + fprintf(fp, "Time: %.20f sec.\n", res); + + global_boot_time += res; + + res = get_bench_time(time_sessiond_th_dispatch_start, + time_sessiond_th_dispatch_block); + + fprintf(fp, "Dispatch registration thread from start to poll()" + "(ready state)\n"); + fprintf(fp, "Time: %.20f sec.\n", res); + + global_boot_time += res; + + fprintf(fp, "Global Boot Time\n"); + fprintf(fp, "Time: %0.20f sec.\n", global_boot_time); +} diff --git a/benchmark/benchmark.h b/benchmark/benchmark.h new file mode 100644 index 000000000..bbdadbbd8 --- /dev/null +++ b/benchmark/benchmark.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef _BENCHMARK_H +#define _BENCHMARK_H + +#include +#include + +#include "cpu.h" +#include "measures.h" + +#define RESULTS_FILE_NAME "/tmp/lttng-bench-results.txt" + +extern FILE *fp; + +void bench_init(void); +void bench_close(void); +void bench_print_boot_process(void); +void bench_print_ust_register(void); +void bench_print_ust_unregister(void); +void bench_print_ust_notification(void); +double bench_get_create_session(void); +double bench_get_destroy_session(void); + +#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 new file mode 100644 index 000000000..02a8d99d3 --- /dev/null +++ b/benchmark/cpu.c @@ -0,0 +1,60 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#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; + struct timeval tvstart, tvstop; + cycles_t c_before, c_after; + unsigned long microseconds; + + memset(&tz, 0, sizeof(tz)); + + gettimeofday(&tvstart, &tz); + c_before = get_cycles(); + gettimeofday(&tvstart, &tz); + + sleep(1); + + gettimeofday(&tvstop, &tz); + c_after = get_cycles(); + gettimeofday(&tvstop, &tz); + + microseconds = ((tvstop.tv_sec - tvstart.tv_sec) * 1000000) + + (tvstop.tv_usec - tvstart.tv_usec); + + return (uint64_t) ((c_after - c_before) / microseconds); +} diff --git a/benchmark/cpu.h b/benchmark/cpu.h new file mode 100644 index 000000000..799ccdf30 --- /dev/null +++ b/benchmark/cpu.h @@ -0,0 +1,28 @@ +/* + * 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. + */ + +#ifndef _CPU_H +#define _CPU_H + +#include +#include + +uint64_t get_cpu_freq(void); +cycles_t get_cycles(void); + +#endif /* _CPU_H */ diff --git a/benchmark/hello b/benchmark/hello new file mode 100755 index 000000000..a687c1521 Binary files /dev/null and b/benchmark/hello differ diff --git a/benchmark/main.c b/benchmark/main.c new file mode 100644 index 000000000..1c176f84c --- /dev/null +++ b/benchmark/main.c @@ -0,0 +1,28 @@ +/* + * 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. + */ + +#include +#include +#include + +#include "benchmark.h" + +int main(int argc, char **argv) +{ + return 0; +} diff --git a/benchmark/measures.h b/benchmark/measures.h new file mode 100644 index 000000000..cbcac2204 --- /dev/null +++ b/benchmark/measures.h @@ -0,0 +1,127 @@ +/* + * 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. + */ + +#ifndef _MEASURES_H +#define _MEASURES_H + +/* Session daemon main() time */ +cycles_t time_sessiond_boot_start; +cycles_t time_sessiond_boot_end; + +/* Session daemon thread manage kconsumerd time */ +cycles_t time_sessiond_th_kcon_start; +cycles_t time_sessiond_th_kcon_poll; + +/* Session daemon thread manage kernel time */ +cycles_t time_sessiond_th_kern_start; +cycles_t time_sessiond_th_kern_poll; + +/* Session daemon thread manage apps time */ +cycles_t time_sessiond_th_apps_start; +cycles_t time_sessiond_th_apps_poll; + +/* Session daemon thread registration apps time */ +cycles_t time_sessiond_th_reg_start; +cycles_t time_sessiond_th_reg_poll; + +/* Session daemon thread registration apps time */ +cycles_t time_sessiond_th_dispatch_start; +cycles_t time_sessiond_th_dispatch_block; + +/* Session daemon thread manage client time */ +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; + +/* + * UST registration time + * + * Start time is taken *after* the poll() has detected activity on the apps + * socket and right *before* the accept(). There is a malloc() after that + * accept and then we recv() the request from the client. We need to measure + * the complete process. + */ +cycles_t time_ust_register_start; +/* + * The stop time is measured right after the futex() wake up. + */ +cycles_t time_ust_register_stop; + +/* + * * UST unregister time + * */ +cycles_t time_ust_unregister_start; +cycles_t time_ust_unregister_stop; + +/* + * UST dispatch registration request time + * + * Start time taken *after* the dequeue which is a blocking call. + */ +cycles_t time_ust_dispatch_register_start; +/* + * Stop time taken *before* the futex() wait so at this point, the registration + * was sent to the manage apps thread. + */ +cycles_t time_ust_dispatch_register_stop; + +/* + * UST managing registration time + */ +/* read() from pipe */ +cycles_t time_ust_register_read_start; +cycles_t time_ust_register_read_stop; +/* register_traceable_app() time */ +cycles_t time_ust_register_add_start; +cycles_t time_ust_register_add_stop; +/* send register done command */ +cycles_t time_ust_register_done_start; +cycles_t time_ust_register_done_stop; + +/* + * UST notification time (using the shm/futex scheme). Those times were break + * down in seperate time for each big action step. + * + * Start time taken *before* we create/get the SHM mmap. + */ +cycles_t time_ust_notify_apps_start; +/* + * Stop time taken after waiting all processes (futex_wait_update()). + */ +cycles_t time_ust_notify_apps_stop; +/* mmap() call */ +cycles_t time_ust_notify_mmap_start; +cycles_t time_ust_notify_mmap_stop; +/* Permissions time (chmod/chown) */ +cycles_t time_ust_notify_perms_start; +cycles_t time_ust_notify_perms_stop; +/* Fork process */ +cycles_t time_ust_notify_fork_start; +cycles_t time_ust_notify_fork_stop; +/* shm_open call */ +cycles_t time_ust_notify_shm_start; +cycles_t time_ust_notify_shm_stop; + +#endif /* _MEASURES_H */ diff --git a/benchmark/run-boot-time.sh b/benchmark/run-boot-time.sh new file mode 100755 index 000000000..4871ab90b --- /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="lttng-sessiond" +RESULTS_PATH="/tmp/lttng-bench-results.txt" +BASEDIR=`dirname $0` + +echo "Starting session daemon" + +BENCH_BOOT_PROCESS=1 $BASEDIR/../lttng-sessiond/$SESSIOND_BIN -v >/dev/null 2>&1 & + +PID_SESSIOND=$! +if [ -z $PID_SESSIOND ]; then + echo -e '\e[1;31mFAILED\e[0m' + exit 1 +else + echo -e "\e[1;32mOK\e[0m" + echo "PID session daemon: $PID_SESSIOND" +fi + +# Wait for the benchmark to run +echo -n "Waiting." +sleep 1 +echo -n "." +sleep 1 +echo "." +sleep 1 + +kill $PID_SESSIOND + +wait $PID_SESSIOND + +echo "Benchmarks done in $RESULTS_PATH" + +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/run-ust-notify.sh b/benchmark/run-ust-notify.sh new file mode 100755 index 000000000..723ed2925 --- /dev/null +++ b/benchmark/run-ust-notify.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="lttng-sessiond" +RESULTS_PATH="/tmp/lttng-bench-results.txt" +BASEDIR=`dirname $0` + +echo "Session daemon boot" + +BENCH_UST_NOTIFY=1 $BASEDIR/../lttng-sessiond/$SESSIOND_BIN -v >/dev/null 2>&1 & + +PID_SESSIOND=$! +if [ -z $PID_SESSIOND ]; then + echo -e '\e[1;31mFAILED\e[0m' + exit 1 +else + echo -e "\e[1;32mOK\e[0m" + echo "PID session daemon: $PID_SESSIOND" +fi + +# Session daemon need to boot up and run benchmark +echo -n "Waiting." +sleep 1 +echo -n "." +sleep 1 +echo "." +sleep 1 + +kill $PID_SESSIOND + +wait $PID_SESSIOND + +echo "Benchmarks done in $RESULTS_PATH" + +exit 0 diff --git a/benchmark/run-ust-register.sh b/benchmark/run-ust-register.sh new file mode 100755 index 000000000..96d70a268 --- /dev/null +++ b/benchmark/run-ust-register.sh @@ -0,0 +1,53 @@ +#!/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="lttng-sessiond" +RESULTS_PATH="/tmp/lttng-bench-results.txt" +BASEDIR=`dirname $0` + +echo "Session daemon boot" +BENCH_UST_REGISTER=1 $BASEDIR/../lttng-sessiond/$SESSIOND_BIN -v >/dev/null 2>&1 & + +PID_SESSIOND=$! +if [ -z $PID_SESSIOND ]; then + echo -e '\e[1;31mFAILED\e[0m' + exit 1 +else + echo -e "\e[1;32mOK\e[0m" + echo "PID session daemon: $PID_SESSIOND" +fi + +# Session daemon need to boot up and run benchmark +echo -n "Waiting." +sleep 1 +echo -n "." +sleep 1 +echo "." +sleep 1 + +# Start libust instrumented application to register. +UST_AUTOPROBE=1 UST_TRACE=1 ./$BASEDIR/hello + +kill $PID_SESSIOND + +wait $PID_SESSIOND + +echo "Benchmarks done in $RESULTS_PATH" + +exit 0 diff --git a/benchmark/runall.sh b/benchmark/runall.sh new file mode 100755 index 000000000..037ac9e3e --- /dev/null +++ b/benchmark/runall.sh @@ -0,0 +1,50 @@ +#!/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. +# + +#### ADD TESTS HERE #### + +test_suite=( "run-boot-time.sh" "run-sessions.sh" "run-ust-register.sh" \ + "run-ust-notify.sh" ) + +#### END TESTS HERE #### + +RESULTS_PATH="/tmp/lttng-bench-results.txt" +BASEDIR=`dirname $0` + +if [ -e $RESULTS_PATH ]; then + mv -v $RESULTS_PATH "$RESULTS_PATH.`date +%s`.txt" +fi + +echo "" + +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 53f21ab09..bd65c55ee 100644 --- a/configure.ac +++ b/configure.ac @@ -57,6 +57,11 @@ AC_CHECK_LIB([popt], [poptGetContext], [], [AC_MSG_ERROR([Cannot find libpopt. Use [LDFLAGS]=-Ldir to specify its location.])] ) +# Needed for benchmark time +AC_CHECK_DECL([caa_get_cycles], [], + [AC_MSG_ERROR([liburcu liburcu_version or newer is needed])], [[#include ]] +) + # URCU library version needed or newer liburcu_version=">= 0.6.7" @@ -133,6 +138,7 @@ AC_CONFIG_FILES([ Makefile doc/Makefile include/Makefile + benchmark/Makefile src/Makefile src/common/Makefile src/common/kernel-ctl/Makefile diff --git a/src/bin/lttng-sessiond/Makefile.am b/src/bin/lttng-sessiond/Makefile.am index 88b7c6974..1e449476c 100644 --- a/src/bin/lttng-sessiond/Makefile.am +++ b/src/bin/lttng-sessiond/Makefile.am @@ -1,4 +1,5 @@ -AM_CPPFLAGS = -DINSTALL_BIN_PATH=\""$(bindir)"\" \ +AM_CPPFLAGS = -I$(top_srcdir)/benchmark \ + -DINSTALL_BIN_PATH=\""$(bindir)"\" \ -DINSTALL_LIB_PATH=\""$(libdir)"\" AM_CFLAGS = -fno-strict-aliasing @@ -32,6 +33,7 @@ lttng_sessiond_LDADD = -lrt -lurcu-common -lurcu \ $(top_builddir)/src/common/kernel-ctl/libkernel-ctl.la \ $(top_builddir)/src/common/hashtable/libhashtable.la \ $(top_builddir)/src/common/libcommon.la \ + $(top_builddir)/benchmark/liblttng-benchmark.la \ $(top_builddir)/src/common/libcompat.la if HAVE_LIBLTTNG_UST_CTL diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 9b2d1fe00..170dcc587 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -75,6 +75,8 @@ struct consumer_data { char cmd_unix_sock_path[PATH_MAX]; }; +#include "benchmark.h" + /* Const values */ const char default_home_dir[] = DEFAULT_HOME_DIR; const char default_tracing_group[] = DEFAULT_TRACING_GROUP; @@ -427,6 +429,25 @@ static void cleanup(void) close(thread_quit_pipe[0]); close(thread_quit_pipe[1]); + /* OUTPUT BENCHMARK RESULTS */ + bench_init(); + + if (getenv("BENCH_UST_NOTIFY")) { + bench_print_ust_notification(); + } + + if (getenv("BENCH_UST_REGISTER")) { + bench_print_ust_register(); + bench_print_ust_unregister(); + } + + if (getenv("BENCH_BOOT_PROCESS")) { + bench_print_boot_process(); + } + + bench_close(); + /* END BENCHMARK */ + /* */ DBG("%c[%d;%dm*** assert failed :-) *** ==> %c[%dm%c[%d;%dm" "Matthew, BEET driven development works!%c[%dm", @@ -609,6 +630,8 @@ static int notify_ust_apps(int active) DBG("Notifying applications of session daemon state: %d", active); + tracepoint(ust_notify_apps_start); + /* See shm.c for this call implying mmap, shm and futex calls */ wait_shm_mmap = shm_ust_get_mmap(wait_shm_path, is_root); if (wait_shm_mmap == NULL) { @@ -618,6 +641,8 @@ static int notify_ust_apps(int active) /* Wake waiting process */ futex_wait_update((int32_t *) wait_shm_mmap, active); + tracepoint(ust_notify_apps_stop); + /* Apps notified successfully */ return 0; @@ -790,6 +815,8 @@ static void *thread_manage_kernel(void *data) char tmp; struct lttng_poll_event events; + tracepoint(sessiond_th_kern_start); + DBG("Thread manage kernel started"); ret = create_thread_poll_set(&events, 2); @@ -824,6 +851,8 @@ static void *thread_manage_kernel(void *data) /* Zeroed the poll events */ lttng_poll_reset(&events); + tracepoint(sessiond_th_kern_poll); + /* Poll infinite value of time */ ret = lttng_poll_wait(&events, -1); if (ret < 0) { @@ -892,6 +921,8 @@ static void *thread_manage_consumer(void *data) struct lttng_poll_event events; struct consumer_data *consumer_data = data; + tracepoint(sessiond_th_kcon_start); + DBG("[thread] Manage consumer started"); ret = lttcomm_listen_unix_sock(consumer_data->err_sock); @@ -915,6 +946,8 @@ static void *thread_manage_consumer(void *data) nb_fd = LTTNG_POLL_GETNB(&events); + tracepoint(sessiond_th_kcon_poll); + /* Inifinite blocking call, waiting for transmission */ ret = lttng_poll_wait(&events, -1); if (ret < 0) { @@ -1047,6 +1080,8 @@ static void *thread_manage_apps(void *data) struct ust_command ust_cmd; struct lttng_poll_event events; + tracepoint(sessiond_th_apps_start); + DBG("[thread] Manage application started"); rcu_register_thread(); @@ -1070,6 +1105,8 @@ static void *thread_manage_apps(void *data) DBG("Apps thread polling on %d fds", nb_fd); + tracepoint(sessiond_th_apps_poll); + /* Inifinite blocking call, waiting for transmission */ ret = lttng_poll_wait(&events, -1); if (ret < 0) { @@ -1093,13 +1130,16 @@ static void *thread_manage_apps(void *data) ERR("Apps command pipe error"); goto error; } else if (revents & LPOLLIN) { + tracepoint(ust_register_read_start); /* Empty pipe */ ret = read(apps_cmd_pipe[0], &ust_cmd, sizeof(ust_cmd)); if (ret < 0 || ret < sizeof(ust_cmd)) { perror("read apps cmd pipe"); goto error; } + tracepoint(ust_register_read_stop); + tracepoint(ust_register_add_start); /* Register applicaton to the session daemon */ ret = ust_app_register(&ust_cmd.reg_msg, ust_cmd.sock); @@ -1108,7 +1148,9 @@ static void *thread_manage_apps(void *data) } else if (ret < 0) { break; } + tracepoint(ust_register_add_stop); + tracepoint(ust_register_done_start); /* * Validate UST version compatibility. */ @@ -1141,7 +1183,7 @@ static void *thread_manage_apps(void *data) DBG("Apps with sock %d added to poll set", ust_cmd.sock); } - + tracepoint(ust_register_done_stop); break; } } else { @@ -1150,6 +1192,8 @@ static void *thread_manage_apps(void *data) * the event at poll_wait. */ if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { + tracepoint(ust_unregister_start); + /* Removing from the poll set */ ret = lttng_poll_del(&events, pollfd); if (ret < 0) { @@ -1158,6 +1202,8 @@ static void *thread_manage_apps(void *data) /* Socket closed on remote end. */ ust_app_unregister(pollfd); + + tracepoint(ust_unregister_stop); break; } } @@ -1186,6 +1232,8 @@ static void *thread_dispatch_ust_registration(void *data) struct cds_wfq_node *node; struct ust_command *ust_cmd = NULL; + tracepoint(sessiond_th_dispatch_start); + DBG("[thread] Dispatch UST command started"); while (!dispatch_thread_exit) { @@ -1193,6 +1241,8 @@ static void *thread_dispatch_ust_registration(void *data) futex_nto1_prepare(&ust_cmd_queue.futex); do { + tracepoint(sessiond_th_dispatch_block); + /* Dequeue command for registration */ node = cds_wfq_dequeue_blocking(&ust_cmd_queue.queue); if (node == NULL) { @@ -1201,6 +1251,8 @@ static void *thread_dispatch_ust_registration(void *data) break; } + tracepoint(ust_dispatch_register_start); + ust_cmd = caa_container_of(node, struct ust_command, node); DBG("Dispatching UST registration pid:%d ppid:%d uid:%d" @@ -1231,6 +1283,8 @@ static void *thread_dispatch_ust_registration(void *data) free(ust_cmd); } while (node != NULL); + tracepoint(ust_dispatch_register_stop); + /* Futex wait on queue. Blocking call on futex() */ futex_nto1_wait(&ust_cmd_queue.futex); } @@ -1254,6 +1308,8 @@ static void *thread_registration_apps(void *data) */ struct ust_command *ust_cmd = NULL; + tracepoint(sessiond_th_reg_start); + DBG("[thread] Manage application registration started"); ret = lttcomm_listen_unix_sock(apps_sock); @@ -1287,6 +1343,8 @@ static void *thread_registration_apps(void *data) while (1) { DBG("Accepting application registration"); + tracepoint(sessiond_th_reg_poll); + nb_fd = LTTNG_POLL_GETNB(&events); /* Inifinite blocking call, waiting for transmission */ @@ -1312,6 +1370,9 @@ static void *thread_registration_apps(void *data) ERR("Register apps socket poll error"); goto error; } else if (revents & LPOLLIN) { + /* Registration starts here. Recording cycles */ + tracepoint(ust_register_start); + sock = lttcomm_accept_unix_sock(apps_sock); if (sock < 0) { goto error; @@ -1361,6 +1422,8 @@ static void *thread_registration_apps(void *data) * barrier with the exchange in cds_wfq_enqueue. */ futex_nto1_wake(&ust_cmd_queue.futex); + + tracepoint(ust_register_stop); } } } @@ -3376,14 +3439,18 @@ static int process_client_msg(struct command_ctx *cmd_ctx) } case LTTNG_CREATE_SESSION: { + tracepoint(create_session_start); ret = cmd_create_session(cmd_ctx->lsm->session.name, cmd_ctx->lsm->session.path, &cmd_ctx->creds); + tracepoint(create_session_end); break; } case LTTNG_DESTROY_SESSION: { + tracepoint(destroy_session_start); ret = cmd_destroy_session(cmd_ctx->session, cmd_ctx->lsm->session.name); + tracepoint(destroy_session_end); break; } case LTTNG_LIST_DOMAINS: @@ -3534,6 +3601,8 @@ static void *thread_manage_clients(void *data) struct command_ctx *cmd_ctx = NULL; struct lttng_poll_event events; + tracepoint(sessiond_th_cli_start); + DBG("[thread] Manage client started"); rcu_register_thread(); @@ -3568,6 +3637,8 @@ static void *thread_manage_clients(void *data) while (1) { DBG("Accepting client command ..."); + tracepoint(sessiond_th_cli_poll); + nb_fd = LTTNG_POLL_GETNB(&events); /* Inifinite blocking call, waiting for transmission */ @@ -4158,6 +4229,8 @@ int main(int argc, char **argv) void *status; const char *home_path; + tracepoint(sessiond_boot_start); + init_kernel_workarounds(); rcu_register_thread(); @@ -4419,6 +4492,8 @@ int main(int argc, char **argv) goto exit_kernel; } + tracepoint(sessiond_boot_end); + ret = pthread_join(kernel_thread, &status); if (ret != 0) { perror("pthread_join"); diff --git a/src/bin/lttng-sessiond/shm.c b/src/bin/lttng-sessiond/shm.c index 77c09995c..0bf3ff58f 100644 --- a/src/bin/lttng-sessiond/shm.c +++ b/src/bin/lttng-sessiond/shm.c @@ -28,6 +28,8 @@ #include +#include "benchmark.h" +#include "measures.h" #include "shm.h" /* @@ -43,6 +45,8 @@ static int get_wait_shm(char *shm_path, size_t mmap_size, int global) int wait_shm_fd, ret; mode_t mode; + tracepoint(ust_notify_perms_start); + /* Default permissions */ mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; @@ -88,6 +92,9 @@ static int get_wait_shm(char *shm_path, size_t mmap_size, int global) */ umask(~mode); + tracepoint(ust_notify_perms_stop); + + tracepoint(ust_notify_shm_start); /* * Try creating shm (or get rw access). We don't do an exclusive open, * because we allow other processes to create+ftruncate it concurrently. @@ -110,6 +117,8 @@ static int get_wait_shm(char *shm_path, size_t mmap_size, int global) exit(EXIT_FAILURE); } + tracepoint(ust_notify_shm_stop); + DBG("Got the wait shm fd %d", wait_shm_fd); return wait_shm_fd; @@ -139,9 +148,12 @@ char *shm_ust_get_mmap(char *shm_path, int global) goto error; } + tracepoint(ust_notify_mmap_start); + wait_shm_mmap = mmap(NULL, mmap_size, PROT_WRITE | PROT_READ, MAP_SHARED, wait_shm_fd, 0); + tracepoint(ust_notify_mmap_stop); /* close shm fd immediately after taking the mmap reference */ ret = close(wait_shm_fd); if (ret) {