s25client icon indicating copy to clipboard operation
s25client copied to clipboard

Speed Up build by placing #pragma once at the correct place

Open Flow86 opened this issue 6 years ago • 10 comments

We put our #pragma once in the header files at the wrong place. We have to put it before the include guard defines, otherwise it does not have any purpose.

Flow86 avatar Jul 03 '19 10:07 Flow86

Better: Remove it.

It is not supported by all compilers as it is non-standard and modern compilers do the same optimization for the header guards as they would for #pragma once. I personally do like the #pragma once more but I guess compatibility is more important

Flamefire avatar Jul 03 '19 10:07 Flamefire

modern compilers do the same optimization for the header guards as they would for #pragma once thats not true.

at least for gcc and Visual Studio using #pragma once has a significant impact. The fact is, the compiler does not need to continue parsing the whole file when reaching a #pragma once. otherwise the compiler always needs to do it even if the include guard afterwards will avoid double processing of the content afterwards.

Flow86 avatar Jul 03 '19 11:07 Flow86

oh and mostly only very old compilers or very specialized compiler do not have support for #pragma once

Flow86 avatar Jul 03 '19 11:07 Flow86

Sorry but that does not seem to be true

  • For gcc it is measured to not matter: https://web.archive.org/web/20080930061318/http://www.gamesfromwithin.com/articles/0501/000067.html
  • For VS 2003 it was around 20% faster
  • "Yet, since include guards appear very often and the overhead of opening files is significant, it's common for compilers to optimize the handling of include guards, making them as fast as #pragma once" https://en.wikipedia.org/wiki/Pragma_once
  • Cray compilers stopped supporting it: http://pubs.cray.com/content/S-2179/8.6/cray-c-and-c++-reference-manual-s-2179-86/miscellaneous-directives

As the cost of reintroducing header guards is exceptionally high I'd suggest not to remove them and instead rely on header guards and the compilers optimization for them

Flamefire avatar Jul 03 '19 11:07 Flamefire

Newer measurements: https://tinodidriksen.com/2011/08/cpp-include-speed/

MSVC:

  • Pragma only | 3.597
  • Ifndef only | 5.153

GCC:

  • Pragma only | 2.005
  • Ifndef only | 0.309

Clang:

  • Pragma only | 0.532
  • Ifndef only | 0.568

This is for ~50000 files/30000 includes. Hence speed does not matter.

Edit: And order of ifndef+pragma does also not matter.

Flamefire avatar Jul 03 '19 11:07 Flamefire

nobody spoke about removing the include guards. I don't know what they tested there, but here we definitly have an improvement since we used pragma once (and include guards) everywhere in the correct order - and also reordered all includes (perhaps the reason it got faster is the reordering) but that way every file was structured the same. Also if you have a quiet slow storage (i.e on virtual machines or similar) you have a significant speed increase with pragma + guard instead of guard+pragma

I will do it. I have seen that a lot of files have outdated or missing copyright headers anyway, so ...

Flow86 avatar Jul 03 '19 12:07 Flow86

nobody spoke about removing the include guards.

I'd rather not have both. The main advantage to me for #pragma once would be to not repeat things and reduce boilerplate which just adds noise when reading

I don't know what they tested there

I included the link. basically just including files

but here we definitly have an improvement since we used pragma once (and include guards) everywhere in the correct order

What is "here"? Is there really a (significant, measurable) benefit to using it? All other sources suggest not, so why spend work here?

Also if you have a quiet slow storage (i.e on virtual machines or similar) you have a significant speed increase with pragma + guard instead of guard+pragma

As written above and founded on sources: Clang+Gcc apply the same optimization on include guards as on pragma-once. So there is no difference there. So again: What is the foundation of that claim?

I will do it.

It's not about "lazyness" but on what is useful. Using both is rather disadvantageous to me.

I have seen that a lot of files have outdated or missing copyright headers anyway, so ...

Could you write a python script to update headers automatically? Do we need to use those lengthy headers or is a 1-2 liner maybe enough? Reducing the clutter and automating this (CI enforced?) would be great.

Flamefire avatar Jul 03 '19 12:07 Flamefire

Here is "in my recent company project".

We have about 1.000.000 files to compile, so even if it has only a minimal amount of time for 50000 files, it will save a lot time for a million. We got the compile from 4h down to about 1h simply by reordering includes and adding the pragmas.

would be to not repeat things and reduce boilerplate which just adds noise when reading

Yeah, but the file has a header anyway so...

It's not about "lazyness"

thats not the point. I only wanted to tell you, that I will do it ;-)

Do we need to use those lengthy headers or is a 1-2 liner maybe enough?

theoretically a 3 liner should be sufficient:

// Copyright (c) 2005 - 2019 Settlers Freaks (sf-team at siedler25.org)
//
// This file is part of Return To The Roots.
//
// SPDX-License-Identifier: GPL-2.0-or-later

we still have to add some file with the "full" disclaimer text

Flow86 avatar Jul 03 '19 12:07 Flow86

We have about 1.000.000 files to compile, so even if it has only a minimal amount of time for 50000 files,

But "we" (in this project) have only 3k. So even the benefit of the 50k case is down by a factor of 10. So I doubt the time saved will even be in the seconds for a full recompile. I do like the pragma once if it saves the bike-shedding of the include guard naming (you changed a couple of them already. Gotta be quite some work to get them all in sync) and reduced maintenance/review time. Having/Requiring both increases the dev time for (in this case) no benefit

theoretically a 3 liner should be sufficient:

Yes please! :+1: (BTW: GPL 2? Isn't it 3?)

we still have to add some file with the "full" disclaimer text

-> https://github.com/Return-To-The-Roots/s25client/blob/master/COPYING

Flamefire avatar Jul 03 '19 13:07 Flamefire

Found something useful for this: https://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html

TLDR: GCC optimizes for include guards unless anything but comments and whitespace is outside the guard

Anyway: I'd still like to use #pragma once only and don't care about compilers not supporting it if they still exist. It's just less work in creating and maintaining stuff...

Flamefire avatar Aug 14 '20 18:08 Flamefire