C++precompiled headers and modules to reduce compilation time

C++precompiled headers and modules to reduce compilation time

C++ modules are one of the hot topics of the new C++ 20 standard, but as of today, February 2022, most compilers fail to deliver the promise in a stable, cross-platform way. Nevertheless, it is possible to take some advantage of this exciting new feature and benefit from a nice reduction in compile times, and it's even better when combined with the well-known pre-compiled headers that most C++ compilers support today.

Consider this simple program and a header-only cross-platform (Win/Linux) library:

main.cpp:

#include <iostream>
#include "sysinfo.hpp"

int main(){

  std::cout << "Hostname: " << getHostName() << std::endl;
  
  std::cout << "Free RAM (MB): " << getFreeMemory() << std::endl;
  
}        

sysinfo.hpp:

#ifndef SYSINFO_HPP
#define SYSINFO_HPP_


#include <string>
#include <unistd.h>


#ifdef _WIN32
#include <windows.h>
#endif


inline std::string getHostName();
inline size_t getFreeMemory();


inline std::string getHostName() {
#ifdef _WIN32
	TCHAR  infoBuf[100];
	DWORD  bufCharCount = 100;
	GetComputerName( infoBuf, &bufCharCount );
	std::string winName(infoBuf);
	return winName;
#endif
#ifdef __linux__
	char hostname[100];
	gethostname(hostname, 100);
	std::string posixName(hostname);
	return posixName;
#endif
}


inline size_t getFreeMemory() {
#ifdef _WIN32
	 MEMORYSTATUSEX status;
	 status.dwLength = sizeof(status);
	 GlobalMemoryStatusEx(&status);
	 return status.ullAvailPhys/1024/1024;
#endif
#ifdef __linux__
	 long phys_page_size = sysconf( _SC_AVPHYS_PAGES );
	 long page_size = sysconf( _SC_PAGESIZE );
	 return (phys_page_size * page_size)/1024/1024;
#endif
}


#endif /* SYSINFO_HPP_ */

_        

The header sysinfo.hpp is a header-only library with some conditional compilation directives in order to compile the same file on Linux and Windows and return proper values according to the platform.

To compile and run these examples I will be using GCC 11.1 on Ubuntu Server 20.04.

Test #1: classic compile using the "time" Linux command to measure the time it took.

time g++ -O3 -std=c++20 main.cpp -o test

real    0m0.338s
user    0m0.320s
sys     0m0.018s
        

It took 0.338s using the "-O3" high optimization level to produce fast and efficient code. Now let's compile the header and then we will compile the main program again.

g++ -O3 -std=c++20 -c sysinfo.hpp        

It will generate a (big) file named sysinfo.hpp.gch on the same directory. From now on, the compiler will use this pre-compiled header instead of the plain .hpp file, let's test it:

time g++ -O3 -std=c++20 main.cpp -o test

real    0m0.165s
user    0m0.149s
sys     0m0.016s
        

That's about 51% less time for compiling and building the executable. Not bad.

We will use a C++ 20 module for importing <iostream> standard library, when using G++ we must pre-compile the standard headers executing this command in the same directory we are using for our program:

g++ -O3 -std=c++20 -fmodules-ts -x c++-system-header string
g++ -O3 -std=c++20 -fmodules-ts -x c++-system-header iostream
        

This will create a directory named gcm.cache containing pre-compiled C++ 20 modules of these headers, now we will make some changes to the source code of main.cpp in order to import the module <iostream> instead of the plain old #include.

main.cpp:

#include "sysinfo.hpp"
import <iostream>; // <--- this is the only change
        

Now we will compile the main program again...

time g++ -O3 -fmodules-ts -std=c++20 main.cpp -o test

real    0m0.152s
user    0m0.137s
sys     0m0.015s
        

That's a 55% reduction in compile-time, combining C++ 20 modules and good old pre-compiled headers, just changing the main program a bit. If a change is made to the main program code, that is the only unit that needs to be recompiled, you can somewhat extrapolate this case to a more complex scenario, some trial & error will be necessary to obtain the best results for your particular case.

Why not go the extra mile and transform sysinfo.hpp into a modern C++ 20 module? because given the current level of C++ modules implementation by GCC 11... I would probably lose my will to live! particularly when compiling on Windows.

We are going to incorporate this building-tuning technique for our MicroServer++ platform, it's a small project in terms of complexity, but no one is going to give me back the 12 seconds of my life it takes to build. #simplicityworks

If you want to install GCC 11 on your Ubuntu 20.04, please follow this recipe we prepared and tested in order to compile our MicroServer++ on Linux:

GCC 11 on Ubuntu 20.04

An excellent introduction to C++ 20 modules by Daniela Engert:


To view or add a comment, sign in

More articles by Martín Córdova

  • C++ Server - QuickStart with Kubernetes - Part 1

    In a few minutes, using your Windows 10 Pro PC or Laptop, you can install and test our free C++ microservices engine…

  • QuickStart con CPPServer y Kubernetes

    Llegó la hora, hemos liberado para uso gratuito nuestro engine de microservicios en C++, este es un QuickStart para…

    2 Comments
  • Observability you said? C++? Ok

    CPPServer, nuestro engine de microservicios escrito en C++, pesa 300K, compilado a código nativo optimizado y lo…

  • Kubernetes-Fest en Windows 10 cortesía de Ubuntu

    Multipass de Canonical vino a cambiar el juego en cuanto a virtualización, y que lo haga en Windows 10 Pro es aun más…

  • Instalación express de una BD de demo con PostgreSQL y Docker

    Estamos próximos a liberar para uso gratuito nuestra plataforma de microservicios C++, corre en Kubernetes y en Azure…

    13 Comments
  • Renovación automática de certificados con Docker y HAProxy

    Los certificados SSL gratuitos con Let's Encrypt están muy de moda, obtenerlos y renovarlos son tareas que se pueden…

  • World's smallest thread pool in C++

    OK, the title is a trap, maybe it won't be the smallest but close I hope, I finally put the sacred red book into good…

  • Entonando acceso a la red en Docker

    Vamos a mostrar como mejorar la configuración de red de los containers Docker, sobre todo para los servidores, pero es…

  • Automatizando OCSP SSL con Docker y HAProxy

    Voy a mostrar como resolvemos la renovación automática del archivo OCSP emitido por la entidad que generó el…

  • Modern C++ vs ODBC API

    Our C++ microservices platform includes a header-only library that encapsulates ODBC API in a very pragmatic way, just…

Others also viewed

Explore content categories