Hi list, I had a short conversation with Kimo about sysctlnametomib() versus sysctlbyname() [1] and I wanted to check if there is really a difference. At the same time I 'benchmarked' some other plugins. I think that a tool like this might aid in collectd plugin development.
I added a -b <N> flag to the collectd which runs "benchmark" by iterating the read loop N times and calculates total CPU time. To collect results I wrote a simple Makefile script. I ran benchmarks on a FreeBSD 8.2 system. I ran 5 instances of collectd simultaneously and every instance ran 100000 iterations. The collectd was configured to use only the plugin in question. I set the time interval as small as possible so that there weren't too many 'Not sleeping because the next interval is 0.000 seconds in the past!' reports. Results (seconds of CPU time): Plugin: Mean: Variance: cpu.in 10.03281 0.00035 cs-sysctl.in 3.49531 0.00312 (uses sysctlnametomib() and sysctl()) cs.in 3.74687 0.00043 (uses sysctlbyname()) disk.in 8.10156 0.00020 interface.in 13.22031 0.00062 load.in 3.31562 0.00556 memory.in 8.67500 0.00041 swap.in 1.82500 0.00761 tcpconns.in 16.11094 0.00162 uptime.in 3.16562 0.00160 users.in 13.93281 0.00080 zfs-arc.in 16.66094 0.00294 (modified to use sysctlbyname()) zfs-arc.in 13.26250 0.00158 (mod. sysctlnametomib() and sysctl()) We can see that plugins use different amount of CPU. This is not real benchmark because values are not comparable to those produced on other systems. However we can easily calculate that if we use 30 seconds time interval 100000 iterations would mean 34 hours of real time, and we can see that some plugins are quite efficient. I would like to point out two things about sysctl calls. First, lets compare ContextSwitch plugin and my sysctl plugin [2]. It seems that when a plugin uses only one sysctl entry there is no significant difference between sysctlnametomib() and sysctlbyname(). Maybe collectd overhead is larger that the small performance gain. Second, we can see that zfs-arc plugin is faster when sysctlnametomib() is used. The plugin reads 16 different sysctl values on every read action and now the difference is noticeable. There are two attachments: - collectd-bench.patch (patch against version 5.0.0) - time-suite.tgz I didn't post zfs-arc plugin patches because they are poor quality. I will return to this later. Thanks for your time. Toni Ylenius [1] http://mailman.verplant.org/pipermail/collectd/2011-June/004542.html [2] https://collectd.org/gerrit/#change,10
commit 4d24d3d4a2a6cdd5d71afdabe0ac6cfb92b49c81 Author: Toni Ylenius <toni.ylen...@iki.fi> Date: Sat Sep 3 22:49:17 2011 +0300 Added benchmark -b flag to collectd. diff --git a/configure.in b/configure.in index 8db24ca..d7d17ca 100644 --- a/configure.in +++ b/configure.in @@ -126,7 +126,7 @@ AC_HEADER_SYS_WAIT AC_HEADER_DIRENT AC_HEADER_STDBOOL -AC_CHECK_HEADERS(stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h sys/isa_defs.h) +AC_CHECK_HEADERS(stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h time.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h sys/isa_defs.h) # For ping library AC_CHECK_HEADERS(netinet/in_systm.h, [], [], diff --git a/src/collectd.c b/src/collectd.c index d33d1d6..94ac319 100644 --- a/src/collectd.c +++ b/src/collectd.c @@ -18,6 +18,7 @@ * Authors: * Florian octo Forster <octo at verplant.org> * Alvaro Barcellos <alvaro.barcellos at gmail.com> + * Toni Ylenius <toni.ylenius at iki.fi> **/ #include "collectd.h" @@ -25,6 +26,7 @@ #include <sys/types.h> #include <sys/socket.h> +#include <time.h> #include <netdb.h> #include <pthread.h> @@ -47,6 +49,7 @@ kstat_ctl_t *kc; #endif /* HAVE_LIBKSTAT */ static int loop = 0; +static int iter = -1; static void *do_flush (void __attribute__((unused)) *arg) { @@ -277,6 +280,7 @@ static void exit_usage (int status) " Default: "CONFIGFILE"\n" " -t Test config and exit.\n" " -T Test plugin read and exit.\n" + " -b <n> Benchmark with <n> iterations.\n" " -P <file> PID-file.\n" " Default: "PIDFILE"\n" #if COLLECT_DAEMON @@ -332,6 +336,13 @@ static int do_loop (void) struct timespec ts_wait = { 0, 0 }; cdtime_t now; + + /* Stop looping when max iterations is reached */ + if (iter >= 0 && iter == 0) + return(0); + else if (iter >= 0) + iter--; + #if HAVE_LIBKSTAT update_kstat (); #endif @@ -412,6 +423,9 @@ int main (int argc, char **argv) char *configfile = CONFIGFILE; int test_config = 0; int test_readall = 0; + int iter_times = 0; /* 0 = do not benchmark */ + clock_t start_clk = 0; + clock_t end_clk = 0; const char *basedir; #if COLLECT_DAEMON struct sigaction sig_chld_action; @@ -425,7 +439,7 @@ int main (int argc, char **argv) { int c; - c = getopt (argc, argv, "htTC:" + c = getopt (argc, argv, "htb:TC:" #if COLLECT_DAEMON "fP:" #endif @@ -449,6 +463,12 @@ int main (int argc, char **argv) daemonize = 0; #endif /* COLLECT_DAEMON */ break; + case 'b': + iter_times = atoi (optarg); +#if COLLECT_DAEMON + daemonize = 0; +#endif /* COLLECT_DAEMON */ + break; #if COLLECT_DAEMON case 'P': global_option_set ("PIDFile", optarg); @@ -508,6 +528,15 @@ int main (int argc, char **argv) if (test_config) return (0); + if (iter_times < 0) + { + fprintf (stderr, "Benchmark iteration number should be a " + "positive number.\n"); + return (1); + } + else if (iter_times > 0) + iter = iter_times; + #if COLLECT_DAEMON /* * fork off child @@ -601,6 +630,10 @@ int main (int argc, char **argv) /* * run the actual loops */ + if (iter_times > 0) + { + start_clk = clock(); + } do_init (); if (test_readall) @@ -618,6 +651,12 @@ int main (int argc, char **argv) INFO ("Exiting normally."); do_shutdown (); + if (iter_times > 0) + { + end_clk = clock(); + INFO ("CPU time used: %.6f", + ((double) (end_clk - start_clk)) / CLOCKS_PER_SEC); + } #if COLLECT_DAEMON if (daemonize) diff --git a/src/collectd.pod b/src/collectd.pod index e36dcdf..cf7f7ea 100644 --- a/src/collectd.pod +++ b/src/collectd.pod @@ -36,6 +36,11 @@ config file. A return code not equal to zero indicates an error. Test the plugin read callbacks only. The program immediately exits after invoking the read callbacks once. A return code not equal to zero indicates an error. +=item B<-b> I<E<lt>nE<gt>> + +Runs benchmark with B<n> number of iterations and exists. Does not daemonize. +After the execution prints used CPU time. + =item B<-P> I<E<lt>pid-fileE<gt>> Specify an alternative pid file. This overwrites any settings in the config
time-suite.tgz
Description: application/compressed-tar
_______________________________________________ collectd mailing list collectd@verplant.org http://mailman.verplant.org/listinfo/collectd