Why does C++ linking use virtually no CPU? - c++

On a native C++ project, linking right now can take a minute or two. Yet, during this time CPU drops from 100% during compilation to virtually zero. Does this mean linking is primarily a disk activity?
If so, is this the main area an SSD would make big changes? But, why aren't all my OBJ files (or as many as possible) kept in RAM after compilation to avoid this? With 4 GB of RAM I should be able to save a lot of disk access and make it CPU-bound again, no?
Update: so the obvious follow-up is, can the VC++ compiler and linker talk together better to streamline things and keep OBJ files in memory, similar to how Delphi does it?

Linking is indeed primarily a disk-based activity. Borland Pascal (back in the day) would keep the entire program in memory, which is why it would link so fast.
Your OBJ files aren't kept in RAM because the compiler and linker are separate programs. If your development environment had an integrated compiler and linker (instead of running them as a separate processes), it could indeed keep everything in RAM.
But you would lose the ability to separate the development environment from the compilers and/or linkers - you would have to use the same compiler/linker, and you wouldn't be able to run the compiler outside the environment.

You can try installing some of those RAM disks utilities and keep your obj directory on the RAM disk or even whole project directory. That should speed it up considerably.
Don't forget to make it permanent afterwards :-D

The Visual Studio linker is largely I/O bound, but how much so depends on a few variables.
Incremental linking (common in Debug builds) generally requires a lot less I/O.
Writing a PDB file (for symbols) can consume a lot of the time. It's a specific bottleneck that Microsoft targeted in VS 2010. The PDB writing is now done asynchronously. I haven't tried it, but I've heard it can help link times quite a bit.
If you using link-time code generation (LTCG) (common in Release builds), you have all the usual I/O initially. Then, the linker re-invokes the compiler to re-generate code for sections that can be further optimized. This portion is generally much more CPU-intensive. Off hand, I don't know if the linker actually spins up the compiler in a separate process and waits (in which case you'll still see low CPU usage for the linker process), or if the compilation is done in the linker process (in which case you'll see the linker go through phases of heavy-I/O then heavy-CPU).
Using an SSD can help with the I/O bound portions. Simply having a second drive can help, too. For example, if your source and objects are all on one drive, and you write your PDB to a separate drive, the linker should spend less time waiting for the PDB writer. Having a second spinning drive has helped my current team's link times dramatically.

In debug builds in Visual Studio you can use incremental linking which allows you to usually avoid a lot of the time spent on linking. Basically it means that instead of linking the whole EXE (or DLL) file from scratch it builds upon the one you last linked, replacing only the things that changed.
This is however not recommended for release builds since it adds some overhead in runtime and can result in an EXE file that is several times larger than the usual.

It's hard to say what exactly is taking the linker so long without knowing how it is interacting with the OS. Thankfully, Microsoft provides Process Monitor so you can do just that.
It's helped me diagnose bugs with the Visual Studio IDE and debugger without access to source.

Related

What steps can be taken to reduce link time? [duplicate]

We have fairly large C++ application which is composed of about 60 projects in Visual Studio 2005. It currently takes 7 minutes to link in Release mode and I would like to try to reduce the time. Are there any tips for improving the link time?
Most of the projects compile to static libraries, this makes testing easier since each one also has a set of associated unit tests. It seems the use of static libraries prevents VS2005 from using incremental linking, so even with incremental linking turned on it does a full link every time.
Would using DLLs for the sub projects make any difference? I don't really want to go through all the headers and add macros to export the symbols (even using a script) but if it would do something to reduce the 7 minute link time I will certainly consider it.
For some reason using nmake from the command line is slightly faster and linking the same application on Linux (with GCC) is much faster.
Visual Studio IDE 7 minutes
Visual C++ using nmake from the command line - 5 minutes
GCC on Linux 34 seconds
If you're using the /GL flag to enable Whole Program Optimization (WPO) or the /LTCG flag to enable Link Time Code Generation, turning them off will improve link times significantly, at the expense of some optimizations.
Also, if you're using the /Z7 flag to put debug symbols in the .obj files, your static libraries are probably huge. Using /Zi to create separate .pdb files might help if it prevents the linker from reading all of the debug symbols from disk. I'm not sure if it actually does help because I have not benchmarked it.
See my suggestion made at Microsoft : https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=511300
You should vote for it ! Here is my last comment on it :
Yes we are using incremental linking to build most of our projects. For the biggest projects, it's useless. In fact, it takes more time to link those projects with incremental linking (2min50 compared to 2min44). We observed that it doesn't work when size of ILK files is big (our biggest project generate an ilk of 262144 KB in win 32).
Bellow, I list others things we tried to reduce link time:
Explicit template instantiation to reduce code bloat. Small gain.
IncrediLink (IncrediBuild give interesting gain for compilation but almost no gain for link).
Remove debug information for libraries who are rarely debugged (good gain).
Delete PDB file in « Pre-Build Event » (strangely it give interesting gain ex: 2min44 instead of 3min34).
Convert many statics library to DLL. Important gain.
Working with computer equiped with lot of RAM in order to maximize disk cache. The biggest gain.
Big obj versus small obj. No difference.
Change project options (/Ob1, /INCREMENTAL, Enable COMDAT folding, Embedding manifest, etc.). Some give interesting gain other not. We try to continuously maximize our settings.
Maximize Internal linkage vs External linkage. It's a good programming practice.
Separate software component as much as we can afford. You can than work in unit test that link fast. But we still have to interate things together, we have legacy code and we worked with third party component.
Use secret linker switch /expectedoutputsize:120000000. Small gain.
Note that for all our experimentation, we meticulously measured link time. Slow link time seriously cost in productivity. When you implement complex algorithm or track difficult bug, you want to iterate rapidly this sequence : modify some code, link, trace debug, modify some code, link, etc...
Another point to optimize link time is the impact it have on our continuous integration cycle. We have many applications that shared common code and we are running continuous integration on it. Link time of all our applications took half the cycle time (15 minutes)...
In thread https://blogs.msdn.microsoft.com/vcblog/2009/09/10/linker-throughput/, some interesting suggestions were made to improve link time. On a 64 bits computer, why not offering an option to work with file completely in RAM ?
Again, any suggestions that may help us reduce link time is welcome.
Generally, using DLLs instead of static libraries will improve linking times quite a bit.
Take a look at Incredibuild by Xoreax. Its distributed compilation dramatically reduced our full build/link times from around 40 minutes to 8 minutes.
Additionally, this product has a feature they call Incredilink which should help you get incremental links working even with statically linked libraries.
I don't think converting to DLLs would be useful.
You could try looking for options to do with optimisation, and turning them off. The linker might be spending a long time looking over the libs for redundant code it can eliminate. Your app may end up bigger or slower, but that may not be a problem to you.
Several people have reported (and I myself have noticed) that modifying a file in a statically linked library will disable incremental linking for the entire solution; this appears to be what you are seeing. See comments here and here for some information about that.
One workaround is to use the Fast Solution Build Add-In. This might involve making a few changes to your workspace, but the payoff is definitely worth it. For a commercial solution, use Xoreax's Incredibuild, which basically incorporates this same technology but adds other features as well. I apologize if I sound like a salesman for Incredibuild - I'm just a very satisfied customer.
I've had similar troubles linking large apps with Visual C++ before. In my case, I simply didn't have enough free RAM and excessive paging to disk was slowing the linking process to a halt. Doubling my RAM from 1GB to 2GB made a dramatic improvement. How much is your dev box running?
I just found out that we had by accident defined a large table of strings in a header file which got included in pretty much every (static) lib. (I am talking about a huge C++ project.) When the linker created the EXE, it looks like the unification of the table (there is only a single one ending up in the EXE) or the parsing of the libs took forever. Putting the table in a separate C++ file took a couple of minutes of the link on a relatively slow machine.
Unfortunately, I don't know how to find stuff like that other than by chance.
For debug builds, then one can use incremental linking, which can improve link times a lot.
Sadly enough there are certain pitfalls, and VS2005 will not warn you.
If using static libraries then incremental linking will not work if modifying a file part for the static library. The solution is to set the linker option "Use Library Dependency Inputs" to "Yes" (This is the same as Fast Solution Build in VS2003)
If using pragma-comment-lib to include the lib of a DLL, and specifies a relative path instead of the lib alone, then incremental linking will stop working. The solution is to specify the lib alone, and use the linker-option LIBPATH to add additional lib-path.
Some times the .ilk file will become corrupted (grow beyond 200 MByte) and then suddenly the incremental linker til take more than 10 times the normal time. Some times it will complain about the .ilk file being corrupt, but usually first after several minutes. The solution for me was to setup the following command for the "Build Event" -> "Pre-Link Event"
for %%f in ($(IntDir)*.ilk) do ( if "%%~zf" GTR "200000000" (del %%f))
60 libs to link does sound like a fair few. This may be a bit of an extreme measure, but it might radically speed things up. Create a new solution, with a few projects, and add all the source from your existing projects to these. Then build and link them instead, and just keep the small ones for testing.
Get a quicker computer with multiple processors and enable parallel builds (this might be on by default). To allow the greatest amount of parallism, make sure your project dependencies are correct and you haven't got unnecessary dependencies.
If you are truly talking about link times, then things like fast solution build and Xoreax won't really help much (except for Incredilink, which might). Assuming that you are truly measuring link start to link end, then I would suggest that the number of libs that you have is the issue.
The link phase is, at least initially, IO bound in loading up all of the object and lib files. You might be in a situation where you have 60 libraries along with the main project of some large number of .obj files. I suspect that you simply might be seeing, at least in part, typical windows slowness in loading up all of those libs and .obj files.
You can easily test this. Take all of those lib files and build one single lib file just as a test. Instead of linking with 60 of them, link with one and see where your time goes. That would be interesting.
NTFS is notoriosly slow. It shoudln't be 7m vs. 32 seconds on Linux slow, but it might be part of the issue. Using DLL's will help but you will suffer application startup time, although that will not be early as bad. I would be confident that you won't have 7m application start up times.
you can try looking at this: http://msdn.microsoft.com/en-us/library/9h3z1a69.aspx
Basically, you can run project builds in parallel if you have several cores.
I had solved my link problem and share to all of you.
My project's link time was 7 min with /Incremental:no linking (link time 7min).
Was 15 min with /Incremental, (link time 7min, embeded manifest time 7min). So I turn off the inremental.
I found Additional dependencies has a.lib AND ignore specific libraries has, too!
So I remove it from Ignore specific libraries turn on the /incremental. first link time need 5min but embeded manifest time has none.
I don't know why, but the incremental linking has worked.
I rollback all project code , so I could find the problem by the lib.
If you do all of above, you can try my method. Good luck!
Step 1 in C++ build time reduction is more memory. After switching from 4GB to 12GB, I saw my link-all-projects time fall off a cliff: from 5:50 to 1:15.

Whole program optimization failing in VC2008

I have a reasonably large C++ program (~11mb exe) compiled under VS2008 and was interested to see if whole program optimization would significantly affect its performance. However, turning on whole program optimization and link time code generation causes the link to fail as follows;
1>c:\cpp\Win32\Atlas\tin\TINDoc.Cpp : fatal error C1083: Cannot open compiler intermediate file: '.\releaseopt\TINDoc.obj': Not enough space
1>LINK : fatal error LNK1257: code generation failed
Looking at task manager, I can see the linker using more and more memory until it runs out and bombs out. The compiler is running on XP 32bit with 2GB or ram and 2gb page file. Is WPO limited to smaller applications and/or bigger environments, or is there any way to get the linker to be a bit more frugal in memory usage.
n.b. already turned of precompiled headers, which was causing the compilation to fail before linking, and turned off output of debug info and anything else that might take extra resources. The help for C1083 suggests missing header files or inadequate file handles rather than lack of space.
Edit: Got it working under VS2010, albeit without precompiled headers, but the performance gains aren't that significant. I'll leave this option alone until I move onto a beefier 64bit platform with a more robust version of VS2010.
VC2008 is a fragile beast. The optimiser just doesn't work for some cases, and looks like you might possibly have one such case.
Examples of "not working" include
De-optimised code (slow!)
Compiler or (more frequently) linker crashes
Obscure compile/link error messages
Incorrect code execution (this one is rare, but not unknown).
Actually, if you look at some of the tricks used by modern optimisers it is pretty amazing that it works as often as it does. The complexity is quite astounding.
Addressing Shane's problem specifically, some things that might cause your error:
Running out of file handles used to be a big problem in DOS and early Windows versions. You hardly ever see it in modern Windows versions. I'm not even certain there is still a limit on file handles.
A compiler bug could be doing an infinite loop, meaning that no amount of resources will be enough.
A recursive include file could also cause something similar. Do all your include files have "#pragma once" or "#if !defined(FOO_INCLUDED)"?
Is it possible you've included the file TINDoc.obj twice in the project? The 2008 compiler is aggressively multi-threaded and there might be contention between two threads trying to access the file. Actually this could happen via a compiler bug, even if you haven't included the file twice.
If the program really is just too big, consider breaking it up into one or more DLLs and building it piecemeal, or splitting the contentious source file into multiple files to compiler in multiple phases.
Don't assume that, because it says "not enough space" that has to be the reason. Some programs (including some compilers) will guess a reason for an error, instead of checking.
You can monitor the use of memory, handles, etc. using task manager or perfmon, or (my preference) Process Explorer
I already posted the first part of this as a comment (above) but I an making it an answer, as suggested by Ben (http://stackoverflow.com/users/587803/ben) -- and expanded it somewhat.
You can try to boot XP with the /3G switch to give the linker a 3GB address space. In Vista/7, use BCDEDIT /Set IncreaseUserVa 3072 in the command line to get the same effect.
This has fixed problems creating .ilk-files for me.

VS 2008 C++ build output?

Why when I watch the build output from a VC++ project in VS do I see:
1>Compiling...
1>a.cpp
1>b.cpp
1>c.cpp
1>d.cpp
1>e.cpp
[etc...]
1>Generating code...
1>x.cpp
1>y.cpp
[etc...]
The output looks as though several compilation units are being handled before any code is generated. Is this really going on? I'm trying to improve build times, and by using pre-compiled headers, I've gotten great speedups for each ".cpp" file, but there is a relatively long pause during the "Generating Code..." message. I do not have "Whole Program Optimization" nor "Link Time Code Generation" turned on. If this is the case, then why? Why doesn't VC++ compile each ".cpp" individually (which would include the code generation phase)? If this isn't just an illusion of the output, is there cross-compilation-unit optimization potentially going on here? There don't appear to be any compiler options to control that behavior (I know about WPO and LTCG, as mentioned above).
EDIT:
The build log just shows the ".obj" files in the output directory, one per line. There is no indication of "Compiling..." vs. "Generating code..." steps.
EDIT:
I have confirmed that this behavior has nothing to do with the "maximum number of parallel project builds" setting in Tools -> Options -> Projects and Solutions -> Build and Run. Nor is it related to the MSBuild project build output verbosity setting. Indeed if I cancel the build before the "Generating code..." step, none of the ".obj" files will exist for the most recent set of "compiled" files. This implies that the compiler truly is handling multiple translation units together. Why is this?
Compiler architecture
The compiler is not generating code from the source directly, it first compiles it into an intermediate form (see compiler front-end) and then generates the code from the intermediate form, including any optimizations (see compiler back-end).
Visual Studio compiler process spawning
In a Visual Studio build compiler process (cl.exe) is executed to compile multiple source files sharing the same command line options in one command. The compiler first performs "compilation" sequentially for each file (this is most likely front-end), but "Generating code" (probably back-end) is done together for all files once compilation is done with them.
You can confirm this by watching cl.exe with Process Explorer.
Why code generation for multiple files at once
My guess is Code generation being done for multiple files at once is done to make the build process faster, as it includes some things which can be done only once for multiple sources, like instantiating templates - it has no use to instantiate them multiple times, as all instances but one would be discarded anyway.
Whole program optimization
In theory it would be possible to perform some cross-compilation-unit optimization as well at this point, but it is not done - no such optimizations are ever done unless enabled with /LTCG, and with LTCG the whole Code generation is done for the whole program at once (hence the Whole Program Optimization name).
Note: it seems as if WPO is done by linker, as it produces exe from obj files, but this a kind of illusion - the obj files are not real object files, they contain the intermediate representation, and the "linker" is not a real linker, as it is not only linking the existing code, it is generating and optimizing the code as well.
It is neither parallelization nor code optimization.
The long "Generating Code..." phase for multiple source files goes back to VC6. It occurs independent of optimizations settings or available CPUs, even in debug builds with optimizations disabled.
I haven't analyzed in detail, but my observations are: They occur when switching between units with different compile options, or when certain amounts of code has passed the "file-by-file" part. It's also the stage where most compiler crashes occured in VC6 .
Speculation: I've always assumed that it's the "hard part" that is improved by processing multiple items at once, maybe just the code and data loaded in cache. Another possibility is that the single step phase eats memory like crazy and "Generating code" releases that.
To improve build performance:
Buy the best machine you can afford
It is the fastest, cheapest improvement you can make. (unless you already have one).
Move to Windows 7 x64, buy loads of RAM, and an i7 860 or similar. (Moving from a Core2 dual core gave me a factor of 6..8, building on all CPUs.)
(Don't go cheap on the disks, too.)
Split into separate projects for parallel builds
This is where 8 CPUS (even if 4 physical + HT) with loads of RAM come to play. You can enable per-project parallelization with /MP option, but this is incompatible with many other features.
At one time compilation meant parse the source and generate code. Now though, compilation means parse the source and build up a symbolic database representing the code. The database can then be transformed to resolved references between symbols. Later on, the database is used as the source to generate code.
You haven't got optimizations switched on. That will stop the build process from optimizing the generated code (or at least hint that optimizations shouldn't be done... I wouldn't like to guarantee no optimizations are performed). However, the build process is still optimized. So, multiple .cpp files are being batched together to do this.
I'm not sure how the decision is made as to how many .cpp files get batched together. Maybe the compiler starts processing files until it decides the memory size of the database is large enough such that if it grows any more the system will have to start doing excessive paging of data in and out to disk and the performance gains of batching any more .cpp files would be negated.
Anyway, I don't work for the VC compiler team, so can't answer conclusively, but I always assumed it was doing it for this reason.
There's a new write-up on the Visual C++ Blog that details some undocumented switches that can be used to time/profile various stages of the build process (I'm not sure how much, if any, of the write-up applies to versions of MSVC prior to VS2010). Interesting stuff which should provide at least a little insight into what's going on behind the scenes:
http://blogs.msdn.com/vcblog/archive/2010/04/01/vc-tip-get-detailed-build-throughput-diagnostics-using-msbuild-compiler-and-linker.aspx
If nothing else, it lets you know what processes, dlls, and at least some of the phases of translation/processing correspond to which messages you see in normal build output.
It parallelizes the build (or at least the compile) if you have a multicore CPU
edit: I am pretty sure it parallelizes in the same was as "make -j", it compiles multiple cpp files at the same time (since cpp are generally independent) - but obviously links them once.
On my core-2 machine it is showing 2 devenv jobs while compiling a single project.

What are the pros + cons of Link-Time Code Generation? (VS 2005)

I've heard that enabling Link-Time Code Generation (the /LTCG switch) can be a major optimization for large projects with lots of libraries to link together. My team is using it in the Release configuration of our solution, but the long compile-time is a real drag. One change to one file that no other file depends on triggers another 45 seconds of "Generating code...". Release is certainly much faster than Debug, but we might achieve the same speed-up by disabling LTCG and just leaving /O2 on.
Is it worth it to leave /LTCG enabled?
It is hard to say, because that depends mostly on your project - and of course the quality of the LTCG provided by VS2005 (which I don't have enough experience with to judge). In the end, you'll have to measure.
However, I wonder why you have that much problems with the extra duration of the release build. You should only hand out reproducible, stable, versioned binaries that have reproducible or archived sources. I've rarely seen a reason for frequent, incremental release builds.
The recommended setup for a team is this:
Developers typically create only incremental debug builds on their machines. Building a release should be a complete build from source control to redistributable (binaries or even setup), with a new version number and labeling/archiving the sources. Only these should be given to in-house testers / clients.
Ideally, you would move the complete build to a separate machine, or maybe a virtual machine on a good PC. This gives you a stable environment for your builds (includes, 3rd party libraries, environment variables, etc.).
Ideally, these builds should be automated ("one click from source control to setup"), and should run daily.
It allows the linker to do the actual compilation of the code, and therefore it can do more optimization such as inlining.
If you don't use LTCG, the compiler is the only component in the build process that can inline a function, as in replace a "call" to a function with the contents of the function, which is usually a lot faster. The compiler would only do so anyway for functions where this yields an improvement.
It can therefore only do so with functions that it has the body of. This means that if a function in the cpp file calls another function which is not implemented in the same cpp file (or in a header file that is included) then it doesn't have the actual body of the function and can therefore not inline it.
But if you use LTCG, it's the linker that does the inlining, and it has all the functions in all the of the cpp files of the entire project, minus referenced lib files that were not built with LTCG. This gives the linker (which becomes the compiler) a lot more to work with.
But it also makes your build take longer, especially when doing incremental changes. You might want to turn on LTCG in your release build configuration.
Note that LTCG is not the same as profile-guided optimization.
I know the guys at Bungie used it for Halo3, the only con they mentioned was that it sometimes messed up their deterministic replay data.
Have you profiled your code and determined the need for this? We actually run our servers almost entirely in debug mode, but special-case a few files that profiled as performance critical. That's worked great, and has kept things debuggable when there are problems.
Not sure what kind of app you're making, but breaking up data structures to correspond to the way they were processed in code (for better cache coherency) was a much bigger win for us.
I've found the downsides are longer compile times and that the .obj files made in that mode (LTCG turned on) can be really massive. For example, .obj files that might be 200-500k were about 2-3mb. It just to happened to me that compiling a bunch of projects in my chain led to a 2 gb folder, the bulk of which was .obj files.
I also don't see problems with extra compilation time using link-time code generation with the release build. I only build my release version once per day (overnight), and use the unit-test and debug builds during the day.

How to improve link performance for a large C++ application in VS2005

We have fairly large C++ application which is composed of about 60 projects in Visual Studio 2005. It currently takes 7 minutes to link in Release mode and I would like to try to reduce the time. Are there any tips for improving the link time?
Most of the projects compile to static libraries, this makes testing easier since each one also has a set of associated unit tests. It seems the use of static libraries prevents VS2005 from using incremental linking, so even with incremental linking turned on it does a full link every time.
Would using DLLs for the sub projects make any difference? I don't really want to go through all the headers and add macros to export the symbols (even using a script) but if it would do something to reduce the 7 minute link time I will certainly consider it.
For some reason using nmake from the command line is slightly faster and linking the same application on Linux (with GCC) is much faster.
Visual Studio IDE 7 minutes
Visual C++ using nmake from the command line - 5 minutes
GCC on Linux 34 seconds
If you're using the /GL flag to enable Whole Program Optimization (WPO) or the /LTCG flag to enable Link Time Code Generation, turning them off will improve link times significantly, at the expense of some optimizations.
Also, if you're using the /Z7 flag to put debug symbols in the .obj files, your static libraries are probably huge. Using /Zi to create separate .pdb files might help if it prevents the linker from reading all of the debug symbols from disk. I'm not sure if it actually does help because I have not benchmarked it.
See my suggestion made at Microsoft : https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=511300
You should vote for it ! Here is my last comment on it :
Yes we are using incremental linking to build most of our projects. For the biggest projects, it's useless. In fact, it takes more time to link those projects with incremental linking (2min50 compared to 2min44). We observed that it doesn't work when size of ILK files is big (our biggest project generate an ilk of 262144 KB in win 32).
Bellow, I list others things we tried to reduce link time:
Explicit template instantiation to reduce code bloat. Small gain.
IncrediLink (IncrediBuild give interesting gain for compilation but almost no gain for link).
Remove debug information for libraries who are rarely debugged (good gain).
Delete PDB file in « Pre-Build Event » (strangely it give interesting gain ex: 2min44 instead of 3min34).
Convert many statics library to DLL. Important gain.
Working with computer equiped with lot of RAM in order to maximize disk cache. The biggest gain.
Big obj versus small obj. No difference.
Change project options (/Ob1, /INCREMENTAL, Enable COMDAT folding, Embedding manifest, etc.). Some give interesting gain other not. We try to continuously maximize our settings.
Maximize Internal linkage vs External linkage. It's a good programming practice.
Separate software component as much as we can afford. You can than work in unit test that link fast. But we still have to interate things together, we have legacy code and we worked with third party component.
Use secret linker switch /expectedoutputsize:120000000. Small gain.
Note that for all our experimentation, we meticulously measured link time. Slow link time seriously cost in productivity. When you implement complex algorithm or track difficult bug, you want to iterate rapidly this sequence : modify some code, link, trace debug, modify some code, link, etc...
Another point to optimize link time is the impact it have on our continuous integration cycle. We have many applications that shared common code and we are running continuous integration on it. Link time of all our applications took half the cycle time (15 minutes)...
In thread https://blogs.msdn.microsoft.com/vcblog/2009/09/10/linker-throughput/, some interesting suggestions were made to improve link time. On a 64 bits computer, why not offering an option to work with file completely in RAM ?
Again, any suggestions that may help us reduce link time is welcome.
Generally, using DLLs instead of static libraries will improve linking times quite a bit.
Take a look at Incredibuild by Xoreax. Its distributed compilation dramatically reduced our full build/link times from around 40 minutes to 8 minutes.
Additionally, this product has a feature they call Incredilink which should help you get incremental links working even with statically linked libraries.
I don't think converting to DLLs would be useful.
You could try looking for options to do with optimisation, and turning them off. The linker might be spending a long time looking over the libs for redundant code it can eliminate. Your app may end up bigger or slower, but that may not be a problem to you.
Several people have reported (and I myself have noticed) that modifying a file in a statically linked library will disable incremental linking for the entire solution; this appears to be what you are seeing. See comments here and here for some information about that.
One workaround is to use the Fast Solution Build Add-In. This might involve making a few changes to your workspace, but the payoff is definitely worth it. For a commercial solution, use Xoreax's Incredibuild, which basically incorporates this same technology but adds other features as well. I apologize if I sound like a salesman for Incredibuild - I'm just a very satisfied customer.
I've had similar troubles linking large apps with Visual C++ before. In my case, I simply didn't have enough free RAM and excessive paging to disk was slowing the linking process to a halt. Doubling my RAM from 1GB to 2GB made a dramatic improvement. How much is your dev box running?
I just found out that we had by accident defined a large table of strings in a header file which got included in pretty much every (static) lib. (I am talking about a huge C++ project.) When the linker created the EXE, it looks like the unification of the table (there is only a single one ending up in the EXE) or the parsing of the libs took forever. Putting the table in a separate C++ file took a couple of minutes of the link on a relatively slow machine.
Unfortunately, I don't know how to find stuff like that other than by chance.
For debug builds, then one can use incremental linking, which can improve link times a lot.
Sadly enough there are certain pitfalls, and VS2005 will not warn you.
If using static libraries then incremental linking will not work if modifying a file part for the static library. The solution is to set the linker option "Use Library Dependency Inputs" to "Yes" (This is the same as Fast Solution Build in VS2003)
If using pragma-comment-lib to include the lib of a DLL, and specifies a relative path instead of the lib alone, then incremental linking will stop working. The solution is to specify the lib alone, and use the linker-option LIBPATH to add additional lib-path.
Some times the .ilk file will become corrupted (grow beyond 200 MByte) and then suddenly the incremental linker til take more than 10 times the normal time. Some times it will complain about the .ilk file being corrupt, but usually first after several minutes. The solution for me was to setup the following command for the "Build Event" -> "Pre-Link Event"
for %%f in ($(IntDir)*.ilk) do ( if "%%~zf" GTR "200000000" (del %%f))
60 libs to link does sound like a fair few. This may be a bit of an extreme measure, but it might radically speed things up. Create a new solution, with a few projects, and add all the source from your existing projects to these. Then build and link them instead, and just keep the small ones for testing.
Get a quicker computer with multiple processors and enable parallel builds (this might be on by default). To allow the greatest amount of parallism, make sure your project dependencies are correct and you haven't got unnecessary dependencies.
If you are truly talking about link times, then things like fast solution build and Xoreax won't really help much (except for Incredilink, which might). Assuming that you are truly measuring link start to link end, then I would suggest that the number of libs that you have is the issue.
The link phase is, at least initially, IO bound in loading up all of the object and lib files. You might be in a situation where you have 60 libraries along with the main project of some large number of .obj files. I suspect that you simply might be seeing, at least in part, typical windows slowness in loading up all of those libs and .obj files.
You can easily test this. Take all of those lib files and build one single lib file just as a test. Instead of linking with 60 of them, link with one and see where your time goes. That would be interesting.
NTFS is notoriosly slow. It shoudln't be 7m vs. 32 seconds on Linux slow, but it might be part of the issue. Using DLL's will help but you will suffer application startup time, although that will not be early as bad. I would be confident that you won't have 7m application start up times.
you can try looking at this: http://msdn.microsoft.com/en-us/library/9h3z1a69.aspx
Basically, you can run project builds in parallel if you have several cores.
I had solved my link problem and share to all of you.
My project's link time was 7 min with /Incremental:no linking (link time 7min).
Was 15 min with /Incremental, (link time 7min, embeded manifest time 7min). So I turn off the inremental.
I found Additional dependencies has a.lib AND ignore specific libraries has, too!
So I remove it from Ignore specific libraries turn on the /incremental. first link time need 5min but embeded manifest time has none.
I don't know why, but the incremental linking has worked.
I rollback all project code , so I could find the problem by the lib.
If you do all of above, you can try my method. Good luck!
Step 1 in C++ build time reduction is more memory. After switching from 4GB to 12GB, I saw my link-all-projects time fall off a cliff: from 5:50 to 1:15.