putting my money where my mouth is (re: the novel idea)
Andreas Ericsson
ae at op5.se
Mon May 9 17:43:58 CEST 2005
Sorry Sean, but the output is basically just nonsense.
You really need to use a real plugin while doing this test since it's
quite obvious that calling a function that does nothing is a lot faster
as an in-core function than as an external program. My experiment showed
benchmarks between two different ways of executing external programs, so
it's ok for that to use nonsense data that returns quickly, while yours
focus on the entire execution cycle from execution-start to
execution-end. You really need to do something a bit more real to
investigate the time gained for that (hint, the most time is spent in
the plugin).
Re-run the test with check_rand.c (you'll find it at
http://oss.op5.se/nagios). It should compile with the exact same options
as check_hello, but you'll need to remove the if(argc == 1) conditions
since that robs it of the random sleep that makes it work as much like a
real plugin as is humanly possible. Compare it with benchmarks from
mthread and mplex when running that same plugin and you'll see why
parallellization is the paramount issue here. The overhead of invoking
fork(), select(), pthread_create() or popen() doesn't really matter all
that much.
To save you the trouble of actually running check_rand, I'll tell you
right now that both mthread and mplex will finish in a maximum of 572
seconds (give or take one or two), no matter how many threads you run,
while your testcase (down it to 100 executions) will complete in a
minimum of below 1 second and a maximum of 57100 seconds (roughly 15
hours). Actual value should be x * (571 * 0.125) + (x * 6) where x =
executions, which gives us (roughly) 7750 seconds (2.2 hours) for your
case. That's with a plugin behaving somewhat properly, but randomly
taking quite some time to complete. Your program won't have any chance
to fire up new checks as old ones complete either (err, that's what it
does, but in a serial manner), while both mthread and mplex can be
modified only slightly to do just that and thus scales far better.
It would be more useful if the testcase at least did a pthread_create()
to land on the resolved function and then preferrably a pthread_join()
to reap the returned value, as this is how an implementation such as
this would work in practice.
sean finney wrote:
> so, in light of last night's discussion, i decided to throw together
> a small proof of concept to illustrate my point. attached are three
> files:
>
> - check_hello.c, a simple "plugin" that prints hello world.
> - a Makefile that illustrates just how easy it is to build a
> shared object in the way i suggested
> - dltest.c, a program that benchmarks one vs. the other by
> executing the system/function calls 1000 times and recording
> elapsed time in microseconds (i'd recommend piping stdout
> to /dev/null)
>
> this is what i get:
>
> copelandia[~/nagiosplug/plugtest]09:41:03$ ./dltest >/dev/null
> dlopen: 131
> system: 3698327
>
>
> sean
>
>
> ------------------------------------------------------------------------
>
> #include <stdio.h>
>
> int main(){
> printf("hello, world!\n");
> }
>
>
> ------------------------------------------------------------------------
>
> dltest: dltest.c
> gcc -g -o dltest dltest.c -ldl
>
> check_hello.o: check_hello.c
> gcc -c check_hello.c
>
> check_hello.shared.o: check_hello.c
> gcc -c -fPIC -Dmain=check_hello check_hello.c
>
> check_hello: check_hello.o
> gcc -o check_hello check_hello.o
>
> check_hello.so: check_hello.shared.o
> ld -shared -o check_hello.so check_hello.o
>
> test:
> ./dltest
>
>
> ------------------------------------------------------------------------
>
> #include <stdio.h>
> #include <dlfcn.h>
> #include <sys/time.h>
> #include <time.h>
>
> const char *ourgv[24] ={ "check_hello", NULL };
> const char *ourcmd = "check_hello";
> extern int optind;
>
> int main(){
> int i;
> struct timeval start, midway, end;
> long total_func, total_sys;
> void *libhandle=NULL;
> int (*check_func)(int, const char**)=NULL;
> libhandle=dlopen("./check_hello.so", RTLD_NOW);
> if(libhandle==NULL){
> fprintf(stderr, "libhandle was null. damn. %s\n", dlerror());
> }
> *(void**)(&check_func) =dlsym(libhandle, "check_hello");
> if(check_func==NULL || *check_func == NULL){
> fprintf(stderr, "check_func was null. damn. %s\n", dlerror());
> }
>
> gettimeofday(&start, NULL);
> for(i=0; i<1000; i++){
> system(ourcmd);
> }
> gettimeofday(&midway, NULL);
> for(i=0; i<1000; i++){
> (*check_func)(1, ourgv);
> }
> gettimeofday(&end, NULL);
>
> total_sys = ((midway.tv_sec - start.tv_sec)*1000000) + (midway.tv_usec - start.tv_usec);
> total_func = ((end.tv_sec - midway.tv_sec)*1000000) + (end.tv_usec - midway.tv_usec);
>
> fprintf(stderr, "dlopen: %ld\n", total_func);
> fprintf(stderr, "system: %ld\n", total_sys);
> }
--
Andreas Ericsson andreas.ericsson at op5.se
OP5 AB www.op5.se
Lead Developer
-------------------------------------------------------
This SF.Net email is sponsored by: NEC IT Guy Games.
Get your fingers limbered up and give it your best shot. 4 great events, 4
opportunities to win big! Highest score wins.NEC IT Guy Games. Play to
win an NEC 61 plasma display. Visit http://www.necitguy.com/?r=20
More information about the Developers
mailing list