-
Notifications
You must be signed in to change notification settings - Fork 1
/
stuple_stress.cpp
125 lines (97 loc) · 3.69 KB
/
stuple_stress.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// SPDX-License-Identifier: BSL-1.0
/*
This source file is used to stress yymp::stuple against std::tuple.
This is not a criticism of the std::tuple implementation; std::tuple has
particular requirements that can cause issues with compile times when overused.
The stress test consists of accumulating into a tuple by overloading operator+
via a wrapping type. In such a situation, one single concatenation operation
is preferred, but in some circumstances (e.g. in embedded DSLs) this is not
always doable.
Usage:
gcc -c stuple_stress.cpp -std=c++20 -I{PATH TO YYMP INCLUDE} -DTEST_DEPTH=50 -DYYMP_STRESS_STD_TUPLE
gcc -c stuple_stress.cpp -std=c++20 -I{PATH TO YYMP INCLUDE} -DTEST_DEPTH=50
The first line tests std::tuple. The second tests yymp::stuple.
Total compile time (in seconds) on my system (using -ftime-report)
TEST_DEPTH=50 TEST_DEPTH=100 TEST_DEPTH=150
std::tuple 4.85 32.05 319.47
yymp::stuple 0.79 1.62 3.40
$ gcc --version
gcc.exe (Rev8, Built by MSYS2 project) 11.2.0
*/
#include <cstddef>
#include <utility>
#include <type_traits>
// Set the default test depth, if not supplied at the command line
#ifndef TEST_DEPTH
# define TEST_DEPTH 100
#endif
// Imitates some type that is distinct under some non-type template parameter.
template<auto> struct Unique { };
// Wraps a tuple type and overloads operator+ which concatenates to the tuple
// on the right.
// If YYMP_STRESS_STD_TUPLE is defined, then std::stuple_cat is used.
// Otherwise, yymp::stuple_cat is used.
template<typename Tuple>
struct tuple_catter
{
Tuple t;
}; template<typename Tuple> tuple_catter(Tuple) -> tuple_catter<Tuple>;
// Provides member type which is the tuple type that results from the test.
template<typename IndexSequence>
struct make_test_tuple;
#ifndef YYMP_STRESS_STD_TUPLE
#include <yymp/stuple.hpp>
template<typename TupleA, typename TupleB>
constexpr auto operator+(const tuple_catter<TupleA>& a, const tuple_catter<TupleB>& b)
{
return tuple_catter{::yymp::stuple_cat(a.t, b.t)};
}
template<typename TupleA, typename X>
constexpr auto operator+(const tuple_catter<TupleA>& a, const X& x)
{
return tuple_catter{::yymp::stuple_cat(a.t, ::yymp::stuple{x})};
}
constexpr ::yymp::stuple empty_tuple {};
template<::std::size_t... I>
struct make_test_tuple<::std::index_sequence<I...>>
{
using type = ::yymp::stuple<Unique<I>...>;
};
#else
#include <tuple>
template<typename TupleA, typename TupleB>
constexpr auto operator+(const tuple_catter<TupleA>& a, const tuple_catter<TupleB>& b)
{
return tuple_catter{::std::tuple_cat(a.t, b.t)};
}
template<typename TupleA, typename X>
constexpr auto operator+(const tuple_catter<TupleA>& a, const X& x)
{
return tuple_catter{::std::tuple_cat(a.t, ::std::tuple{x})};
}
constexpr ::std::tuple empty_tuple {};
template<::std::size_t... I>
struct make_test_tuple<::std::index_sequence<I...>>
{
using type = ::std::tuple<Unique<I>...>;
};
#endif // YYMP_STRESS_STD_TUPLE
// Synthesizes an expression that effectively joins many tuples through a
// concatenation method, one pair at a time.
// While one can and should join them all at once using a single call to the
// concatenation function, this is not always possible.
template<::std::size_t... I>
constexpr
auto test(::std::integer_sequence<::std::size_t, I...>)
{
return (tuple_catter{empty_tuple} + ... + Unique<I>{});
}
constexpr auto foo = test(::std::make_index_sequence<TEST_DEPTH + 1>{}).t;
// Verify the tuple type that results from the test.
static_assert(std::is_same_v<
decltype(foo),
const typename make_test_tuple<::std::make_index_sequence<TEST_DEPTH + 1>>::type
>);
int main()
{
}