Почему JIT-порядок влияет на производительность?C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Почему JIT-порядок влияет на производительность?

Сообщение Anonymous »

Почему порядок, в котором методы C# в .NET 4.0 компилируются точно в срок, влияет на скорость их выполнения? Например, рассмотрим два эквивалентных метода:

Код: Выделить всё

public static void SingleLineTest()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
int count = 0;
for (uint i = 0; i < 1000000000; ++i) {
count += i % 16 == 0 ? 1 : 0;
}
stopwatch.Stop();
Console.WriteLine("Single-line test --> Count: {0}, Time: {1}", count, stopwatch.ElapsedMilliseconds);
}

public static void MultiLineTest()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
int count = 0;
for (uint i = 0; i < 1000000000; ++i) {
var isMultipleOf16 = i % 16 == 0;
count += isMultipleOf16 ? 1 : 0;
}
stopwatch.Stop();
Console.WriteLine("Multi-line test  --> Count: {0}, Time: {1}", count, stopwatch.ElapsedMilliseconds);
}
Единственное отличие — это введение локальной переменной, которая влияет на генерируемый ассемблерный код и производительность цикла. Почему это так — вопрос сам по себе.

Возможно, еще более странно то, что на x86 (но не на x64) порядок вызова методов имеет около 20% влияние на производительность. Вызовите такие методы...

Код: Выделить всё

static void Main()
{
SingleLineTest();
MultiLineTest();
}
...и SingleLineTest работает быстрее. (Скомпилируйте, используя конфигурацию выпуска x86, убедившись, что параметр «Оптимизировать код» включен, и запустите тест вне VS2010.) Но обратный порядок...

Код: Выделить всё

static void Main()
{
MultiLineTest();
SingleLineTest();
}
...и оба метода занимают одинаковое время (почти, но не совсем, столько же, сколько MultiLineTest раньше). (При запуске этого теста полезно добавить несколько дополнительных вызовов SingleLineTest и MultiLineTest, чтобы получить дополнительные образцы. Сколько и в каком порядке не имеет значения, за исключением того, какой метод вызывается первым.)< /p>

Наконец, чтобы продемонстрировать, что порядок JIT важен, сначала оставьте MultiLineTest, но заставьте сначала JIT-обрабатывать SingleLineTest...

Код: Выделить всё

static void Main()
{
RuntimeHelpers.PrepareMethod(typeof(Program).GetMethod("SingleLineTest").MethodHandle);
MultiLineTest();
SingleLineTest();
}
Теперь SingleLineTest снова работает быстрее.

Если вы отключите «Подавить оптимизацию JIT при загрузка модуля» в VS2010, вы можете поставить точку останова в SingleLineTest и увидеть, что ассемблерный код в цикле один и тот же независимо от порядка JIT; однако ассемблерный код в начале метода различается. Но какое это имеет значение, когда большая часть времени проводится в цикле, вызывает недоумение.

Пример проекта, демонстрирующего такое поведение, находится на github.

Неясно, как такое поведение влияет на реальные приложения. Одна из проблем заключается в том, что это может привести к нестабильности настройки производительности в зависимости от порядка первого вызова методов. Проблемы такого рода было бы трудно обнаружить с помощью профилировщика. После того, как вы обнаружите «горячие точки» и оптимизируете их алгоритмы, будет трудно определить это без долгих догадок и предварительной проверки, возможно ли дополнительное ускорение с помощью методов JITing.

Обновление. См. также запись Microsoft Connect по этой проблеме.

Подробнее здесь: https://stackoverflow.com/questions/104 ... erformance
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»