Я тестировал, как Interlocked.Increment
и lock
ведут себя на архитектуре моего компьютера, потому что я прочитал следующие строки в в этой статье.
Переписанный с помощью Interlocked.Increment, метод должен выполняться быстрее, по крайней мере, на некоторых архитектурах.
Используя следующий код, я убеждаюсь, что в моих проектах стоит проверить блокировки.
var watch = new Stopwatch();
var locker = new object();
int counter = 0;
watch.Start();
for (int i = 0; i < 100000000; i++)
{
lock (locker)
{
counter++;
}
}
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalSeconds);
watch.Reset();
counter = 0;
watch.Start();
for (int i = 0; i < 100000000; i++)
{
Interlocked.Increment(ref counter);
}
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalSeconds);
Я получаю стабильные результаты с приблизительными значениями 2,4 с для блокировки и 1,2 с для блокировки. Однако я был удивлен, обнаружив, что запуск этого кода в режиме выпуска улучшает значение только для Interlocked примерно до 0,7 с , а время блокировки остается прежним. Это почему? Как оптимизируется Interlocked, когда в режиме выпуска блокировки нет?
1 ответ
Вы должны посмотреть на сгенерированный машинный код, чтобы увидеть разницу: Debug + Windows + Disassembly. Версия отладочной сборки вызова Interlocked.Increment ():
00FC27AD call 7327A810
Версия сборки релиза:
025F279D lock inc dword ptr [ebp-24h]
Или, другими словами, оптимизатор джиттера по-настоящему умел в сборке Release и заменил вызов вспомогательной функции на единственную машинную инструкцию.
Оптимизация просто не может быть лучше. Та же оптимизация не может быть применена к вызову метода Monitor.Enter (), который находится под оператором lock , это довольно существенная функция, реализованная в CLR и не может быть встроена. Он делает много вещей помимо Interlocked.Increment (), он позволяет операционной системе перепланировать, когда поток блокируется при попытке получить монитор, и поддерживает очередь ожидающих потоков. Это может быть очень важно для обеспечения хорошего параллелизма, но не в вашем тестовом коде, поскольку блокировка полностью не оспаривается. Остерегайтесь синтетических тестов, которые не соответствуют фактическому использованию.
Похожие вопросы
Новые вопросы
c#
C # (произносится как «резкий») - это высокоуровневый, статически типизированный язык программирования с несколькими парадигмами, разработанный Microsoft. Код C # обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, включая, среди прочего, .NET Framework, .NET Core и Xamarin. Используйте этот тег для вопросов о коде, написанном на C # или в формальной спецификации C #.