This is the mail archive of the
cygwin
mailing list for the Cygwin project.
Re: Cygwin speed
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
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;
}
--
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/