-
Notifications
You must be signed in to change notification settings - Fork 161
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve field count typical case performance (#120)
The tightest upper bound one can specify on the number of fields in a struct is `sizeof(type) * CHAR_BIT`. So this was previously used when performing a binary search for the field count. This upper bound is extremely loose when considering a typical large struct, which is more likely to contain a relatively small number of relatively large fields rather than the other way around. The binary search range being multiple orders of magnitude larger than necessary wouldn't have been a significant issue if each test was cheap, but they're not. Testing a field count of N costs O(N) memory and time. As a result, the initial few steps of the binary search may be prohibitively expensive. The primary optimization introduced by these changes is to use unbounded binary search, a.k.a. exponential search, instead of the typically loosely bounded binary search. This produces a tight upper bound (within 2x) on the field count to then perform the binary search with. As an upside of this change, the compiler-specific limit placed on the upper bound on the field count to stay within compiler limits could be removed.
- Loading branch information
Showing
10 changed files
with
1,369 additions
and
75 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright (c) 2023-2024 Antony Polukhin | ||
// | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#include <boost/pfr/tuple_size.hpp> | ||
|
||
struct A { | ||
template <typename... Args> | ||
explicit A(Args&&...) {} | ||
}; | ||
|
||
int main() { | ||
(void)boost::pfr::tuple_size<A>::value; // Must be a compile time error | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright (c) 2023-2024 Antony Polukhin | ||
// | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#include <boost/pfr/tuple_size.hpp> | ||
|
||
struct A { | ||
template <typename Arg0, typename... Args> | ||
explicit A(Arg0&&, Args&&...) {} | ||
}; | ||
|
||
int main() { | ||
(void)boost::pfr::tuple_size<A>::value; // Must be a compile time error | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// Copyright (c) 2023-2024 Antony Polukhin | ||
// | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#include <boost/pfr/detail/fields_count.hpp> | ||
|
||
int main() { | ||
return static_cast<int>(boost::pfr::detail::fields_count<BOOST_PFR_RUN_TEST_ON>()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Copyright (c) 2024 Antony Polukhin | ||
// | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#include <boost/pfr/tuple_size.hpp> | ||
|
||
#include <climits> | ||
#include <cstdint> | ||
|
||
#if defined(__clang__) | ||
# if SIZE_MAX > (1ULL << 32) - 1 | ||
# define ARRAY_MAX (SIZE_MAX >> 3) | ||
# else | ||
# define ARRAY_MAX SIZE_MAX | ||
# endif | ||
# define OBJECT_MAX SIZE_MAX | ||
#elif defined(__GNUC__) | ||
# define ARRAY_MAX INT_MAX | ||
# define OBJECT_MAX (SIZE_MAX >> 1) | ||
#elif defined(_MSC_VER) | ||
# define ARRAY_MAX INT_MAX | ||
# define OBJECT_MAX UINT_MAX | ||
#else // Let's play it safe | ||
# define ARRAY_MAX INT_MAX | ||
# define OBJECT_MAX INT_MAX | ||
#endif | ||
|
||
#pragma pack(1) | ||
struct A { | ||
char x[ARRAY_MAX <= (OBJECT_MAX >> 3) ? ARRAY_MAX : OBJECT_MAX >> 3]; | ||
}; | ||
|
||
struct B { | ||
A a; | ||
A b; | ||
A c; | ||
A d; | ||
A e; | ||
A f; | ||
A g; | ||
A h; | ||
}; | ||
|
||
struct C { | ||
A& a; | ||
A b; | ||
A c; | ||
A d; | ||
A e; | ||
A f; | ||
A g; | ||
A h; | ||
}; | ||
#pragma pack() | ||
|
||
int main() { | ||
#ifndef _MSC_VER | ||
static_assert(boost::pfr::tuple_size_v<char[ARRAY_MAX]> == ARRAY_MAX, ""); | ||
#endif | ||
static_assert(boost::pfr::tuple_size_v<B> == 8, ""); | ||
static_assert(boost::pfr::tuple_size_v<C> == 8, ""); | ||
} |
Oops, something went wrong.