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 (которая,
собственно, и потянет упомянутые в статье два барьера вместо одного), по
словам измерявших людей, работает заметно медленнее, чем обычные
блокировки.  Зато надежнее.  Таким образом, если у нас основная нагрузка
- конкурентные апдейты, то наш выбор - мутабельные структуры, не вопрос.

Собственно, измерявший товарищ так и делал, насколько я его понял.

А вот если основная нагрузка - конкурентное чтение, а апдейтов
сравнительно мало, я бы ставил на иммутабельные.  При примерно той же
скорости работы будет меньше затрат на дебаггинг.  Возможно, учитывая
конкурентность, на порядок меньше.  А то может получиться, что время,
затраченное на поиск одного бага, связанного с конкурентностью в
мутабельном случае, может не окупиться за все время работы всех
экземпляров программы, ускоренной такой ценой :) Даже если не учитывать
экономический эффект от его проявления на боевом сервере у заказчика.

Ответить