Oleksandr Gavenko -> debian-russian@lists.debian.org @ Wed, 28 Oct 2015 13:17:00 +0200:
>> Понятно что неизменяемость влечет за собой генерацию кучи обьектов и большей >> нагрузки на GC и тут еще нужно смотреть что лучше. OG> Вот пример когда имутабельность приводит к меньшей производительности: OG> http://concurrencyfreaks.blogspot.com/2013/10/immutable-data-structures-are-not-as.html OG> Когда у нас большущее дерево (но влазит в L2, который сейчас несколько OG> мегабайт на десктопе и десятки-сотни на серверах) в случае мутабельности OG> перебалансировка выкинет/добавит 1 ноду, в имутабельном случае LOG(N), это за OG> собою влечет засовывание в кеш LOG(N) новых значений. Заметьте не изменения, а OG> добавления! Т.к. новые ноды будут иметь новые адреса вирт. памяти. С одной стороны, кто бы спорил - серебряной пули нет. С другой - а они про блокировки не забыли? Очевидно, что приведенный аргумент работает для случая однопоточного добавления без параллельных запросов. Если у меня частые добавления, которые можно поместить в такую вот приятную среду, то да, конечно. А вот если надо обеспечить консистентность для параллельных запросов в процессе перебалансировки, сразу становится неочевидно. Применительно к кэшу лишняя блокировка - вещь, чреватая боком. Если говорить о чтении, то там нужна не полноценная блокировка, а атомарное чтение одного указателя. Атомарное в смысле обеспечения консистентности при возможной одновременной записи в него же. Для этого существуют примитивы попроще и побыстрее, чем общая блокировка через мутекс (насколько я понимаю, собственно, мутекс через такой примитив в конце концов и реализуют). Конечно, если у нас и апдейты конкурентные, то блокировки между ними нужны и в иммутабельном случае. Software Transactional Memory (которая, собственно, и потянет упомянутые в статье два барьера вместо одного), по словам измерявших людей, работает заметно медленнее, чем обычные блокировки. Зато надежнее. Таким образом, если у нас основная нагрузка - конкурентные апдейты, то наш выбор - мутабельные структуры, не вопрос. Собственно, измерявший товарищ так и делал, насколько я его понял. А вот если основная нагрузка - конкурентное чтение, а апдейтов сравнительно мало, я бы ставил на иммутабельные. При примерно той же скорости работы будет меньше затрат на дебаггинг. Возможно, учитывая конкурентность, на порядок меньше. А то может получиться, что время, затраченное на поиск одного бага, связанного с конкурентностью в мутабельном случае, может не окупиться за все время работы всех экземпляров программы, ускоренной такой ценой :) Даже если не учитывать экономический эффект от его проявления на боевом сервере у заказчика.