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 <[email protected]> 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 [email protected] http://mailman.verplant.org/listinfo/collectd
