Как стать автором
Обновить

Комментарии 33

А зачем использовать unique_ptr в map? Нельзя просто класть данные по типу?

Для большей гибкости, так как в общем случае тип ColdData может быть не перемещаемым и не копируемым.

Такие типы довольно хорошо в мапу ложаться. Для этого можно использовать
m.emplace(std::piecewise_construct, ...)
А как их перемещать при перемещении основного объекта?
Ну, если ColdData не поддерживает перемещение, то может и не поддерживать перемещение основного объекта? Хотя да, об этом я не подумал
мапе ж не нужно перемещать/копировать объекты, достаточно сравнивать, емплейсить ну и удалять
Да правильно, нахрена что-то получать из мапы — достаточно добавлять и удалять.
«получать из мапы» можно и по ссылке. Разумеется, подумав о владении
НЛО прилетело и опубликовало эту надпись здесь
Здорово! Жаль, что GCC только начиная с 7.1 это поддерживает.

А доступ к элементам мэп не защищён блокировками потому, что… ?

потому что блокировки в такой ситуации(вычислительно-интенсивном алгоритме), при большом количестве потоков ещё большее зло, Если уж радеем за каждый flops то уж лучше concurrent_unordered_map из tbb

Ну чего лучше это понятно. Вопрос почему автор об этом не сказал ни слова. В любом случае *concurent*map* from *.h* обычно стоит таки не бесплатно, т.к. потокобезопасность не волшебными гномиками достигается. Соответственно, автор либо показал не всё решение, либо его бенчмарк не отражает картину в целом, либо в реализации есть банальная ошибка. Либо не описал ограничения подхода.


Я своими глазами видел в горячем mission critical коде подобный подход с доступом к мапе без блокировки, и как ни странно, он работал годами, ну иногда баги там какие то странные всплывали раз в полгода...

Возможно в их случае это не нужно, например, все объекты создаются в одном потоке при старте программы, и уничтожаются в том же потоке при завершении. Доступ к «холодным» данным осуществяется только в исключительных случаях, которые могут обрабатываться том же потоке, где и были созданы (мало ли как у них построена система).

Так как подразумевается, что доступ к «холодным» данным явление редкое, то добавление блокировок не сильно уменьшит производительность, а параллелится, скорей всего обработка массивов с «основными» данными.

Вот эти слова с ограничениями хотелось бы видеть в статье или в переводе. Можно например у авторов спросить — как так?

Может быть у них все работает в одном потоке?

Тогда, считать наносекунды на фоне i/o слегка странно.

Согласен, что пример неудачный, но подход то рабочий.

На самом деле, я даже уверен что блокировка не попортит avg, немножко больше вылетов в распределении будет и то в менее синтетических тестах нежели у автора.

Блокировки будут при создании/удалении элементов, которые лежат в векторе. Это тоже накладывают нюансы. А оптимизация на одном потоке при i/o не такая уж и редкая задача. Однопоточные сервисы никуда не делись.

Я скорее к тому, что распараллеливание такого сервиса даст более драматичный прирост производительности. И тогда, остаётся только кейс с одно ядерными системами, что довольно редко в наше время. Второй момент — речь идёт о поддержании чистоты кэша, но, если на этом же ядре будет происходить ввод/вывод то все потуги со структурами массивов кажутся каплей в море ибо кэшем будет в общем то заправлять ядро. Т.е. для одноядерного сценария с i/o, лично мне, это кажется оптимизацией уровня писать на асме вместо C.

Насколько понимаю, разработчики tarantool стараются оптимизировать расположения элементов в памяти.

Я опыта с этой поделкой не имел, но по описанию в интернете это in memory database? Там i/o сильно условный и в юзерспейсе происходит нет?

С тем же успехом закрыть блокировками доступ можно и снаружи, если предполагается использовать многопоточные сценарии. На однопоточный сценарий навешивать блокировки плохо.
А можно сделать третий шаблонный аргумент с указанием стратегии блокировки, которая по умолчанию ничего не делает.

Звучит разумно.

Кроме многопоточности, автор, также, ничего не говорит о UB в случае использования таких «волшебных» объектов совместно с другими глобальными объектами, т.к. порядок их создания и разрушения не определен. На мой взгляд, тут на лицо проблема архитектуры классов, когда в обертку файлового дескриптора, зачем-то, запихнули path, который не используется 90% времени, а может быть вообще не применим к такому объекту. В этом случае, я бы рекомендовал создать мапу явно, если она нужна, и работать с ней отдельно от обертки, которая вполне себе самодостаточная сущность, на мой взгляд. В общем, такое решение, как «затычка» в конкретной ситуации, может быть и имеет право на жизнь, но паттерном я бы такой подход не стал называть.

Точно, композиция лучше и агрегации и наследования, почти всегда. Вот если бы пул для холодных данных можно было бы задавать из вне, было бы интереснее.

Мне интересно, зачем понадобилось держать все эти файлы в файловой системе? Ведь файлы можно открыть, получить дескриптор, и тут же удалить: файл будет жить до последнего закрытого файлового дескриптора. В Linux ещё есть O_TMPFILE, с помощью которого можно избежать выдумывания имени для файла. При необходимости другие процессы могут получить доступ к таким файлам через procfs (или её аналог). Через неё же файл можно вернуть в файловую систему, если потребуется.
Код приведенный в статье служит лишь для демонстрации базовой идеи. Он не используется в продакшене непосредственно в таком виде. Они не могут дать комментариев к тому, как конкретно они делают, что и для чего используют.

Мне кажется, API можно сильно упростить если вместо ColdData& выставлять наружу std::unique_ptr<ColdData>&.


В частности, пропадут TwoPhaseInit, init_cold_data и reset_cold_data

после 15 лет кодинга на С++, я уже не могу на него смотреть. А динозавры всё еще придумывают новые способы как прострелить себе ногу. Холодные, горячие, бред.
Что думаете о Rust?

Такой же принцип используется в golang'e, только там ещё буфера (структуры) сортируются по частоте обращений — возможно будет полезно для вашего случая, так как там получается даже более чем в 10 раз быстрее.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории