Skip to content

Commit 8c087c4

Browse files
yfeldblummeta-codesync[bot]
authored andcommitted
enum_find array-lookup tweaks
Summary: * Use 2 bytes per entry v.s. 16 bytes per entry. But paid for by forcing all of the `TEnumDataStorage<>::names` symbols (v.s. just copying the arrays and removing the symbols). So roughly zero change in build size. * Slightly nicer symbol names. Reviewed By: Mizuchi Differential Revision: D87139981 fbshipit-source-id: ec4d0223922436794f6ef05eace773a855aa83b2
1 parent a127a11 commit 8c087c4

File tree

1 file changed

+28
-37
lines changed

1 file changed

+28
-37
lines changed

thrift/lib/cpp2/gen/module_types_cpp.h

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -178,51 +178,42 @@ FOLLY_EXPORT FOLLY_ALWAYS_INLINE enum_find<U>& enum_find_instance() {
178178
return impl;
179179
}
180180

181-
template <typename E, typename = void>
182-
inline constexpr bool eligible_for_dense_enum_optimization_v = false;
183-
184-
// Empty Thrift enums as well as empty Thrift union tag enums do NOT
185-
// have TEnumtraits<E>::min()/max() static methods. Instead of failing
186-
// the build, we will just exclude them from the dense enum optimization.
187-
// It is reasonable to expect few would call `enum_find_name` on an
188-
// empty enum. So it should not miss any major optimizations.
189-
// Since C++ allows `static_cast<E>()` with any value representable
190-
// by the underlying type, it's better to just fallback to the unoptimized
191-
// path instead of failing to build.
192181
template <typename E>
193-
inline constexpr bool eligible_for_dense_enum_optimization_v<
194-
E,
195-
folly::void_t<decltype(TEnumTraits<E>::max())>> =
196-
(((folly::to_underlying(TEnumTraits<E>::max()) -
197-
folly::to_underlying(TEnumTraits<E>::min())) <
198-
2 * TEnumTraits<E>::size) ||
199-
((folly::to_underlying(TEnumTraits<E>::max()) -
200-
folly::to_underlying(TEnumTraits<E>::min())) < 16)) &&
201-
(TEnumTraits<E>::size < 10'000);
182+
consteval auto enum_find_name_dense_array_make() {
183+
using T = TEnumTraits<E>;
184+
using D = TEnumDataStorage<E>;
185+
constexpr auto min = folly::to_underlying(T::min());
186+
constexpr auto max = folly::to_underlying(T::max());
187+
std::array<int16_t, max - min + 1> ret;
188+
for (auto& e : ret) {
189+
e = -1;
190+
}
191+
for (size_t i = 0; i < T::size; ++i) {
192+
ret[folly::to_underlying(D::values[i]) - min] = i;
193+
}
194+
return ret;
195+
}
196+
197+
template <typename E>
198+
inline constexpr auto enum_find_name_dense =
199+
enum_find_name_dense_array_make<E>();
202200

203201
template <typename E, typename U = std::underlying_type_t<E>>
204202
FOLLY_ERASE bool enum_find_name(
205203
E const value, std::string_view* const out) noexcept {
206-
if constexpr (eligible_for_dense_enum_optimization_v<E>) {
207-
static constexpr auto index = []() consteval {
208-
constexpr auto min = folly::to_underlying(TEnumTraits<E>::min());
209-
constexpr auto max = folly::to_underlying(TEnumTraits<E>::max());
210-
constexpr auto size = TEnumTraits<E>::size;
211-
std::array<std::string_view, max - min + 1> ret;
212-
for (size_t i = 0; i < size; ++i) {
213-
ret[folly::to_underlying(TEnumDataStorage<E>::values[i]) - min] =
214-
TEnumDataStorage<E>::names[i];
215-
}
216-
return ret;
217-
}();
204+
constexpr auto sz = TEnumTraits<E>::size;
205+
// excludes empty enums and empty union tag enums, but these are typically
206+
// unlikely to be searched anyway
207+
if constexpr (sz && sz <= 4096) {
218208
constexpr auto min = folly::to_underlying(TEnumTraits<E>::min());
219209
constexpr auto max = folly::to_underlying(TEnumTraits<E>::max());
220-
const auto under = folly::to_underlying(value);
221-
if (under < min || under > max) {
222-
return false;
210+
constexpr auto gap = max - min;
211+
if constexpr (gap < 2 * sz || gap < 16) {
212+
constexpr auto& index = enum_find_name_dense<E>;
213+
const auto under = folly::to_underlying(value);
214+
const auto idx = under < min || under > max ? -1 : index[under - min];
215+
return idx >= 0 && ((*out = TEnumDataStorage<E>::names[idx]), true);
223216
}
224-
std::string_view name = index[under - min];
225-
return !name.empty() && ((*out = name), true);
226217
}
227218
const auto r = enum_find<U>::find_name(U(value), enum_find_instance<E>());
228219
return r && ((*out = r.result), true);

0 commit comments

Comments
 (0)