Mail Archives: cygwin/2007/03/07/15:14:09
--------------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--
- Raw text -