Why is MinGW very slow?
Asked Answered
M

4

35

I'm using the Code::Blocks IDE with GCC/MinGW on Windows, and I'm trying to build a wxWidgets application which has ca. 20k lines and 40 source modules. And it builds very very slow.

Compiling a C++ module lasts 2-5 seconds, and linking lasts even 2-3 minutes.

It's a portable code, and this code compiles very fast on Linux. I can't follow the build message window... The entire process lasts less than 20 seconds.

I tried the common tweaks (for example, precompiled header, turn optimizations off, etc.), but nothing worked.

Why is it so slow?

Maurilla answered 30/5, 2009 at 10:25 Comment(5)
which gcc version are you using? do gcc --version at the command line to find outGasman
FWIW I figured out a solution to speed up the linking: https://mcmap.net/q/450222/-speed-up-extremely-slow-mingw-w64-compilation-linkingUdall
@BenCreasy Why do you tag MSYS2? The answer below claims this is purely a MSYS1 bug.Balthazar
@Balthazar good point, altho hyde's answer applies still - msys2 remains quite slow, and my feeling is that msys2 builds are still much slower than the equivalent linux builds. but I haven't rigorously investigated thatLoveless
I flipped it back to just msys1Loveless
B
20

Are you on an Active Directory domain, but not immediately connected to it?

While I don't have the "answer" as to why MinGW would be slow, it has been my experience that computers which belong to an AD domain, but are unable to reach the AD controller, have a delay in starting executables (such as rxvt.exe) and currently running ones experience a pause or stutter (such as emacs, which is built using MinGW).

I am still investigating to determine the actual cause of this behavior, but thought I would mention it in case it applies to you.

Boothman answered 8/12, 2009 at 16:43 Comment(4)
+1 I'm experiencing this as well, disabling my network adapters results in immediate startup. Putting bogus DNS entries (127.0.0.1) for the domain controllers in my hosts file makes things much quicker, but not as quick as disabling the network entirely.Milla
Our AD controller is at: server.domain.com. Adding "127.0.0.1 server.domain.com" to my hosts file do the trick.Windmill
Thanks for this hint. I've been wondering for ages why this occurs only on one of my machines! It so happens that it's not connected to its AD domain...Brandling
I'll be damned. I've been gritting my teeth at this for months - just turned off the wifi on my laptop, and msys utils are much, much snappier.Evesham
N
19

As of MSYS 1.0.19-1, if the user account is in Active Directory domain and the Domain Controller (DC) is unreachable, then MSYS DLL will introduce a long delay before starting any MSYS executable (that uses MSYS DLL). This affects MSYS make and all the command-line utilities from CoreUtils package such as ls, rm etc that are typically installed in C:\MinGW\msys\1.0\bin.

Observations:

  • When launching utilities from MSYS bash shell, only the shell's startup is hit by the delay. Utilities launched from the shell are not impact.

  • The delay can vary, in my case it is 21sec.

  • Running any MSYS utility within 10-20sec after the delayed command will launch without a new delay.
  • Problem occurs when the machine is connected to a different network, or when disconnected from its domain, or when Domain Controller hostname changes (problem in my case). To check if DC is reachable, open cmd and type echo %LOGONSERVER%, then ping or net view with the host name of the DC.

Why is it so slow:

  • The code of MSYS DLL in uinfo.cc internal_getlogin() makes two system calls to get user information. First time it calls NetUserGetInfo() to retrive the user account from the local machine. It fails for domain users, so it calls it second time with the DC server taken from LOGONSERVER variable. If this host is not immediately accessible, it will introduce a long delay until the call fails on timeout. The application will start shortly after.

How to avoid this problem, several workarounds:

  • Either run everything from MSYS shell, or
  • If the reason is the change in DC hostname, then a restart or re-login will resolve the issue. Windows will automatically update LOGONSERVER with the correct DC host.
  • If MSYS tools are called from Windows cmd or a script, then set LOGONSERVER to a localhost to avoid network access. E.g. set LOGONSERVER=\\LOCALHOST worked for me. Note: this variable is set at logon and changing it globally in Windows Environment Variables window has no effect compared to setting it in cmd or a script.
  • I consider this a bug in MinGW/MSYS. The code in MSYS2 and Cygwin is different. I checked MSYS2 and it has no such issue.
Nowhither answered 7/5, 2017 at 10:8 Comment(2)
Both this and the answer above seem to fix the issue for me, i.e. disabling wifi from the answer above, or running sh.exe from this answer fixed the problem. I was going to keep using sh.exe when I noticed that loading my .bashrc from sh.exe would break things again. After searching a bit I noticed I added MinGW/msys/1.0/usr/bin to the path, and changing that to MinGW/msys/1.0/bin also fixes the issue. Don't know why exe in usr/bin are different from the ones under bin. Hope this helps.Crenulation
Wow, I've been struggling with this issue for months and spent hours with the wrong search terms obviously. Fun part was that it only occurred when the Jenkins was running as a service and executing the build, if you logged in on the machine everything was fine and build rapidly. Using set LOGONSERVER=\\LOCALHOST before calling the build command in Jenkins fixed it. Sadly I only have one upvote.Dogwatch
E
13

Many "unixy" things on MinGW are painfully slow, because Windows has no fork(). Windows only has CreateProcess(), which is quite different. Unix shells and GNU Make do a lot of forking, so running these under MinGW results in "emulated" forks, which are really slow.

Another thing which suffers from this is GNU Autotools, so running ./configure scripts when building "unixy" applications from sources is also very slow. This can get really annoying if you need to do it many times (for example when having troubles with with getting configure to find all the libraries).

This answer explains in more detail how Cygwin and MinGW used to simulate fork(), and this answer has more up to date explanation.

Evangelia answered 21/4, 2015 at 8:18 Comment(3)
Are you trying to tell us, that fork() is really used to clone the current process instead of being followed by execp()? Which compiler/linker needs to clone a process?Hooknosed
@ExcessPhase I'm not sure what you mean by that. Unix programs use fork() to create child processes. When you compile that Unix program for MinGW, the fork() call still needs to create a child process just like it would in "real" Unix, even if fork() is followed by exec, no matter how slow the MinGW emulated fork is, because compiler can't change the program code to work more efficiently under Windows.Evangelia
@ExcessPhase Though, things may have been optimized, I added a 2nd answer link just now.Evangelia
I
-1

You can try to use a more recent version of the toolset. I found this to be useful: http://nuwen.net/mingw.html It has all the tools used by MinGW and common APIs in a single big package. From the site:

My MinGW distribution ("distro") is x64-native and currently contains GCC 6.1.0 and Boost 1.61.0.

MinGW is a port of GCC to Windows. It is free of charge and simple to use (well, as simple as toolchains ever get). It produces standalone Windows executables which may be distributed in any manner.

Ingeborg answered 8/12, 2009 at 17:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.