News:

Do you need help?
Simutrans Wiki Manual can help you to play and extend Simutrans. In 9 languages.

Very slow compilation on MSVC 2008

Started by falconne, November 19, 2011, 07:03:35 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

falconne

I'm playing around with the code in MSVC and everything's working fine but I'm finding my compiles are excruciatingly slow; around 5-13 seconds per file leading to 15-20 minutes for the project. All that time appears to be spent in header resolution. I found this strange, because all the headers are protected by pragmas against duplicate includes.

I can speed up the build with /MP, but I think there must be something basic going wrong here. Even though the time is spent in header resolution (and the process activity shows insignificant cpu usage but a decent amount of disk usage) moving the workspace from my hard drive to my SSD didn't improve the compile speed at all, which I thought was really odd.

I wondered if this was happening because using STL in VS 2008 seems to cause large number of headers to get included from its base library, but this doesn't seem to be affecting other 3rd party C++ projects I'm compiling. Perhaps a pre compiled header is required just for the MSVC builds?

Is anyone else experiencing this or am I doing something obviously wrong? Or do most folk compiling in Windows use MinGW?

Dwachs

It should get better after one complete compile. Then only changed files and dependencies are recompiled.
Parsley, sage, rosemary, and maggikraut.

falconne

True but if I edit something like simfab.h then a lot of cc files need recompiling and that takes ages. I'm finding that as I'm learning the code and experimenting I will make a small change to a lower level header file, then have to go do something else for 15 mins before I can see the effect of my changes. As you can imagine it's hard to get my head around a complex codebase this way, I keep losing concentration :)

I might try putting all the STL includes into a precompiled header and see if that helps at all.

Dwachs

There are not that much STL headers included besides string... But 15 min is definitely too much.

Files that are included by a lot of other files are for instance: simworld.h, simhalt.h, simfab.h, grund.h
Parsley, sage, rosemary, and maggikraut.

VS

#4
My time: Building after "clean" on a single-core Athlon at 1.8 GHz, 1.5 GB memory and MSVC 2010 in the background needs 365 seconds, or about 6 minutes.

Just a wild guess - I don't know that much about MSVC, but... Sometimes, when I open the project after updating sources, it will show a progressbar at the bottom of window and say something about scanning files, usually hundreds of them. This may take quite a while. It did that with both 2010 and 2008. Maybe it's actually generating precompiled headers then, and maybe you disabled that in some way?

My projects... Tools for messing with Simutrans graphics. Graphic archive - templates and some other stuff for painters. Development logs for most recent information on what is going on. And of course pak128!

falconne

Precompiled headers did the trick, brought my clean build time down from nearly 20 minutes to just 12 seconds :)

The problem is the heavy Windows development environment. Sure the code only uses a few STL includes, but the VS 2008 STL implementation seems to involve having every STL header include a whole tree of other headers that slow down each compile (and since each source file's tree of headers eventually includes many of the STL includes, every file gets hit by this delay). I bet VS 2010 is even worse.

More so than the STL includes, the problem was windows.h being included a lot. This file appears to be really heavy, especially in v6.0 of the Windows SDK that my copy of VS 2008 is using. Adding this into the precompiled header helped a lot, although I had to use a few defines, like WIN32_LEAN_AND_MEAN, because there were several Simutrans headers that caused conflicts with definitions in that file. So far I've found no runtime problems from building with these defines (and this is only for my local debugging anyway).

In case anyone's interested, the precompiled header I created contained:

#include <string.h>
#include <string>
#include <assert.h>
#include <typeinfo.h>
#include <iterator>
#include <typeinfo>
#include <stddef.h>

#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#define NOMINMAX
#include <windows.h>


And I used the /FI compiler option to automatically have it included in every file (that way you don't have to modify any existing files). I also had to do a bit of a hack with bzlib.h... it was being included by loadsave.h, which appeared to be in the tree of many of the files, but since it was an external include it didn't get the benefit of my precompiled header and it too included windows.h, so that was still causing a lot of slowdown. So in my environment I ended up including bzlib.h in the Simutrans project making it a local file, which solves the problem. The last thing was to use /MP to build with every hyper threaded core to get the best build time.

prissi

#include <iterator>
#include <typeinfo>

is not used at all ... And do not forget that MSVC is single core compiling.

Actually after chaning a header, only few file affecting by the header are recompiled (those needed the recompile). If I change grund.h this will be a lot, for a little stuff in simfab.h I may be ok with a single file. (But not 12s though.)

falconne

I meant it now only takes 12s to build the whole project from scratch (clean build), which I think is reasonable. It was taking me 15-20 mins before the change. A small compile now takes an insignificant time as you'd expect.

Also, although by default MSVC doesn't parallel build an individual project, when you use the /MP compile switch it does. I'm using /MP8, so it always has 8 cl.exe's going, compiling 8 files at once (I have a quad core hyper threaded). The overall build time goes down if I use less or more processes than 8.

I created my precompiled header based on a trace from using the /showincludes compile switch. I collected the STL headers that were being included in many of the files. <iterator> and <typeinfo> are being included by slist_tpl.h, at least in the trunk code, and that header eventually gets pulled into many source files, so they came up a lot in my trace. It looks like they can be removed form that file all together. The thing there is that even if each .cc file only has a few includes, those headers include a bunch of others and they in turn include more, so the eventual list for each file becomes large, especially when the MSVC STL headers start pulling in their dependencies.

I've attached part of the /showincludes trace from my current build (it's only half the build, the full trace is too big to attach even zipped). This is using precompiled headers, so this trace is a lot smaller than what I was getting at the beginning, as it excludes much of the STL headers. Even so, you can see each file pulls in quite a lot of internal headers and I think reducing the dependencies would reduce the compile time on all platforms. Even if the build time is probably not a big deal, I think doing so also has the benefit of making the code cleaner and more maintainable by culling excess dependencies.

falconne

#8
Quote from: VS on November 19, 2011, 12:52:43 PM
My time: Building after "clean" on a single-core Athlon at 1.8 GHz, 1.5 GB memory and MSVC 2010 in the background needs 365 seconds, or about 6 minutes.

Just a wild guess - I don't know that much about MSVC, but... Sometimes, when I open the project after updating sources, it will show a progressbar at the bottom of window and say something about scanning files, usually hundreds of them. This may take quite a while. It did that with both 2010 and 2008. Maybe it's actually generating precompiled headers then, and maybe you disabled that in some way?

That's just building the intellisense index. That only takes a few seconds on my machine. Precompiled headers aren't built manually, at least in later versions of MSVC that I can see, you have to create them manually which is what I did.

I don't know why mine was performing so badly. I have a clean set up of Win 7 64 bit and VS 2008 SP1. Something obviously not happy with that combination. Regardless, the problem was simple enough eventually.

Edit: Sorry about the double post, should have just edited the previous reply