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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Calmarius
  • 18,570
  • 18
  • 110
  • 157
  • which gcc version are you using? do gcc --version at the command line to find out –  May 30 '09 at 11:13
  • FWIW I figured out a solution to speed up the linking: https://stackoverflow.com/a/75655889/19739129 – jpr42 Mar 06 '23 at 21:13

4 Answers4

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.

mdaniel
  • 31,240
  • 5
  • 55
  • 58
  • 7
    +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. – Jacob Stanley Aug 17 '11 at 18:18
  • Our AD controller is at: server.domain.com. Adding "127.0.0.1 server.domain.com" to my hosts file do the trick. – rcmadruga Mar 27 '12 at 15:05
  • 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... – André Caron Mar 27 '14 at 03:25
  • 1
    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. – Andrew Christianson Apr 23 '15 at 21:26
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.
jpaugh
  • 6,634
  • 4
  • 38
  • 90
AlexF
  • 399
  • 4
  • 9
  • 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. – hackdev Apr 15 '20 at 08:29
  • 1
    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. – Arsenal Jan 05 '21 at 15:26
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.

Community
  • 1
  • 1
hyde
  • 60,639
  • 21
  • 115
  • 176
  • 1
    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? –  Aug 13 '15 at 16:16
  • 2
    @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. – hyde Aug 13 '15 at 16:54
  • @ExcessPhase Though, things may have been optimized, I added a 2nd answer link just now. – hyde Aug 13 '15 at 17:03
-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.

SurvivalMachine
  • 7,946
  • 15
  • 57
  • 87