Why does Cygwin execute shell commands very slowly?
Finally, I found the source - a service named "QQPCMgr RTP Service" running on my office computer, it's the real time protection service of "QQ PC Manager".
By disabling it, the time of the script in the question falls back to:
real 0m0.943s
user 0m0.105s
sys 0m0.231s
I have told the developers of QQPCMgr about this, hope they will find the reason.
This still much slower than Linux, but gets the same "real time" of other cygwin computers.
Thank you all!
Startup is really slow for all Cygwin applications
Eventually I found what causes this issue, but I'm still not sure why. Cygwin works for other people in same environment very well.
Cause: On the start of every Cygwin application it tries to get credentials as it is described in etc/nsswitch.conf
file. For some reason, it takes a lots of time for my account as it contacts with several Active Directory domain controllers via LDAP.
Solution 1: You can save the current user and group in etc/passwd
and etc/group
files and set Cygwin to check them before Active Directory.
- Start
mintty.exe
and wait till it opens - Run
mkpasswd -c
and save its output toetc/passwd
file (you will have to create it, output should be one line) - Run
mkgroup -c
and save its output toetc/group
file (you will have to create it, output should be one line) - Open
etc/nsswitch.conf
and write
nsswitch.conf contents:
passwd: files # db
group: files # db
Now your Cygwin should start immediately.
Solution 2: There is special CygServer application, shipped with Cygwin, which can be started as an NT service or as a simple process (just run usr/sbin/cygserver.exe
). It caches credentials and propagates them to every next Cygwin process while cygserver is running.
Add it to startup or start it before your Cygwin session and you're good — cygserver startup will take time, but every next Cygwin process will start immediately.
Is it your case? I want to share my investigation steps, so you could check, if your case is same to mine.
- Install MS Network Monitor as it is able to show traffic from a specific process. Run it as administrator.
- Create New capture tab and click Start (you don't have to add any filters or anything).
- Start
mintty
and you will see its connections in netmon: - You will see list of
mintty
connections in the tree view on the left and TCP and LDAP frames on the right after selecting on of those connections. - Additionally, you can get name of those remote machines by IP address. Run
nbtstat -a 8.8.8.8
in command line (replace 8.8.8.8 by one of IP addresses from netmon).
Going deeper: I'm still playing with etc/nsswitch.conf file to get local credentials or maybe cached ones so it will run faster without cygserver. But no luck yet.
Cygwin commands from CMD are slow; from bash are fast
A section in Cygwin's FAQ addresses slow startup times. Cygwin recently changed to using Active Directory lookups for authentication, rather than using flat files. Changing the defaults in /etc/nsswitch.conf
from
passwd: files db
group: files db
to
passwd: files
group: files
skips the AD lookup. My Cygwin commands are now speedy again.
Slow load time of bash in cygwin
As you've noted in your answer, the problem is Cygwin's bash-completion package. The quick and easy fix is to disable bash-completion, and the correct way to do that is to run Cygwin's setup.exe (download it again if you need to) and select to uninstall that package.
The longer solution is to work through the files in /etc/bash_completion.d
and disable the ones you don't need. On my system, the biggest culprits for slowing down Bash's load time (mailman, shadow, dsniff and e2fsprogs) all did exactly nothing, since the tools they were created to complete weren't installed.
If you rename a file in /etc/bash_completion.d
to have a .bak
extension, it'll stop that script being loaded. Having disabled all but a select 37 scripts on one of my systems in that manner, I've cut the average time for bash_completion to load by 95% (6.5 seconds to 0.3 seconds).
How to speed up Cygwin?
The problem you're running into is not some arbitrary limit in Cygwin that you can make go away with a settings change. It's an inherent aspect of the way Cygwin has to work to get the POSIX semantics programs built under it expect.
The POSIX fork()
system call has no native equivalent on Windows, so Cygwin is forced to emulate it in a very inefficient way. Shell scripts cause a call to fork()
every time they execute an external process, which happens quite a lot since the shell script languages are so impoverished relative to what we'd normally call a programming language. External programs are how shell scripts get anything of consequence done.
There are other inefficiencies in Cygwin, though if you profiled it, you'd probably find that that's the number one speed hit. In most places, the Cygwin layer between a program built using it and the underlying OS is pretty thin. The developers of Cygwin take a lot of pains to keep the layer as thin as possible while still providing correct POSIX semantics. The current uncommon thickness in the fork()
call emulation is unavoidable short of Microsoft adding a native fork()
type facility to their OS. Their incentives to do that aren't very good.
The solutions posted above as comments aren't bad.
Another possibility is to go through the drush
script and see if there are calls to external programs you can replace with shell intrinsics or more efficient constructs. I wouldn't expect a huge speed improvement by doing that, but it has the nice property that you'll speed things up on the Linux side as well. (fork()
is efficient on Linux, but starting external programs is still a big speed hit that you may not have to pay as often as you currently do.) For instance:
numlines=`grep somepattern $somefile | wc -l`
if [ $numlines -gt 0 ] ; then ...
would run faster as:
if grep -q somepattern $somefile ; then ...
The first version is arguably clearer, but it requires at least three external program invocations, and with primitive shells, four. (Do you see all of them?) The replacement requires only one external program invocation.
Related Topics
What Means "Atomic" System Call
Is There a Rpm File Naming Convention in Lsb
Linux: How to Send Tcp Packet from Specific Port
Enabling The Vt-X Inside a Virtual Machine
Bash Command Line Arguments Passed to Sed via Ssh
How to Remove Everything Else in a Folder Except Filea
Linux Telnet Vt100 Return Key Sends ^M
Ssh Command Output to Save in a Text File in Shell Script
Problem of Understanding Clock_Gettime
Linux Support 802.1Ag and Y1731
How to Distribute C++11 Shared Library on Centos6
Shared Libraries (Dlopen) and Thread-Safety of Library Static Pointers
Avoid Daemon Running in Dedicated CPU Cores
I Need a Tcp Option (Ioctl) to Send Data Immediately
How to Detect Availability of Gui in Bash/Shell