This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/67565] [concepts] Very slow compile time and high memory usage with complex concept definitions, even if unused
- From: "tom at honermann dot net" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Fri, 15 Jan 2016 04:43:52 +0000
- Subject: [Bug c++/67565] [concepts] Very slow compile time and high memory usage with complex concept definitions, even if unused
- Auto-submitted: auto-generated
- References: <bug-67565-4 at http dot gcc dot gnu dot org/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67565
Tom Honermann <tom at honermann dot net> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |andrew.n.sutton at gmail dot com,
| |asutton at gcc dot gnu.org,
| |tom at honermann dot net
--- Comment #2 from Tom Honermann <tom at honermann dot net> ---
I'm also experiencing this issue and finding it to be rather catastrophic at
present. I'm currently using gcc trunk (r232017).
I distilled the following test case from my project before coming across this
bug report. The test cases shares some properties with the one in comment 0;
no actual instantiations of the class template (or function for Adrian's test
case) are needed to trigger the issue, both conjunctions and disjunctions are
present.
This test case includes some conditional compilation options intended to
demonstrate that syntactic transformations that should have no semantic affect
have dramatic compile time performance impact; search for GO_FAST1 and
GO_FAST2. Additionally, defining the GO_SLOWER1 macro demonstrates a means of
scaling the performance impact.
$ cat t.cpp
$ cat t.cpp
template<typename T>
concept bool
C1()
{
return sizeof(T) > 4;
}
template<typename T>
constexpr bool
f1()
{
return C1<T>();
}
template<typename T>
constexpr bool
f2()
{
return f1<T>()
|| f1<T>()
|| f1<T>()
|| f1<T>()
|| f1<T>();
}
template<typename T>
concept bool
C2()
{
#if GO_FAST1
return f2<T>();
#else
return f1<T>()
|| f1<T>()
|| f1<T>()
|| f1<T>()
#if GO_SLOWER1
|| f1<T>()
#endif
|| f1<T>();
#endif
}
template<typename T>
concept bool C3() {
return C2<T>()
&& (C1<T>()
|| C1<T>()
|| C1<T>());
}
template<typename T>
concept bool C4() {
return C3<typename T::type1>()
&& C3<typename T::type2>();
}
template<typename T>
concept bool C5() {
return C4<T>();
}
template<typename T>
concept bool C6() {
return C5<T>()
&& true;
}
#if GO_FAST2
template<typename C>
requires C4<C>()
&& C5<C>()
&& C6<C>()
#else
template<C4 C>
requires C5<C>()
&& C6<C>()
#endif
struct S {
};
$ time g++ -c -std=c++1z t.cpp
real 0m9.485s
user 0m8.672s
sys 0m0.820s
$ time g++ -c -std=c++1z t.cpp -DGO_FAST1
real 0m0.027s
user 0m0.008s
sys 0m0.008s
$ time g++ -c -std=c++1z t.cpp -DGO_FAST2
real 0m0.064s
user 0m0.056s
sys 0m0.000s
$ time g++ -c -std=c++1z t.cpp -DGO_SLOWER1
real 0m30.464s
user 0m26.100s
sys 0m2.832s
The GO_SLOWER1 test peaks at about 10G of virtual memory for me.