Комментарии 33
Для большей гибкости, так как в общем случае тип ColdData
может быть не перемещаемым и не копируемым.
m.emplace(std::piecewise_construct, ...)
А доступ к элементам мэп не защищён блокировками потому, что… ?
Ну чего лучше это понятно. Вопрос почему автор об этом не сказал ни слова. В любом случае *concurent*map* from *.h* обычно стоит таки не бесплатно, т.к. потокобезопасность не волшебными гномиками достигается. Соответственно, автор либо показал не всё решение, либо его бенчмарк не отражает картину в целом, либо в реализации есть банальная ошибка. Либо не описал ограничения подхода.
Я своими глазами видел в горячем mission critical коде подобный подход с доступом к мапе без блокировки, и как ни странно, он работал годами, ну иногда баги там какие то странные всплывали раз в полгода...
Так как подразумевается, что доступ к «холодным» данным явление редкое, то добавление блокировок не сильно уменьшит производительность, а параллелится, скорей всего обработка массивов с «основными» данными.
Тогда, считать наносекунды на фоне i/o слегка странно.
На самом деле, я даже уверен что блокировка не попортит avg, немножко больше вылетов в распределении будет и то в менее синтетических тестах нежели у автора.
Я скорее к тому, что распараллеливание такого сервиса даст более драматичный прирост производительности. И тогда, остаётся только кейс с одно ядерными системами, что довольно редко в наше время. Второй момент — речь идёт о поддержании чистоты кэша, но, если на этом же ядре будет происходить ввод/вывод то все потуги со структурами массивов кажутся каплей в море ибо кэшем будет в общем то заправлять ядро. Т.е. для одноядерного сценария с i/o, лично мне, это кажется оптимизацией уровня писать на асме вместо C.
А можно сделать третий шаблонный аргумент с указанием стратегии блокировки, которая по умолчанию ничего не делает.
Мне кажется, API можно сильно упростить если вместо ColdData&
выставлять наружу std::unique_ptr<ColdData>&
.
В частности, пропадут TwoPhaseInit, init_cold_data и reset_cold_data
Такой же принцип используется в golang'e, только там ещё буфера (структуры) сортируются по частоте обращений — возможно будет полезно для вашего случая, так как там получается даже более чем в 10 раз быстрее.
OutOfLine – паттерн размещения в памяти для высокопроизводительных приложений на C++