From: newsham AT lava DOT net (Tim Newsham) Subject: fork speed 29 Oct 1997 18:12:14 -0800 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit To: gnu-win32 AT cygnus DOT com Cc: noer AT cygnus DOT com Hi, I've been doing some profiling of the fork() call in cygwin.dll to find out why it is so slow and to see what could be done to speed it up. I am using a pentium 133mhz with 32 megs of ram. My observations are: From fork() entry to parent exit averages about 50 msec. from fork entry to child exit averages about 75 msec. 75 msec is a lot of computer time. I broke down the time a bit. The biggest events are: enter fork CreateProcess -----> do some copying resume child -----> child enters crt0 wait for child child longjmps to fork code <----- signal parent to continue more copying wait for parent return init uinfo init socket return the parent takes about 10msec doing the initial steups until waiting for the child. The child enters crt0 about 45msec after the fork started and quickly longjmps to the fork code and signals the parent to continue (at about 47msec the parent continues). The parent then finishes its work at about 50msec. The child side gets signalled by the parent at around 50msec. It then initializes uinfo until 65msec after fork, and initializes sockets until about 75msec after the fork. Then it returns at about 75msec after the fork. I have yet to look into where the time goes when doing the CreateProcess. This seems to be taking up about 35msec, roughly half the fork time, between when CreateProcess is called and the child actually starts running. I did look into the child initialization functions to init uinfo and init sockets a bit though. The init uinfo function reads in /etc/passwd and /etc/group and figures out what the user id is for the current process. This seems a bit wasteful to me. Is it ever the case that a fork() operation is going to change the uid and username of a user? I took out the call to the uinfo init function from the fork call and changed the passwd and group functions to do initialization (reading /etc/passwd and /etc/group) on first lookup (ie. getpwname()). This reduced the fork time by about 15msec. The init socket function simply calls the winsock initialization function. Again I opted for lazy evaluation and took the call out of the fork code and put it at the start of many of the socket functions. This may make socket operations slightly slower but speeds up fork by about 10msec. Since most programs dont use sockets this seems to be a big win to me. As a nice side affect, this should get rid of problems people have been having with winsock dialing on demand each time an cygwin program is started up. With my changes it should only do this when actually socket operations are used. So with these two pretty minor changes my fork() went from about 75msec to about 50msec, a 33% speed increase. The difference is quite noticeable when running shell scripts and lots of shell commands (i.e. makefiles). I am still looking into other possible improvements so I'll defer posting patches until its all finished and I have done more complete testing. If anyone has ideas on other possible improvements to fork please let me know. Btw, is there a developers mailing list that this would be more appropriate for? It seems that most people on the general cygwin list are probably not very interested in things like this. Tim N. - For help on using this list (especially unsubscribing), send a message to "gnu-win32-request AT cygnus DOT com" with one line of text: "help".