Why does std::array<std::string, 65536> a = {};
take more than 17 minutes to compile with gcc using -O3 on a Core i7 9700K processor?
I've stumbled on a problem with gcc where I've empty-initialized a std::array
with std::string
s in the header file, rather than doing it in a dedicated constructor in a source file. The file is included in multiple places, which resulted in an near endless optimization loop. With -O0
it promptly finished, however with -O1
I've waited for over an hour on a core i7-9700K processor and gcc is still running.
I finally narrowed down the problem to the empty initialization of std::array<std::string, N>
where N
is some large number. A similar problem can also be seen with other non-trivial constructors for other types where the compilation time is increasing linearly with the number of elements. Like the example below.
#include <array>
struct A {
A() : i(0) {}
int i;
};
int main() {
std::array<A, 65536> a = {};
return 0;
}
In an attempt to figure this out myself I've compiled the above code to assembly code. With -O0
the assembly looks like an unrolled for
loop of calls to the constructor with about 4 times the number of lines as the array size. When turning on optimization the initialization seems to be eliminated all together.
#include <array>
#include <string>
int main() {
std::array<std::string, 65536> a = {};
return 0;
}
When replacing the content of the array with a std::string
however the compiler seems to be unable to remove the initialization of std::string
even with optimization turned on.
I imagine this is part of the reason why my initial build got stuck in some endless optimization loop, but it does not explain it fully nor why clang seems to handle this so much better. Is there anyone that can shed some more light on this issue?
I have tried with a couple of gcc version ranging from gcc-6 to gcc-8. Even with gcc-4.9 it takes some time but not quite as much, clocking in on 4,5 minutes. Using clang with -stdlib=libstdc++ yields a compilation time of 0m0,120s.