How to accelerate compilation of C ++ code

Source: Internet
Author: User
Tags perl script

C ++CodeIt has always been a high-performance and high-profile face to the world during its operation, but speaking of the Compilation speed, there is only a low-key copy. For exampleSource codeEven if you use incredibuild to mobilize nearly machines, it may take four hours to build a complete build !!! Although normal development usually does not require a complete build locally, it is enough to compile several related projects for you to wait for a long time (this is called monkey around und by foreigners ). Think about the scenario that has been working on a single core at GHz for several years-put a book in front of you and click the build button to read the book for a while ~~~ The past is terrible.

As you can imagine, if you do not pay attention to it, the Compilation speed is very likely to become a bottleneck in the development process. So why is C ++ compilation so slow?

One of the most important reasons is the compilation model of C ++'s basic "header file-source file:

    1. Each source file, as a compilation unit, may contain hundreds or even thousands of header files. In each compilation unit, these header files are read from the hard disk and parsed.
    2. Each compilation unit generates an OBJ file, so these OBJ files will be linked together, and this process is difficult to parallel.

Here, the problem lies in repeated load and resolution of numerous header files and intensive disk operations.

The following describes how to speed up compilation from various perspectives, mainly aiming at the key issue raised above.

Code perspective
  • Use a pre-declaration in the header file instead of directly containing the header file.
    Do not think that you only add a header file. This effect may be infinitely magnified due to the "included" feature of the header file. Therefore, we need to streamline the header file as much as possible. In many cases, it is difficult to declare a class in a namespace in front of the namespace, and the direct include operation is much more convenient. You must resist this temptation. The class members and function parameters should also be referenced as much as possible and pointers, create conditions for the pre-declaration.

  • Use pimpl Mode
    All pimpl is called Private implementation. The interfaces and implementations of traditional C ++ classes are confused, while pimpl completely isolates the interfaces and implementations of classes. In this way, as long as the public interfaces of the class remain unchanged, only the CPP needs to be compiled for class implementation modifications. At the same time, header files provided by the class to the outside world will be much simpler.

  • Highly modular
    Modularization means low coupling, and mutual dependency is minimized. There are actually two meanings here. First, the changes in one header file between files should not cause re-compilation of other files; second, the modifications to one project between the project and the project, try not to cause too much compilation for other projects. This requires that the header file or project content must be single, and nothing should be inserted in it, thus causing unnecessary dependencies. This can also be called cohesion.

    Take the header file as an example. Do not put two irrelevant classes or macro definitions that are unrelated to each other in a header file. The content should be as single as possible, so that the files containing them do not contain unwanted content. I remember that we once did this. We found out the header files in the most "hot" code and divided them into several independent small files. The effect was quite impressive.

    In fact, the refactoring we did last year separates many DLL files into two parts: the UI and core, which have the same effect-improving development efficiency.

  • Delete redundant header files
    Some codes have been developed and maintained over the last ten years, and there are countless people involved. It is very likely that they contain useless header files or duplicate include files. Removing these redundant include files is quite necessary. Of course, this is mainly for CPP, because for a header file, it is difficult to define whether a specific include is redundant. It depends on whether it is used in the final compilation unit, this may be used in a compilation unit, but not in another compilation unit.
    I have previously written a Perl script to automatically remove these redundant header files. In a project, more than 5000 include files are removed.

  • Pay special attention to inline and template
    This is two more "advanced" mechanisms in C ++, But they force us to include the implementation in the header file, which adds the header file content, this slows down compilation. Before using it, consider it.
Comprehensive Skills
    • Pre-compiled header file (PCH)
      Place common but infrequently modified header files in pre-compiled header files. In this way, at least in a single project, you do not need to load and parse the same header file once and again in each compilation unit.

    • Unity build
      The Unity build method is very simple. It includes all CPP into one CPP (all. cpp) and only compiles all. cpp. In this way, we only have one compilation unit, which means that we do not need to reload and parse the same header file, because only one OBJ file is generated, you do not need to perform intensive disk operations during the connection. It is estimated that there will be a 10 x improvement. Let's take a look at this video to see how it works and how it works.
    • Ccache
      Compiler cache, By caching the last compiled results, enables rebuild to greatly speed up keeping the results the same. We know that if it is a build, the system will compare the Time of the source code with the target code to determine whether to re-compile a file, this method is not completely reliable (for example, the Code of the previous version is obtained from SVN), while the principle of ccache judgment is the file content, which is more reliable than other methods. Unfortunately, Visual Studio does not support this function yet-you can add a new command, such as cache build, between build and rebuild, rebuild is useless.
    • Do not have too many additional include directories
      The compiler locates your include header file and searches based on the include directories you provide. As you can imagine, if you provide 100 contained directories and a header file is under 100th directories, it is very painful to locate it. Organize your include directories and keep them as concise as possible.
Compile Resources

To increase the speed, either reduce the number of tasks or increase the number of workers, the previous two aspects are all about reducing the number of tasks. In fact, the number of workers who increase the compilation speed is still very important.

    • parallel compilation
      buy a 4-core CPU or an 8-core CPU. Each build means that 8 files are compiled in parallel, which is a great speed. If your boss does not agree, let him read this Article : hardware is cheap, programmers are expensive

    • better disks
      we know that the compilation speed is very slow because of disk operations. In addition to minimizing disk operations, what we can do is speed up the disk. For example, when the above eight cores work together, the disk is likely to become the biggest bottleneck. Buy a 15000 rpm disk, or an SSD, or RAID 0 disk. In short, the sooner the better.

    • distributed compilation
      the performance of a single machine is always limited, using idle CPU resources in the network, and the build server dedicated for compilation to help you compile to fundamentally solve the problem of our compilation speed. Think about how long it would take to build the project within 2 minutes, you will know that you must not have it-incredibuild.

    • this can be done in parallel.
      This is an extreme situation. If you use incredibuild and are not satisfied with the final compilation speed, what should you do? In fact, as long as you jump out of the framework of thinking, the Compilation speed can still be a qualitative leap-the premise is that you have enough machines:

      assume that you have solution a and solution B, and B depends on a, so you must build B after. It takes one hour for a and B to build each, so it takes two hours in total. But must B be built after? Out of this framework, you have the following solutions:

      • Build A and B at the same time.
      • A's build is successful. Although B's build fails, it only fails on the last link.
      • re-link the project in B.

      in this way, by parallel compilation of build a and B, link the project in B, the entire Compilation speed should be controlled within 1 hour and 15 minutes.

In addition, this book talks about many things in this regard: large-scale C ++ programming.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.