From owner-cvs-all Sat Oct 10 20:37:44 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id UAA07216 for cvs-all-outgoing; Sat, 10 Oct 1998 20:37:44 -0700 (PDT) (envelope-from owner-cvs-all@FreeBSD.ORG) Received: from spinner.netplex.com.au (spinner.netplex.com.au [202.12.86.3]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id UAA07204; Sat, 10 Oct 1998 20:37:18 -0700 (PDT) (envelope-from peter@netplex.com.au) Received: from spinner.netplex.com.au (localhost [127.0.0.1]) by spinner.netplex.com.au (8.9.1/8.9.1/Spinner) with ESMTP id LAA18511; Sun, 11 Oct 1998 11:09:41 +0800 (WST) (envelope-from peter@spinner.netplex.com.au) Message-Id: <199810110309.LAA18511@spinner.netplex.com.au> X-Mailer: exmh version 2.0.2 2/24/98 To: Bruce Evans cc: cvs-committers@FreeBSD.ORG, cvs-all@FreeBSD.ORG Subject: Re: cvs commit: src/lib/libc/gen popen.c In-reply-to: Your message of "Sat, 10 Oct 1998 12:30:45 MST." <199810101930.MAA28329@freefall.freebsd.org> Date: Sun, 11 Oct 1998 11:09:41 +0800 From: Peter Wemm Sender: owner-cvs-all@FreeBSD.ORG Precedence: bulk Bruce Evans wrote: > bde 1998/10/10 12:30:45 PDT > > Modified files: > lib/libc/gen popen.c > Log: > vfork -> fork. The child calls execl() which calls malloc(), so > vfork() can't be used. We could use alloca() in execl() so that > it can be called between vfork() and execve(), but a "portable" > popen() shouldn't depend on this. Calling execle() instead of > execl() should be fairly safe, since execle() is supposed to be > callable from signal handlers and signal handlers can't call > malloc(). However, execle() is broken. Why not fix it properly by not using execl()? Index: popen.c =================================================================== RCS file: /home/ncvs/src/lib/libc/gen/popen.c,v retrieving revision 1.10 diff -u -r1.10 popen.c --- popen.c 1998/10/10 19:30:45 1.10 +++ popen.c 1998/10/11 02:11:46 @@ -62,6 +62,7 @@ struct pid *cur; FILE *iop; int pdes[2], pid, twoway; + char *argv[4]; /* * Lite2 introduced two-way popen() pipes using socketpair(). @@ -84,7 +85,12 @@ return (NULL); } - switch (pid = fork()) { + argv[0] = "sh"; + argv[1] = "-c"; + argv[2] = command; + argv[3] = NULL; + + switch (pid = vfork()) { case -1: /* Error. */ (void)close(pdes[0]); (void)close(pdes[1]); @@ -116,7 +122,7 @@ } (void)close(pdes[1]); } - execl(_PATH_BSHELL, "sh", "-c", command, NULL); + execv(_PATH_BSHELL, argv); _exit(127); /* NOTREACHED */ } fork() is significantly slower than vfork(), especially with a complex address space with lots of maps that fork() has to clone. It'll all the malloc calls in execl() too. On statically linked binaries, fork+exit takes around 5 times longer than vfork+exit: $Id: lat_proc.c,v 1.5 1995/11/08 01:40:21 lm Exp $ Static Process fork+exit: 302 microseconds Static Process vfork+exit: 63 microseconds Static Process fork+execve: 1250 microseconds Static Process vfork+execve: 994 microseconds Static Process fork+/bin/sh -c: 5977 microseconds Static Process vfork+/bin/sh -c: 5156 microseconds While with a dynamically linked binary (and hence a more complicated address space to clone and set up in copy-on-write mode), fork() takes 13.3 times longer: $Id: lat_proc.c,v 1.5 1995/11/08 01:40:21 lm Exp $ Process fork+exit: 848 microseconds Process vfork+exit: 64 microseconds Process fork+execve: 5712 microseconds Process vfork+execve: 5090 microseconds Process fork+/bin/sh -c: 10935 microseconds Process vfork+/bin/sh -c: 9410 microseconds Of course, fork() + exec() is the issue here, so fork speed isn't the whole picture. When combined with exec, it works out that the combination is between around 10% and 20% slower than the vfork combination. These numbers are from an ELF-reasonably-current system, on a 686MX-200 system (A pentium-200 class cpu). I don't want to start benchmark wars [again], but this (modified) lmbench test shows it's worthwhile for programs that do a lot of popen(). (The mods to lmbench were to make the test run for 10 times longer for better stability, and an added vfork() test.) My PPro-200 does much better in UP mode, but worse in SMP mode - no real suprise there. Cheers, -Peter To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe cvs-all" in the body of the message