Я работал по принципу параллельного программирования без разделения ресурсов. По сути, все мои рабочие потоки имеют неизменные доступные только для чтения копии одного и того же состояния, которое никогда не передается между ними ( даже по ссылке ). Вообще говоря, это сработало очень хорошо.
Теперь кто-то ввел одноэлементный кэш без блокировки ( например, статический словарь ), к которому все потоки обращаются одновременно. Поскольку словарь никогда не изменяется после запуска, блокировки отсутствуют. Проблем с безопасностью потоков не было, но теперь наблюдается снижение производительности.
Вопрос заключается в том, что, поскольку нет блокировок, почему появление этого синглтона приводит к снижению производительности? Что именно происходит под одеялом, что могло бы объяснить это?
Чтобы подтвердить, доступ к этому новому синглтону - единственное изменение, и я могу надежно воссоздать его, просто закомментировав вызов кеша.
источник
Ответы:
Возможно, что неизменное состояние разделяет строку кэша с чем-то изменяемым. В этом случае изменение соседнего изменяемого состояния может привести к принудительной повторной синхронизации этой строки кэша между ядрами, что может снизить производительность.
источник
false sharing
сценарий, который вы описываете. Чтобы изолировать это, мне нужно профилировать L2 Cache. К сожалению, это ссылочные типы, поэтому добавление буферного пространства не будет возможным, если это действительно происходит.Я хотел бы убедиться , что
Equals()
иGetHashCode()
методы объектов , которые используются в качестве ключей в словарь не имеют какие - либо неожиданные без поточных людей побочных эффектов. Профилирование очень помогло бы здесь.Если по какой-либо причине ваши ключи являются строками, то, возможно, у вас есть это: ходят слухи, что строки ведут себя как неизменяемые объекты, но ради определенных оптимизаций они внутренне реализованы изменяемым образом, со всем, что это влечет за собой в отношении многопоточности ,
Я бы попытался передать словарь темам, которые используют его как обычную ссылку, а не как одиночку, чтобы увидеть, связана ли проблема с общностью или с единственностью словаря. (Устранение возможных причин.)
Я бы также попробовал использовать
ConcurrentDictionary
вместо обычногоDictionary
на случай, если его использование даст неожиданные результаты. Есть много вещей, которые можно рассуждать о проблеме, еслиConcurrentDictionary
окажется, что она работает намного лучше или намного хуже, чем ваша обычнаяDictionary
.Если ни один из вышеперечисленных не указывает на проблему, то я бы предположил, что снижение производительности вызвано каким-то странным конфликтом между потоком сбора мусора и остальными вашими потоками, поскольку сборщик мусора пытается выяснить, объекты в вашем словаре должны быть расположены или нет, пока к ним обращаются ваши потоки.
источник