AlexSm 6d3e410c45 Remove CMakeLists from main (#2032) 7 months ago
..
README.md cc2baf0174 intermediate changes 2 years ago
dispatch_methods.cpp 8e7094c87f intermediate changes 2 years ago
dispatch_methods.h e5e7d3b69b [enum_parser] generate ToStringBuf specialization 2 years ago
enum_runtime.cpp 8e7094c87f intermediate changes 2 years ago
enum_runtime.h e5e7d3b69b [enum_parser] generate ToStringBuf specialization 2 years ago
ordered_pairs.cpp 8e7094c87f intermediate changes 2 years ago
ordered_pairs.h c04b663c7b intermediate changes 2 years ago
ya.make bf0f13dd39 add ymake export to ydb 1 year ago

README.md

Enum serialization runtime support library

{% note warning %}

This library should not be used or referred directly. Use GENERATE_ENUM_SERIALIZATION_WITH_HEADER and GENERATE_ENUM_SERIALIZATION macros instead.

{% endnote %}

Implementation details

Code bloat

Использование шаблонов вида TVector<EEnum>, std::array<EEnum> или TMap<EEnum, TStringBuf>, а также алгоритмов поверх них, приводит к значительному разбуханию коде. Так как компилятор для разных перечислений вынужден генерировать разные специализации, даже если они компилируются в идентичный машинный код. Можно во многом выиграть если хранить не массив из EEnum, а массив из std::underlying_type_t<EEnum> (или из TSelectEnumRepresentationType<EEnum>::TType). Ведь различных типов-перечислений намного больше, чем целочисленных типов, на которых они базируются (и тем более больше, чем различных TSelectEnumRepresentationType::TType, коих всего четыре). И когда компилятор встречает вызов std::lower_bound, то для двух массивов из двух перечислений enum A: int {} и enum B: int{} он создаст две специализации, а если использовать целочисленные типы — то только одну. Всё это позволяет вынести вызовы вроде std::lower_bound в универсальные и переиспользуемые функции, принимающие например (TArrayRef<const int> values, int enumValue) своими аргументами. За счёт этого код 1) быстрее компилируется, 2) результат получается более компактным, 3) как следствие, он меньше засоряет во время исполнения кеш инструкций процессора одинаковыми или очень похожими специализациями функций.

Преобразование между enum и int выносится в пользовательский код (в шаблонные inline функции), и производится только в момент непосредственного использования (первым действием в семействе функций ToString, последним действием в семуйстве функций FromString), где оптимизирующий компилятор обычно может заменить их на no-op или на простые операции со значениями в регистрах. А контейнеры вида TVector<EEnum> и TMap<EEnum, ...>, которые возвращаются из функций util/generic/serialized_enum.h, заменяются на специальные классы TArrayView и TMappedDictView. Они также поддерживают быстрое и преобразование из перечислений в целочисленные типы и обратно в момент использования, и не требуют создавать специализации для каждого из возможных типов-перечислений.