X-Spam-Check-By: sourceware.org Message-ID: <45EF1CED.608@t-online.de> Date: Wed, 07 Mar 2007 21:13:33 +0100 From: Christian Franke User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070111 SeaMonkey/1.1 MIME-Version: 1.0 To: cygwin AT cygwin DOT com Subject: Re: Cygwin speed References: <45E86FFD DOT 7060301 AT princeton DOT edu> <45E876FA DOT 7401B017 AT dessent DOT net> <20070305011713 DOT GG6734 AT ns1 DOT anodized DOT com> In-Reply-To: <20070305011713.GG6734@ns1.anodized.com> Content-Type: multipart/mixed; boundary="------------080503080008000005090109" X-ID: VsDEOMZJZeuGNpPAnzVh5gAs90-WzrmorjmlqVnDwwaAmGxxF2I2Qd X-TOI-MSGID: c8d436eb-f538-4661-97e9-c9d4c196bc6b X-IsSubscribed: yes Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com --------------080503080008000005090109 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Christopher Layne wrote: > On Fri, Mar 02, 2007 at 11:11:54AM -0800, Brian Dessent wrote: >> Vinod Gupta wrote: >> >>> Cygwin was a slow by a factor of 3x. Is that normal? >> Yes. Emulation of POSIX functions which do not exist on Windows is >> expensive. Fork is especially bad, which is all you're really testing >> there. > > Where is the *continual* fork in his script btw? There is no fork at all, the script uses only builtin shell commands. This command prints the fork() count of a script on Cygwin: $ strace bash ./script.sh | grep -c 'fork: 0 = fork()' One reason for the slow execution of the script are >8000000 context switches done by Cygwin. Bash calls sigprocmask() before starting each command, even for builtin commands. Cygwin's sigprocmask() unconditionally calls sig_dispatch_pending(). This is necessary because POSIX requires that at least one pending signal is dispatched by sigprocmask(). sig_dispatch_pending() sends a __SIGFLUSH* to self and this causes 2 thread context switches: main->sig->main. With the attached patch, sigprocmask() does nothing if the signal mask is not changed. This reduces the context switches to <5000. (Patch is only intended for testing, it at least breaks above POSIX rule) I've run 4 tests scripts on 5 "platforms": Test 1: Original script, but with [[...]] instead of [...]: i=1000000 while [[ $i -gt 0 ]]; do j=$(((i/3+i*3)**3)) i=$((i-1)) done Test 2: Original script unchanged: i=1000000 while [ $i -gt 0 ]; do ... Test 3: Original script with /100 iterations and using command version of [ (test): i=10000 while /usr/bin/[ $i -gt 0 ]; do ... Test 4: A real world "./configure" script Results on same AMD64 3200+ @2GHz, XP SP2: | Runtime (seconds) of test | 1 2 3 4 ------------------------------------------- Cygwin 1.5.24-2 77 84 138 33 Cygwin +patch 38 46 138 33 Linux on Virt.PC: 49 57 62 22 Linux on VMware: 29 34 23 20 Linux native: 23 29 7 6 (Linux = grml 0.9 live CD) Observations: - Shell scripts with many builtin commands would benefit from a Cygwin optimization preventing unnecessary context switches ... - ... but this might not help for most real world scripts. - fork() on Linux is also considerably slower when running in a VM on Windows. - Bash's builtin [[...]] is faster than [...] Christian --------------080503080008000005090109 Content-Type: text/plain; name="patch.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="patch.txt" diff -up cygwin-1.5.24-2.orig/winsup/cygwin/signal.cc cygwin-1.5.24-2/winsup/cygwin/signal.cc --- cygwin-1.5.24-2.orig/winsup/cygwin/signal.cc 2006-07-05 01:57:43.001000000 +0200 +++ cygwin-1.5.24-2/winsup/cygwin/signal.cc 2007-03-07 19:23:27.593750000 +0100 @@ -153,7 +153,6 @@ sigprocmask (int how, const sigset_t *se int __stdcall handle_sigprocmask (int how, const sigset_t *set, sigset_t *oldset, sigset_t& opmask) { - sig_dispatch_pending (); /* check that how is in right range */ if (how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK) { @@ -171,7 +170,8 @@ handle_sigprocmask (int how, const sigse if (set) { - sigset_t newmask = opmask; + sigset_t oldmask = opmask; + sigset_t newmask = oldmask; switch (how) { case SIG_BLOCK: @@ -187,7 +187,11 @@ handle_sigprocmask (int how, const sigse newmask = *set; break; } - set_signal_mask (newmask, opmask); + if (oldmask != newmask) + { + sig_dispatch_pending(); + set_signal_mask (newmask, opmask); + } } return 0; } --------------080503080008000005090109 Content-Type: text/plain; charset=us-ascii -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/ --------------080503080008000005090109--