166
Теория и практика .NET-бенчмаркинга Андрей Акиньшин, JetBrains Екатеринбург, 02.11.2016 1/85

Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Embed Size (px)

Citation preview

Page 1: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Теория и практика .NET-бенчмаркинга

Андрей Акиньшин, JetBrains

Екатеринбург, 02.11.2016

1/85

Page 2: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 1Теория

2/85 1. Теория

Page 3: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 1.1Почему мы об этом говорим?

3/85 1.1 Теория: Почему мы об этом говорим?

Page 4: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

StackOverflow

Люди любят бенчмаркать

4/85 1.1 Теория: Почему мы об этом говорим?

Page 5: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

StackOverflowТипичный вопрос

5/85 1.1 Теория: Почему мы об этом говорим?

Page 6: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

HabrahabrНекоторые делают выводы и пишут статьи

6/85 1.1 Теория: Почему мы об этом говорим?

Page 7: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Применения бенчмарков

• Performance analysis• Сравнение алгоритмов• Оценка улучшений производительности• Анализ регрессии• . . .

• Научный интерес• Маркетинг• Весёлое времяпрепровождение ,

7/85 1.1 Теория: Почему мы об этом говорим?

Page 8: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Применения бенчмарков

• Performance analysis

• Сравнение алгоритмов• Оценка улучшений производительности• Анализ регрессии• . . .

• Научный интерес• Маркетинг• Весёлое времяпрепровождение ,

7/85 1.1 Теория: Почему мы об этом говорим?

Page 9: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Применения бенчмарков

• Performance analysis• Сравнение алгоритмов

• Оценка улучшений производительности• Анализ регрессии• . . .

• Научный интерес• Маркетинг• Весёлое времяпрепровождение ,

7/85 1.1 Теория: Почему мы об этом говорим?

Page 10: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Применения бенчмарков

• Performance analysis• Сравнение алгоритмов• Оценка улучшений производительности

• Анализ регрессии• . . .

• Научный интерес• Маркетинг• Весёлое времяпрепровождение ,

7/85 1.1 Теория: Почему мы об этом говорим?

Page 11: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Применения бенчмарков

• Performance analysis• Сравнение алгоритмов• Оценка улучшений производительности• Анализ регрессии

• . . .

• Научный интерес• Маркетинг• Весёлое времяпрепровождение ,

7/85 1.1 Теория: Почему мы об этом говорим?

Page 12: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Применения бенчмарков

• Performance analysis• Сравнение алгоритмов• Оценка улучшений производительности• Анализ регрессии• . . .

• Научный интерес• Маркетинг• Весёлое времяпрепровождение ,

7/85 1.1 Теория: Почему мы об этом говорим?

Page 13: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Применения бенчмарков

• Performance analysis• Сравнение алгоритмов• Оценка улучшений производительности• Анализ регрессии• . . .

• Научный интерес

• Маркетинг• Весёлое времяпрепровождение ,

7/85 1.1 Теория: Почему мы об этом говорим?

Page 14: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Применения бенчмарков

• Performance analysis• Сравнение алгоритмов• Оценка улучшений производительности• Анализ регрессии• . . .

• Научный интерес• Маркетинг

• Весёлое времяпрепровождение ,

7/85 1.1 Теория: Почему мы об этом говорим?

Page 15: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Применения бенчмарков

• Performance analysis• Сравнение алгоритмов• Оценка улучшений производительности• Анализ регрессии• . . .

• Научный интерес• Маркетинг• Весёлое времяпрепровождение ,

7/85 1.1 Теория: Почему мы об этом говорим?

Page 16: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 1.2Общая методология

8/85 1.2 Теория: Общая методология

Page 17: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

План performance-работ

1 Поставить задачу2 Выбрать метрики3 Выбрать инструмент4 Провести эксперимент5 Получить результаты6 Выполнить анализ и сделать выводы

Анализ полученных данных — самый важный этап

9/85 1.2 Теория: Общая методология

Page 18: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

План performance-работ

1 Поставить задачу

2 Выбрать метрики3 Выбрать инструмент4 Провести эксперимент5 Получить результаты6 Выполнить анализ и сделать выводы

Анализ полученных данных — самый важный этап

9/85 1.2 Теория: Общая методология

Page 19: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

План performance-работ

1 Поставить задачу2 Выбрать метрики

3 Выбрать инструмент4 Провести эксперимент5 Получить результаты6 Выполнить анализ и сделать выводы

Анализ полученных данных — самый важный этап

9/85 1.2 Теория: Общая методология

Page 20: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

План performance-работ

1 Поставить задачу2 Выбрать метрики3 Выбрать инструмент

4 Провести эксперимент5 Получить результаты6 Выполнить анализ и сделать выводы

Анализ полученных данных — самый важный этап

9/85 1.2 Теория: Общая методология

Page 21: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

План performance-работ

1 Поставить задачу2 Выбрать метрики3 Выбрать инструмент4 Провести эксперимент

5 Получить результаты6 Выполнить анализ и сделать выводы

Анализ полученных данных — самый важный этап

9/85 1.2 Теория: Общая методология

Page 22: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

План performance-работ

1 Поставить задачу2 Выбрать метрики3 Выбрать инструмент4 Провести эксперимент5 Получить результаты

6 Выполнить анализ и сделать выводы

Анализ полученных данных — самый важный этап

9/85 1.2 Теория: Общая методология

Page 23: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

План performance-работ

1 Поставить задачу2 Выбрать метрики3 Выбрать инструмент4 Провести эксперимент5 Получить результаты6 Выполнить анализ и сделать выводы

Анализ полученных данных — самый важный этап

9/85 1.2 Теория: Общая методология

Page 24: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

План performance-работ

1 Поставить задачу2 Выбрать метрики3 Выбрать инструмент4 Провести эксперимент5 Получить результаты6 Выполнить анализ и сделать выводы

Анализ полученных данных — самый важный этап

9/85 1.2 Теория: Общая методология

Page 25: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Виды performance-работ

• Profiling• Monitoring• Performance tests• Benchmarking (micro/macro)• . . .

10/85 1.2 Теория: Общая методология

Page 26: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Виды performance-работ

• Profiling

• Monitoring• Performance tests• Benchmarking (micro/macro)• . . .

10/85 1.2 Теория: Общая методология

Page 27: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Виды performance-работ

• Profiling• Monitoring

• Performance tests• Benchmarking (micro/macro)• . . .

10/85 1.2 Теория: Общая методология

Page 28: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Виды performance-работ

• Profiling• Monitoring• Performance tests

• Benchmarking (micro/macro)• . . .

10/85 1.2 Теория: Общая методология

Page 29: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Виды performance-работ

• Profiling• Monitoring• Performance tests• Benchmarking (micro/macro)

• . . .

10/85 1.2 Теория: Общая методология

Page 30: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Виды performance-работ

• Profiling• Monitoring• Performance tests• Benchmarking (micro/macro)• . . .

10/85 1.2 Теория: Общая методология

Page 31: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Performance spaces

Исходный код

X

Окружение

X

Входные данные

Распределение

11/85 1.2 Теория: Общая методология

Page 32: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Performance spaces

Исходный код

X

Окружение

X

Входные данные

Распределение

11/85 1.2 Теория: Общая методология

Page 33: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Performance spaces

Исходный код

X

Окружение

X

Входные данные

Распределение

11/85 1.2 Теория: Общая методология

Page 34: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Performance spaces

Исходный код

X

Окружение

X

Входные данные

Распределение

11/85 1.2 Теория: Общая методология

Page 35: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Performance spaces

Исходный код

X

Окружение

X

Входные данные

Распределение

11/85 1.2 Теория: Общая методология

Page 36: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Performance spaces

Непонимание проблематики влечёт за собойследующие проблемы:

• Легко обмануть себя, сделать неправильныевыводы, принять вредные бизнес-решения

• Легко пропустить важную конфигурацию,которая испортит жизнь в продакшене

• Легко повестись на кривые бенчмарки иличёрный маркетинг

12/85 1.2 Теория: Общая методология

Page 37: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Performance spaces

Непонимание проблематики влечёт за собойследующие проблемы:

• Легко обмануть себя, сделать неправильныевыводы, принять вредные бизнес-решения

• Легко пропустить важную конфигурацию,которая испортит жизнь в продакшене

• Легко повестись на кривые бенчмарки иличёрный маркетинг

12/85 1.2 Теория: Общая методология

Page 38: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Performance spaces

Непонимание проблематики влечёт за собойследующие проблемы:

• Легко обмануть себя, сделать неправильныевыводы, принять вредные бизнес-решения

• Легко пропустить важную конфигурацию,которая испортит жизнь в продакшене

• Легко повестись на кривые бенчмарки иличёрный маркетинг

12/85 1.2 Теория: Общая методология

Page 39: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Performance spaces

Непонимание проблематики влечёт за собойследующие проблемы:

• Легко обмануть себя, сделать неправильныевыводы, принять вредные бизнес-решения

• Легко пропустить важную конфигурацию,которая испортит жизнь в продакшене

• Легко повестись на кривые бенчмарки иличёрный маркетинг

12/85 1.2 Теория: Общая методология

Page 40: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Окружение

C# compiler старый csc / RoslynCLR CLR2 / CLR4 / CoreCLR / MonoOS Windows / Linux / MacOS / FreeBSDJIT LegacyJIT-x86 / LegacyJIT-x64 / RyuJIT-x64GC MS (разные CLR) / Mono (Boehm/Sgen)Toolchain JIT / NGen / .NET NativeHardware тысячи его. . . . . .

И не забываем про версии, много-много версий

13/85 1.2 Теория: Общая методология

Page 41: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Окружение

C# compiler старый csc / RoslynCLR CLR2 / CLR4 / CoreCLR / MonoOS Windows / Linux / MacOS / FreeBSDJIT LegacyJIT-x86 / LegacyJIT-x64 / RyuJIT-x64GC MS (разные CLR) / Mono (Boehm/Sgen)Toolchain JIT / NGen / .NET NativeHardware тысячи его. . . . . .

И не забываем про версии, много-много версий

13/85 1.2 Теория: Общая методология

Page 42: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Окружение и запуск

Советы по запуску бенчмарков

• Release build• Без дебаггера• Выключите другие приложения• Используйте максимальнуюпроизводительность

14/85 1.2 Теория: Общая методология

Page 43: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Окружение и запуск

Советы по запуску бенчмарков

• Release build

• Без дебаггера• Выключите другие приложения• Используйте максимальнуюпроизводительность

14/85 1.2 Теория: Общая методология

Page 44: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Окружение и запуск

Советы по запуску бенчмарков

• Release build• Без дебаггера

• Выключите другие приложения• Используйте максимальнуюпроизводительность

14/85 1.2 Теория: Общая методология

Page 45: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Окружение и запуск

Советы по запуску бенчмарков

• Release build• Без дебаггера• Выключите другие приложения

• Используйте максимальнуюпроизводительность

14/85 1.2 Теория: Общая методология

Page 46: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Окружение и запуск

Советы по запуску бенчмарков

• Release build• Без дебаггера• Выключите другие приложения• Используйте максимальнуюпроизводительность

14/85 1.2 Теория: Общая методология

Page 47: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Требования к бенчмарку

• Надёжность• Точность• Воспроизводимость• Изолированность• Переносимость• Простота• Честность

15/85 1.2 Теория: Общая методология

Page 48: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Требования к бенчмарку

• Надёжность

• Точность• Воспроизводимость• Изолированность• Переносимость• Простота• Честность

15/85 1.2 Теория: Общая методология

Page 49: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Требования к бенчмарку

• Надёжность• Точность

• Воспроизводимость• Изолированность• Переносимость• Простота• Честность

15/85 1.2 Теория: Общая методология

Page 50: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Требования к бенчмарку

• Надёжность• Точность• Воспроизводимость

• Изолированность• Переносимость• Простота• Честность

15/85 1.2 Теория: Общая методология

Page 51: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Требования к бенчмарку

• Надёжность• Точность• Воспроизводимость• Изолированность

• Переносимость• Простота• Честность

15/85 1.2 Теория: Общая методология

Page 52: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Требования к бенчмарку

• Надёжность• Точность• Воспроизводимость• Изолированность• Переносимость

• Простота• Честность

15/85 1.2 Теория: Общая методология

Page 53: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Требования к бенчмарку

• Надёжность• Точность• Воспроизводимость• Изолированность• Переносимость• Простота

• Честность

15/85 1.2 Теория: Общая методология

Page 54: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Требования к бенчмарку

• Надёжность• Точность• Воспроизводимость• Изолированность• Переносимость• Простота• Честность

15/85 1.2 Теория: Общая методология

Page 55: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

BenchmarkDotNet

16/85 1.2 Теория: Общая методология

Page 56: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 1.3Таймеры

17/85 1.3 Теория: Таймеры

Page 57: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

DateTime vs Stopwatch

var start = DateTime.Now;Foo();var finish = DateTime.Now;var time = (finish - start).TotalMilliseconds;

vs

var sw = Stopwatch.StartNew();Foo();sw.Stop();var time = sw.ElapsedMilliseconds;

18/85 1.3 Теория: Таймеры

Page 58: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Характеристики таймеров

• Монотонностьзамеры должны неуменьшаться

• Resolutionминимальное положительное время междузамерами

• Latencyвремя на получение замера

19/85 1.3 Теория: Таймеры

Page 59: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Характеристики таймеров

• Монотонностьзамеры должны неуменьшаться

• Resolutionминимальное положительное время междузамерами

• Latencyвремя на получение замера

19/85 1.3 Теория: Таймеры

Page 60: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Характеристики таймеров

• Монотонностьзамеры должны неуменьшаться

• Resolutionминимальное положительное время междузамерами

• Latencyвремя на получение замера

19/85 1.3 Теория: Таймеры

Page 61: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Характеристики таймеров

• Монотонностьзамеры должны неуменьшаться

• Resolutionминимальное положительное время междузамерами

• Latencyвремя на получение замера

19/85 1.3 Теория: Таймеры

Page 62: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

DateTime.UtcNow

OS ImplementationWindows GetSystemTimeAsFileTimeLinux gettimeofday

OS Runtime Time∗

Latency Windows Full/Core ≈7–8nsLatency Windows Mono ≈30–31nsResolution Windows Any ≈0.5..15.625msLatency Linux Mono ≈26–30nsResolution Linux Mono ≈1µs

∗Intel i7-4702MQ CPU 2.20GHz

См. также: http://aakinshin.net/en/blog/dotnet/datetime/

20/85 1.3 Теория: Таймеры

Page 63: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

DateTime.UtcNow

OS ImplementationWindows GetSystemTimeAsFileTimeLinux gettimeofday

OS Runtime Time∗

Latency Windows Full/Core ≈7–8nsLatency Windows Mono ≈30–31nsResolution Windows Any ≈0.5..15.625msLatency Linux Mono ≈26–30nsResolution Linux Mono ≈1µs

∗Intel i7-4702MQ CPU 2.20GHz

См. также: http://aakinshin.net/en/blog/dotnet/datetime/

20/85 1.3 Теория: Таймеры

Page 64: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

DateTime.UtcNow

OS ImplementationWindows GetSystemTimeAsFileTimeLinux gettimeofday

OS Runtime Time∗

Latency Windows Full/Core ≈7–8nsLatency Windows Mono ≈30–31nsResolution Windows Any ≈0.5..15.625ms

Latency Linux Mono ≈26–30nsResolution Linux Mono ≈1µs

∗Intel i7-4702MQ CPU 2.20GHz

См. также: http://aakinshin.net/en/blog/dotnet/datetime/

20/85 1.3 Теория: Таймеры

Page 65: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

DateTime.UtcNow

OS ImplementationWindows GetSystemTimeAsFileTimeLinux gettimeofday

OS Runtime Time∗

Latency Windows Full/Core ≈7–8nsLatency Windows Mono ≈30–31nsResolution Windows Any ≈0.5..15.625msLatency Linux Mono ≈26–30nsResolution Linux Mono ≈1µs

∗Intel i7-4702MQ CPU 2.20GHz

См. также: http://aakinshin.net/en/blog/dotnet/datetime/

20/85 1.3 Теория: Таймеры

Page 66: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

DateTime.UtcNow

OS ImplementationWindows GetSystemTimeAsFileTimeLinux gettimeofday

OS Runtime Time∗

Latency Windows Full/Core ≈7–8nsLatency Windows Mono ≈30–31nsResolution Windows Any ≈0.5..15.625msLatency Linux Mono ≈26–30nsResolution Linux Mono ≈1µs

∗Intel i7-4702MQ CPU 2.20GHz

См. также: http://aakinshin.net/en/blog/dotnet/datetime/20/85 1.3 Теория: Таймеры

Page 67: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Stopwatch.GetTimestamp()

Hardware timers

• NA• TSC (Variant / Constant / Invariant)• ACPI PM (Freq = 3.579545 MHz)• HPET (Freq = 14.31818 MHz)

Implementation

• Windows: QueryPerformanceCounter• Linux: clock_gettime /mach_absolute_time / gettimeofday

21/85 1.3 Теория: Таймеры

Page 68: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Stopwatch.GetTimestamp()

Hardware timers

• NA• TSC (Variant / Constant / Invariant)• ACPI PM (Freq = 3.579545 MHz)• HPET (Freq = 14.31818 MHz)

Implementation

• Windows: QueryPerformanceCounter• Linux: clock_gettime /mach_absolute_time / gettimeofday

21/85 1.3 Теория: Таймеры

Page 69: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Stopwatch.GetTimestamp()

Hardware timers

• NA• TSC (Variant / Constant / Invariant)• ACPI PM (Freq = 3.579545 MHz)• HPET (Freq = 14.31818 MHz)

Implementation

• Windows: QueryPerformanceCounter• Linux: clock_gettime /mach_absolute_time / gettimeofday

21/85 1.3 Теория: Таймеры

Page 70: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Stopwatch.GetTimestamp()

Runtime OS Timer 1 tick Latency ResolutionFull Win TSC 300-400ns 15-18ns 300-400nsFull Win HPET 69.8ns 500-800ns ≈LatencyFull Win NA 100ns 7-10ns 0.5-55msMono Win TSC 100ns 35-45ns 300-400nsMono Win HPET 100ns 500-800ns ≈LatencyMono Win NA 100ns 30-40ns 0.5-55msCore Linux TSC 1ns 30-35ns ≈LatencyCore Linux HPET/ACPI 1ns 500-800ns ≈LatencyMono Linux TSC 100ns 20-25ns 100nsMono Linux HPET/ACPI 100ns 500-800ns ≈Latency

Intel i7-4702MQ CPU 2.20GHz

См. также: http://aakinshin.net/en/blog/dotnet/stopwatch/

22/85 1.3 Теория: Таймеры

Page 71: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Важно помнить про таймеры

• Важно понимать значения Latency и Resolution

• 1 tick ≠ Resolution

• Время может идти назад /

• Два последовательных замера могут быть равны

• Два последовательных замера могут различаться намиллисекунды

23/85 1.3 Теория: Таймеры

Page 72: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Важно помнить про таймеры

• Важно понимать значения Latency и Resolution

• 1 tick ≠ Resolution

• Время может идти назад /

• Два последовательных замера могут быть равны

• Два последовательных замера могут различаться намиллисекунды

23/85 1.3 Теория: Таймеры

Page 73: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Важно помнить про таймеры

• Важно понимать значения Latency и Resolution

• 1 tick ≠ Resolution

• Время может идти назад /

• Два последовательных замера могут быть равны

• Два последовательных замера могут различаться намиллисекунды

23/85 1.3 Теория: Таймеры

Page 74: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Важно помнить про таймеры

• Важно понимать значения Latency и Resolution

• 1 tick ≠ Resolution

• Время может идти назад /

• Два последовательных замера могут быть равны

• Два последовательных замера могут различаться намиллисекунды

23/85 1.3 Теория: Таймеры

Page 75: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Важно помнить про таймеры

• Важно понимать значения Latency и Resolution

• 1 tick ≠ Resolution

• Время может идти назад /

• Два последовательных замера могут быть равны

• Два последовательных замера могут различаться намиллисекунды

23/85 1.3 Теория: Таймеры

Page 76: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Важно помнить про таймеры

• Важно понимать значения Latency и Resolution

• 1 tick ≠ Resolution

• Время может идти назад /

• Два последовательных замера могут быть равны

• Два последовательных замера могут различаться намиллисекунды

23/85 1.3 Теория: Таймеры

Page 77: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 1.4Количество итераций

24/85 1.4 Теория: Количество итераций

Page 78: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Микробенчмаркинг

Плохой бенчмарк

// Resolution(Stopwatch) = 466 ns// Latency(Stopwatch) = 18 nsvar sw = Stopwatch.StartNew();Foo(); // 100 nssw.Stop();WriteLine(sw.ElapsedMilliseconds);

Небольшое улучшение

var sw = Stopwatch.StartNew();for (int i = 0; i < N; i++) // (N * 100 + eps) ns

Foo();sw.Stop();var total = sw.ElapsedTicks / Stopwatch.Frequency;WriteLine(total / N);

25/85 1.4 Теория: Количество итераций

Page 79: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Микробенчмаркинг

Плохой бенчмарк

// Resolution(Stopwatch) = 466 ns// Latency(Stopwatch) = 18 nsvar sw = Stopwatch.StartNew();Foo(); // 100 nssw.Stop();WriteLine(sw.ElapsedMilliseconds);

Небольшое улучшение

var sw = Stopwatch.StartNew();for (int i = 0; i < N; i++) // (N * 100 + eps) ns

Foo();sw.Stop();var total = sw.ElapsedTicks / Stopwatch.Frequency;WriteLine(total / N);

25/85 1.4 Теория: Количество итераций

Page 80: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Прогрев

Запустим бенчмарк несколько раз:int[] x = new int[128 * 1024 * 1024];for (int iter = 0; iter < 5; iter++){

var sw = Stopwatch.StartNew();for (int i = 0; i < x.Length; i += 16)

x[i]++;sw.Stop();Console.WriteLine(sw.ElapsedMilliseconds);

}

Результат:17681626262

26/85 1.4 Теория: Количество итераций

Page 81: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Прогрев

Запустим бенчмарк несколько раз:int[] x = new int[128 * 1024 * 1024];for (int iter = 0; iter < 5; iter++){

var sw = Stopwatch.StartNew();for (int i = 0; i < x.Length; i += 16)

x[i]++;sw.Stop();Console.WriteLine(sw.ElapsedMilliseconds);

}

Результат:17681626262

26/85 1.4 Теория: Количество итераций

Page 82: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Несколько запусков метода

Run 01 : 529.8674 ns/opRun 02 : 532.7541 ns/opRun 03 : 558.7448 ns/opRun 04 : 555.6647 ns/opRun 05 : 539.6401 ns/opRun 06 : 539.3494 ns/opRun 07 : 564.3222 ns/opRun 08 : 551.9544 ns/opRun 09 : 550.1608 ns/opRun 10 : 533.0634 ns/op

27/85 1.4 Теория: Количество итераций

Page 83: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Несколько запусков бенчмарка

28/85 1.4 Теория: Количество итераций

Page 84: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Простой случайЦентральная предельная теорема

спешит на помощь!

29/85 1.4 Теория: Количество итераций

Page 85: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Но есть и сложные случаи

30/85 1.4 Теория: Количество итераций

Page 86: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 1.5Различные сложности

31/85 1.5 Теория: Различные сложности

Page 87: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Накладные расходы

var sw = Stopwatch.StartNew();int x = 0;for (int i = 0; i < N; i++) // overhead

x++; // target operationsw.Stop();

32/85 1.5 Теория: Различные сложности

Page 88: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Изоляция бенчмарков

Плохой бенчмарк

var sw1 = Stopwatch.StartNew();Foo();sw1.Stop();var sw2 = Stopwatch.StartNew();Bar();sw2.Stop();

Вспомним про:• Interface method dispatch• Garbage collector and autotuning• Jitting

33/85 1.5 Теория: Различные сложности

Page 89: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Изоляция бенчмарков

Плохой бенчмарк

var sw1 = Stopwatch.StartNew();Foo();sw1.Stop();var sw2 = Stopwatch.StartNew();Bar();sw2.Stop();

Вспомним про:• Interface method dispatch• Garbage collector and autotuning• Jitting

33/85 1.5 Теория: Различные сложности

Page 90: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Борьба с оптимизациями

• Dead code elimination• Inlining• Constant folding• Instruction Level Parallelism• Branch prediction• . . .

34/85 1.5 Теория: Различные сложности

Page 91: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Борьба с оптимизациями

• Dead code elimination

• Inlining• Constant folding• Instruction Level Parallelism• Branch prediction• . . .

34/85 1.5 Теория: Различные сложности

Page 92: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Борьба с оптимизациями

• Dead code elimination• Inlining

• Constant folding• Instruction Level Parallelism• Branch prediction• . . .

34/85 1.5 Теория: Различные сложности

Page 93: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Борьба с оптимизациями

• Dead code elimination• Inlining• Constant folding

• Instruction Level Parallelism• Branch prediction• . . .

34/85 1.5 Теория: Различные сложности

Page 94: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Борьба с оптимизациями

• Dead code elimination• Inlining• Constant folding• Instruction Level Parallelism

• Branch prediction• . . .

34/85 1.5 Теория: Различные сложности

Page 95: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Борьба с оптимизациями

• Dead code elimination• Inlining• Constant folding• Instruction Level Parallelism• Branch prediction

• . . .

34/85 1.5 Теория: Различные сложности

Page 96: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Борьба с оптимизациями

• Dead code elimination• Inlining• Constant folding• Instruction Level Parallelism• Branch prediction• . . .

34/85 1.5 Теория: Различные сложности

Page 97: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Доступ к памятиEvent Latency Scaled1 CPU cycle 0.3 ns 1 sLevel 1 cache access 0.9 ns 3 sLevel 2 cache access 2.8 ns 9 sLevel 3 cache access 12.9 ns 43 sMain memory access 120 ns 6 minSolid-state disk I/O 50-150 µs 2-6 daysRotational disk I/O 1-10 ms 1-12 monthsInternet: SF to NYC 40 ms 4 yearsInternet: SF to UK 81 ms 8 yearsInternet: SF to Australia 183 ms 19 yearsOS virtualization reboot 4 s 423 yearsSCSI command time-out 30 s 3000 yearsHardware virtualization reboot 40 s 4000 yearsPhysical system reboot 5 m 32 millenia

© Systems Performance: Enterprise and the Cloud

35/85 1.5 Теория: Различные сложности

Page 98: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Processor affinity

36/85 1.5 Теория: Различные сложности

Page 99: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

True sharing

37/85 1.5 Теория: Различные сложности

Page 100: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

False sharing

38/85 1.5 Теория: Различные сложности

Page 101: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

False sharing в действииprivate static int[] x = new int[1024];

private void Inc(int p){

for (int i = 0; i < 10000001; i++)x[p]++;

}

private void Run(int step){

var sw = Stopwatch.StartNew();Task.WaitAll(

Task.Factory.StartNew(() => Inc(0 * step)),Task.Factory.StartNew(() => Inc(1 * step)),Task.Factory.StartNew(() => Inc(2 * step)),Task.Factory.StartNew(() => Inc(3 * step)));

Console.WriteLine(sw.ElapsedMilliseconds);}

Run(1) Run(256)≈400ms ≈150ms

39/85 1.5 Теория: Различные сложности

Page 102: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

False sharing в действииprivate static int[] x = new int[1024];

private void Inc(int p){

for (int i = 0; i < 10000001; i++)x[p]++;

}

private void Run(int step){

var sw = Stopwatch.StartNew();Task.WaitAll(

Task.Factory.StartNew(() => Inc(0 * step)),Task.Factory.StartNew(() => Inc(1 * step)),Task.Factory.StartNew(() => Inc(2 * step)),Task.Factory.StartNew(() => Inc(3 * step)));

Console.WriteLine(sw.ElapsedMilliseconds);}

Run(1) Run(256)≈400ms ≈150ms

39/85 1.5 Теория: Различные сложности

Page 103: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Бенчмаркинг — это сложно

Anon et al., “A Measure of Transaction Processing Power”

There are lies, damn lies and then there are performancemeasures.

40/85 1.5 Теория: Различные сложности

Page 104: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 2Практика

41/85 2. Практика

Page 105: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 2.1Сложности нанобенчмаркинга

42/85 2.1 Практика: Сложности нанобенчмаркинга

Page 106: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Задача

Какой из методов работает быстрее?

[MethodImpl(MethodImplOptions.NoInlining)]public void Empty0() {}

[MethodImpl(MethodImplOptions.NoInlining)]public void Empty1() {}

[MethodImpl(MethodImplOptions.NoInlining)]public void Empty2() {}

[MethodImpl(MethodImplOptions.NoInlining)]public void Empty3() {}

43/85 2.1 Практика: Сложности нанобенчмаркинга

Page 107: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Попытка решенияДавайте забенчмаркаем!

private void MeasureX() // X = 0, 1, 2, 3{

for (int i = 0; i < Rep; i++){

var sw = Stopwatch.StartNew();for (int j = 0; j < N; j++)

EmptyX(); // X = 0, 1, 2, 3sw.Stop();Write(sw.ElapsedMilliseconds + " ");

}}

Empty0: 242 253 245 253 242 244 245 255 245 245 // SlowEmpty1: 224 228 229 224 223 224 227 222 228 222 // FastEmpty2: 229 222 226 222 224 226 227 229 225 230 // FastEmpty3: 241 240 237 244 242 241 238 245 239 239 // Slow

Intel Core i7 Haswell, RyuJIT-x64

44/85 2.1 Практика: Сложности нанобенчмаркинга

Page 108: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Попытка решенияДавайте забенчмаркаем!

private void MeasureX() // X = 0, 1, 2, 3{

for (int i = 0; i < Rep; i++){

var sw = Stopwatch.StartNew();for (int j = 0; j < N; j++)

EmptyX(); // X = 0, 1, 2, 3sw.Stop();Write(sw.ElapsedMilliseconds + " ");

}}

Empty0: 242 253 245 253 242 244 245 255 245 245 // SlowEmpty1: 224 228 229 224 223 224 227 222 228 222 // FastEmpty2: 229 222 226 222 224 226 227 229 225 230 // FastEmpty3: 241 240 237 244 242 241 238 245 239 239 // Slow

Intel Core i7 Haswell, RyuJIT-x6444/85 2.1 Практика: Сложности нанобенчмаркинга

Page 109: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Обратимся к классике

Рекомендуемая литература:Agner Fog,“The microarchitecture of Intel, AMD and VIA CPUs.An optimization guide for assembly programmers andcompiler makers.”

3.8 Branch prediction in Intel Haswell, Broadwell and Skylake

Pattern recognition for indirect jumps and calls.Indirect jumps and indirect calls are predicted well.

45/85 2.1 Практика: Сложности нанобенчмаркинга

Page 110: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Обратимся к классике

Рекомендуемая литература:Agner Fog,“The microarchitecture of Intel, AMD and VIA CPUs.An optimization guide for assembly programmers andcompiler makers.”

3.8 Branch prediction in Intel Haswell, Broadwell and Skylake

Pattern recognition for indirect jumps and calls.Indirect jumps and indirect calls are predicted well.

45/85 2.1 Практика: Сложности нанобенчмаркинга

Page 111: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Воспользуемся верным инструментом

46/85 2.1 Практика: Сложности нанобенчмаркинга

Page 112: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Старая добрая раскрутка циклаvar sw = Stopwatch.StartNew();for (int j = 0; j < N; j++){

Empty0();Empty0();Empty0();Empty0();Empty0();Empty0();Empty0();Empty0();Empty0();Empty0();Empty0();Empty0();Empty0();Empty0();Empty0();Empty0();

}sw.Stop();

47/85 2.1 Практика: Сложности нанобенчмаркинга

Page 113: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Раскрутим наш цикл

Есть ли статистически значимая разница между замерами?48/85 2.1 Практика: Сложности нанобенчмаркинга

Page 114: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Работа над ошибками

• Выключайте приложения во времябенчмаркинга!Результаты без запущенной VisualStudio:

• Не пытайтесь оценивать статистическуюзначимость на глаз.

49/85 2.1 Практика: Сложности нанобенчмаркинга

Page 115: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 2.2Работаем с памятью

50/85 2.2 Практика: Работаем с памятью

Page 116: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Сумма элементов массива

const int N = 1024;int[,] a = new int[N, N];

[Benchmark]public double SumIj(){

var sum = 0;for (int i = 0; i < N; i++)

for (int j = 0; j < N; j++)sum += a[i, j];

return sum;}

[Benchmark]public double SumJi(){

var sum = 0;for (int j = 0; j < N; j++)

for (int i = 0; i < N; i++)sum += a[i, j];

return sum;}

SumIj SumJiLegacyJIT-x86 1 попугай 3.5 попугая

51/85 2.2 Практика: Работаем с памятью

Page 117: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Сумма элементов массива

const int N = 1024;int[,] a = new int[N, N];

[Benchmark]public double SumIj(){

var sum = 0;for (int i = 0; i < N; i++)

for (int j = 0; j < N; j++)sum += a[i, j];

return sum;}

[Benchmark]public double SumJi(){

var sum = 0;for (int j = 0; j < N; j++)

for (int i = 0; i < N; i++)sum += a[i, j];

return sum;}

SumIj SumJiLegacyJIT-x86 1 попугай 3.5 попугая

51/85 2.2 Практика: Работаем с памятью

Page 118: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 2.3Работаем с условными

переходами

52/85 2.3 Практика: Работаем с условными переходами

Page 119: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Branch predictionconst int N = 32767;int[] sorted, unsorted; // random numbers [0..255]private static int Sum(int[] data){

int sum = 0;for (int i = 0; i < N; i++)

if (data[i] >= 128)sum += data[i];

return sum;}[Benchmark]public int Sorted(){

return Sum(sorted);}

[Benchmark]public int Unsorted(){

return Sum(unsorted);}

Sorted UnsortedLegacyJIT-x86 1 попугай 7.4 попугая

53/85 2.3 Практика: Работаем с условными переходами

Page 120: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Branch predictionconst int N = 32767;int[] sorted, unsorted; // random numbers [0..255]private static int Sum(int[] data){

int sum = 0;for (int i = 0; i < N; i++)

if (data[i] >= 128)sum += data[i];

return sum;}[Benchmark]public int Sorted(){

return Sum(sorted);}

[Benchmark]public int Unsorted(){

return Sum(unsorted);}

Sorted UnsortedLegacyJIT-x86 1 попугай 7.4 попугая

53/85 2.3 Практика: Работаем с условными переходами

Page 121: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 2.4Interface method dispatch

54/85 2.4 Практика: Interface method dispatch

Page 122: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Интерфейсы

private interface IFoo {double Inc(double x);

}private class Foo1 : IFoo {

public double Inc(double x) =>x + 1;

}private class Foo2 : IFoo {

public double Inc(double x) =>x + 1;

}private double Run(IFoo foo) {

double sum = 0;for (int i = 0; i < 1001; i++)

sum += foo.Inc(0);return sum;

}

[Benchmark]public double Run11() {

var bar1 = new Foo1();var bar2 = new Foo1();return Run(bar1) + Run(bar2);

}

[Benchmark]public double Run12() {

var bar1 = new Foo1();var bar2 = new Foo2();return Run(bar1) + Run(bar2);

}

Run11 Run12LegacyJIT-x64 1 попугай 1.25 попугая

55/85 2.4 Практика: Interface method dispatch

Page 123: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Интерфейсы

private interface IFoo {double Inc(double x);

}private class Foo1 : IFoo {

public double Inc(double x) =>x + 1;

}private class Foo2 : IFoo {

public double Inc(double x) =>x + 1;

}private double Run(IFoo foo) {

double sum = 0;for (int i = 0; i < 1001; i++)

sum += foo.Inc(0);return sum;

}

[Benchmark]public double Run11() {

var bar1 = new Foo1();var bar2 = new Foo1();return Run(bar1) + Run(bar2);

}

[Benchmark]public double Run12() {

var bar1 = new Foo1();var bar2 = new Foo2();return Run(bar1) + Run(bar2);

}

Run11 Run12LegacyJIT-x64 1 попугай 1.25 попугая

55/85 2.4 Практика: Interface method dispatch

Page 124: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Интерфейсы

private interface IFoo {double Inc(double x);

}private class Foo1 : IFoo {

public double Inc(double x) =>x + 1;

}private class Foo2 : IFoo {

public double Inc(double x) =>x + 1;

}private double Run(IFoo foo) {

double sum = 0;for (int i = 0; i < 1001; i++)

sum += foo.Inc(0);return sum;

}

[Benchmark]public double Run11() {

var bar1 = new Foo1();var bar2 = new Foo1();return Run(bar1) + Run(bar2);

}

[Benchmark]public double Run12() {

var bar1 = new Foo1();var bar2 = new Foo2();return Run(bar1) + Run(bar2);

}

Run11 Run12LegacyJIT-x64 1 попугай 1.25 попугая

55/85 2.4 Практика: Interface method dispatch

Page 125: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 2.5Inlining

56/85 2.5 Практика: Inlining

Page 126: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Исходники .NET Framework

57/85 2.5 Практика: Inlining

Page 127: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Inlining — это сложно// mscorlib/system/decimal.cs,158// Constructs a Decimal from an integer value.public Decimal(int value) {

// JIT today can't inline methods that contains "starg"// opcode. For more details, see DevDiv Bugs 81184:// x86 JIT CQ: Removing the inline striction of "starg".int value_copy = value;if (value_copy >= 0) {

flags = 0;}else {

flags = SignMask;value_copy = -value_copy;

}lo = value_copy;mid = 0;hi = 0;

}

58/85 2.5 Практика: Inlining

Page 128: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Проведём опыт

[Benchmark]int Calc() => WithoutStarg(0x11) + WithStarg(0x12);

int WithoutStarg(int value) => value;

int WithStarg(int value){

if (value < 0)value = -value;

return value;}

LegacyJIT-x86 LegacyJIT-x64 RyuJIT-x641 попугай 0 попугаев 1 попугай

59/85 2.5 Практика: Inlining

Page 129: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Проведём опыт

[Benchmark]int Calc() => WithoutStarg(0x11) + WithStarg(0x12);

int WithoutStarg(int value) => value;

int WithStarg(int value){

if (value < 0)value = -value;

return value;}

LegacyJIT-x86 LegacyJIT-x64 RyuJIT-x641 попугай 0 попугаев 1 попугай

59/85 2.5 Практика: Inlining

Page 130: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Как же так?

LegacyJIT-x64

; LegacyJIT-x64mov ecx,23hret

RyuJIT-x64

// Inline expansion aborted due to opcode// [06] OP_starg.s in method// Program:WithStarg(int):int:this

60/85 2.5 Практика: Inlining

Page 131: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Как же так?

LegacyJIT-x64

; LegacyJIT-x64mov ecx,23hret

RyuJIT-x64

// Inline expansion aborted due to opcode// [06] OP_starg.s in method// Program:WithStarg(int):int:this

60/85 2.5 Практика: Inlining

Page 132: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Ещё одна загадка

61/85 2.5 Практика: Inlining

Page 133: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Отгадка

62/85 2.5 Практика: Inlining

Page 134: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 2.6Readonly fields

63/85 2.6 Практика: Readonly fields

Page 135: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Почитаем блог Джона Скита

64/85 2.6 Практика: Readonly fields

Page 136: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Проведём ещё один опытpublic struct Int256{

private readonly long bits0, bits1, bits2, bits3;public Int256(long bits0, long bits1, long bits2, long bits3){

this.bits0 = bits0; this.bits1 = bits1;this.bits2 = bits2; this.bits3 = bits3;

}public long Bits0 => bits0; public long Bits1 => bits1;public long Bits2 => bits2; public long Bits3 => bits3;

}private Int256 a = new Int256(1L, 5L, 10L, 100L);private readonly Int256 b = new Int256(1L, 5L, 10L, 100L);[Benchmark] public long GetValue() =>

a.Bits0 + a.Bits1 + a.Bits2 + a.Bits3;[Benchmark] public long GetReadOnlyValue() =>

b.Bits0 + b.Bits1 + b.Bits2 + b.Bits3;

LegacyJIT-x64 RyuJIT-x64GetValue 1 попугай 1 попугайGetReadOnlyValue 6.2 попугая 7.6 попугая

65/85 2.6 Практика: Readonly fields

Page 137: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Проведём ещё один опытpublic struct Int256{

private readonly long bits0, bits1, bits2, bits3;public Int256(long bits0, long bits1, long bits2, long bits3){

this.bits0 = bits0; this.bits1 = bits1;this.bits2 = bits2; this.bits3 = bits3;

}public long Bits0 => bits0; public long Bits1 => bits1;public long Bits2 => bits2; public long Bits3 => bits3;

}private Int256 a = new Int256(1L, 5L, 10L, 100L);private readonly Int256 b = new Int256(1L, 5L, 10L, 100L);[Benchmark] public long GetValue() =>

a.Bits0 + a.Bits1 + a.Bits2 + a.Bits3;[Benchmark] public long GetReadOnlyValue() =>

b.Bits0 + b.Bits1 + b.Bits2 + b.Bits3;

LegacyJIT-x64 RyuJIT-x64GetValue 1 попугай 1 попугайGetReadOnlyValue 6.2 попугая 7.6 попугая

65/85 2.6 Практика: Readonly fields

Page 138: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Как же так?

; GetValueIL_0000: ldarg.0IL_0001: ldflda valuetype Program::aIL_0006: call instance int64 Int256::get_Bits0()

; GetReadOnlyValueIL_0000: ldarg.0IL_0001: ldfld valuetype Program::bIL_0006: stloc.0IL_0007: ldloca.s 0IL_0009: call instance int64 Int256::get_Bits0()

См. также: Jon Skeet, Micro-optimization: the surprising inefficiency of readonly fields

66/85 2.6 Практика: Readonly fields

Page 139: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 2.7SIMD

67/85 2.7 Практика: SIMD

Page 140: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Поговорим про SIMDprivate struct MyVector{

public float X, Y, Z, W;public MyVector(float x, float y, float z, float w){

X = x; Y = y; Z = z; W = w;}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static MyVector operator *(MyVector left, MyVector right){

return new MyVector(left.X * right.X, left.Y * right.Y,left.Z * right.Z, left.W * right.W);

}}private Vector4 vector1, vector2, vector3;private MyVector myVector1, myVector2, myVector3;[Benchmark] public void MyMul() => myVector3 = myVector1 * myVector2;[Benchmark] public void BclMul() => vector3 = vector1 * vector2;

LegacyJIT-x64 RyuJIT-x64MyMul 34 попугая 5 попугаевBclMul 34 попугая 1 попугай

68/85 2.7 Практика: SIMD

Page 141: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Поговорим про SIMDprivate struct MyVector{

public float X, Y, Z, W;public MyVector(float x, float y, float z, float w){

X = x; Y = y; Z = z; W = w;}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static MyVector operator *(MyVector left, MyVector right){

return new MyVector(left.X * right.X, left.Y * right.Y,left.Z * right.Z, left.W * right.W);

}}private Vector4 vector1, vector2, vector3;private MyVector myVector1, myVector2, myVector3;[Benchmark] public void MyMul() => myVector3 = myVector1 * myVector2;[Benchmark] public void BclMul() => vector3 = vector1 * vector2;

LegacyJIT-x64 RyuJIT-x64MyMul 34 попугая 5 попугаевBclMul 34 попугая 1 попугай

68/85 2.7 Практика: SIMD

Page 142: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Как же так?

; LegacyJIT-x64

; MyMul, BclMul; ...movss xmm3,dword ptr [rsp+40h]mulss xmm3,dword ptr [rsp+30h]movss xmm2,dword ptr [rsp+44h]mulss xmm2,dword ptr [rsp+34h]movss xmm1,dword ptr [rsp+48h]mulss xmm1,dword ptr [rsp+38h]movss xmm0,dword ptr [rsp+4Ch]mulss xmm0,dword ptr [rsp+3Ch]xor eax,eaxmov qword ptr [rsp],raxmov qword ptr [rsp+8],raxlea rax,[rsp]movss dword ptr [rax],xmm3movss dword ptr [rax+4],xmm2movss dword ptr [rax+8],xmm1movss dword ptr [rax+0Ch],xmm0; ...

; RyuJIT-x64

; MyMul; ...vmulss xmm0,xmm0,xmm4vmulss xmm1,xmm1,xmm5vmulss xmm2,xmm2,xmm6vmulss xmm3,xmm3,xmm7; ...

; BclMulvmovupd xmm0,xmmword ptr [rcx+8]vmovupd xmm1,xmmword ptr [rcx+18h]vmulps xmm0,xmm0,xmm1vmovupd xmmword ptr [rcx+28h],xmm0

69/85 2.7 Практика: SIMD

Page 143: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 2.8Constant folding

70/85 2.8 Практика: Constant folding

Page 144: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Интересный issue на dotnet/coreclr

71/85 2.8 Практика: Constant folding

Page 145: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Учимся извлекать корни

double Sqrt13() =>Math.Sqrt(1) + Math.Sqrt(2) + Math.Sqrt(3) + /* ... */+ Math.Sqrt(13);

VS

double Sqrt14() =>Math.Sqrt(1) + Math.Sqrt(2) + Math.Sqrt(3) + /* ... */+ Math.Sqrt(13) + Math.Sqrt(14);

RyuJIT-x64Sqrt13 ≈ 93nsSqrt14 0 ns

72/85 2.8 Практика: Constant folding

Page 146: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Учимся извлекать корни

double Sqrt13() =>Math.Sqrt(1) + Math.Sqrt(2) + Math.Sqrt(3) + /* ... */+ Math.Sqrt(13);

VS

double Sqrt14() =>Math.Sqrt(1) + Math.Sqrt(2) + Math.Sqrt(3) + /* ... */+ Math.Sqrt(13) + Math.Sqrt(14);

RyuJIT-x64Sqrt13 ≈ 93nsSqrt14 0 ns

72/85 2.8 Практика: Constant folding

Page 147: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Как же так?

RyuJIT-x64, Sqrt13vsqrtsd xmm0,xmm0,mmword ptr [7FF94F9E4D28h]vsqrtsd xmm1,xmm0,mmword ptr [7FF94F9E4D30h]vaddsd xmm0,xmm0,xmm1vsqrtsd xmm1,xmm0,mmword ptr [7FF94F9E4D38h]vaddsd xmm0,xmm0,xmm1vsqrtsd xmm1,xmm0,mmword ptr [7FF94F9E4D40h]vaddsd xmm0,xmm0,xmm1vsqrtsd xmm1,xmm0,mmword ptr [7FF94F9E4D48h]vaddsd xmm0,xmm0,xmm1vsqrtsd xmm1,xmm0,mmword ptr [7FF94F9E4D50h]vaddsd xmm0,xmm0,xmm1vsqrtsd xmm1,xmm0,mmword ptr [7FF94F9E4D58h]vaddsd xmm0,xmm0,xmm1vsqrtsd xmm1,xmm0,mmword ptr [7FF94F9E4D60h]vaddsd xmm0,xmm0,xmm1vsqrtsd xmm1,xmm0,mmword ptr [7FF94F9E4D68h]vaddsd xmm0,xmm0,xmm1vsqrtsd xmm1,xmm0,mmword ptr [7FF94F9E4D70h]vaddsd xmm0,xmm0,xmm1vsqrtsd xmm1,xmm0,mmword ptr [7FF94F9E4D78h]vaddsd xmm0,xmm0,xmm1vsqrtsd xmm1,xmm0,mmword ptr [7FF94F9E4D80h]vaddsd xmm0,xmm0,xmm1vsqrtsd xmm1,xmm0,mmword ptr [7FF94F9E4D88h]vaddsd xmm0,xmm0,xmm1ret

73/85 2.8 Практика: Constant folding

Page 148: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Как же так?RyuJIT-x64, Sqrt14

vmovsd xmm0,qword ptr [7FF94F9C4C80h]ret

74/85 2.8 Практика: Constant folding

Page 149: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Как же так?Большое дерево выражения

* stmtExpr void (top level) (IL 0x000... ???)| /--* mathFN double sqrt| | \--* dconst double 13.000000000000000| /--* + double| | | /--* mathFN double sqrt| | | | \--* dconst double 12.000000000000000| | \--* + double| | | /--* mathFN double sqrt| | | | \--* dconst double 11.000000000000000| | \--* + double| | | /--* mathFN double sqrt| | | | \--* dconst double 10.000000000000000| | \--* + double| | | /--* mathFN double sqrt| | | | \--* dconst double 9.0000000000000000| | \--* + double| | | /--* mathFN double sqrt| | | | \--* dconst double 8.0000000000000000| | \--* + double| | | /--* mathFN double sqrt| | | | \--* dconst double 7.0000000000000000| | \--* + double| | | /--* mathFN double sqrt| | | | \--* dconst double 6.0000000000000000| | \--* + double| | | /--* mathFN double sqrt| | | | \--* dconst double 5.0000000000000000// ...

75/85 2.8 Практика: Constant folding

Page 150: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Как же так?Constant folding в действии

N001 [000001] dconst 1.0000000000000000 => $c0 {DblCns[1.000000]}N002 [000002] mathFN => $c0 {DblCns[1.000000]}N003 [000003] dconst 2.0000000000000000 => $c1 {DblCns[2.000000]}N004 [000004] mathFN => $c2 {DblCns[1.414214]}N005 [000005] + => $c3 {DblCns[2.414214]}N006 [000006] dconst 3.0000000000000000 => $c4 {DblCns[3.000000]}N007 [000007] mathFN => $c5 {DblCns[1.732051]}N008 [000008] + => $c6 {DblCns[4.146264]}N009 [000009] dconst 4.0000000000000000 => $c7 {DblCns[4.000000]}N010 [000010] mathFN => $c1 {DblCns[2.000000]}N011 [000011] + => $c8 {DblCns[6.146264]}N012 [000012] dconst 5.0000000000000000 => $c9 {DblCns[5.000000]}N013 [000013] mathFN => $ca {DblCns[2.236068]}N014 [000014] + => $cb {DblCns[8.382332]}N015 [000015] dconst 6.0000000000000000 => $cc {DblCns[6.000000]}N016 [000016] mathFN => $cd {DblCns[2.449490]}N017 [000017] + => $ce {DblCns[10.831822]}N018 [000018] dconst 7.0000000000000000 => $cf {DblCns[7.000000]}N019 [000019] mathFN => $d0 {DblCns[2.645751]}N020 [000020] + => $d1 {DblCns[13.477573]}...

76/85 2.8 Практика: Constant folding

Page 151: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 2.9Instruction level parallelism

77/85 2.9 Практика: Instruction level parallelism

Page 152: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Неожиданные perf-эффекты

1Справедливо для RyuJIT RC, ныне пофикшено78/85 2.9 Практика: Instruction level parallelism

Page 153: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Задачка

private double[] x = new double[11];

[Benchmark]public double Calc(){

double sum = 0.0;for (int i = 1; i < x.Length; i++)

sum += 1.0 / (i * i) * x[i];return sum;

}

LegacyJIT-x64 RyuJIT-x641Calc 1 попугай 2 попугая

79/85 2.9 Практика: Instruction level parallelism

Page 154: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Задачка

private double[] x = new double[11];

[Benchmark]public double Calc(){

double sum = 0.0;for (int i = 1; i < x.Length; i++)

sum += 1.0 / (i * i) * x[i];return sum;

}

LegacyJIT-x64 RyuJIT-x641Calc 1 попугай 2 попугая

1RyuJIT RC79/85 2.9 Практика: Instruction level parallelism

Page 155: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Как же так?

; LegacyJIT-x64; eax = imov eax,r8d; eax = i*iimul eax,r8d; xmm0=i*icvtsi2sd xmm0,eax; xmm1=1movsd xmm1,

mmword ptr [7FF9141145E0h]; xmm1=1/(i*i)divsd xmm1,xmm0

; xmm1=1/(i*i)*x[i]mulsd xmm1,

mmword ptr [rdx+r9+10h]; xmm1 = sum + 1/(i*i)*x[i]addsd xmm1,xmm2; sum = sum + 1/(i*i)*x[i]movapd xmm2,xmm1

; RyuJIT-x64; r8d = imov r8d,eax; r8d = i*iimul r8d,eax; xmm1=i*ivcvtsi2sd xmm1,xmm1,r8d; xmm2=1vmovsd xmm2,

qword ptr [7FF9140E4398h]; xmm2=1/(i*i)vdivsd xmm2,xmm2,xmm1mov r8,rdxmovsxd r9,eax; xmm1 = 1/(i*i)vmovaps xmm1,xmm2; xmm1 = 1/(i*i)*x[i]vmulsd xmm1,xmm1,

mmword ptr [r8+r9*8+10h]; sum += 1/(i*i)*x[i]vaddsd xmm0,xmm0,xmm1

См. также: https://github.com/dotnet/coreclr/issues/993

80/85 2.9 Практика: Instruction level parallelism

Page 156: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Часть 3Заключение

81/85 3. Заключение

Page 157: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Отказ от ответственности

• Все представленные выводы и бенчмаркимогут быть враньём

• Использование BenchmarkDotNet не делаетваш бенчмарк правильным

• Использование самописных бенчмарков неделает выводы ложными

82/85 3. Заключение

Page 158: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Отказ от ответственности

• Все представленные выводы и бенчмаркимогут быть враньём

• Использование BenchmarkDotNet не делаетваш бенчмарк правильным

• Использование самописных бенчмарков неделает выводы ложными

82/85 3. Заключение

Page 159: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Отказ от ответственности

• Все представленные выводы и бенчмаркимогут быть враньём

• Использование BenchmarkDotNet не делаетваш бенчмарк правильным

• Использование самописных бенчмарков неделает выводы ложными

82/85 3. Заключение

Page 160: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Отказ от ответственности

• Все представленные выводы и бенчмаркимогут быть враньём

• Использование BenchmarkDotNet не делаетваш бенчмарк правильным

• Использование самописных бенчмарков неделает выводы ложными

82/85 3. Заключение

Page 161: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Сегодня мы узнали

• Бенчмаркинг и прочие замерыпроизводительности — это сложно

• Бенчмаркинг требует очень много сил,знаний, времени и нервов

• Бенчмарк без анализа — плохой бенчмарк

83/85 3. Заключение

Page 162: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Сегодня мы узнали

• Бенчмаркинг и прочие замерыпроизводительности — это сложно

• Бенчмаркинг требует очень много сил,знаний, времени и нервов

• Бенчмарк без анализа — плохой бенчмарк

83/85 3. Заключение

Page 163: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Сегодня мы узнали

• Бенчмаркинг и прочие замерыпроизводительности — это сложно

• Бенчмаркинг требует очень много сил,знаний, времени и нервов

• Бенчмарк без анализа — плохой бенчмарк

83/85 3. Заключение

Page 164: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Сегодня мы узнали

• Бенчмаркинг и прочие замерыпроизводительности — это сложно

• Бенчмаркинг требует очень много сил,знаний, времени и нервов

• Бенчмарк без анализа — плохой бенчмарк

83/85 3. Заключение

Page 165: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Методическая литератураДля успешных микробенчмарков нужно очень много знать:

84/85 3. Заключение

Page 166: Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)

Вопросы?

Андрей Акиньшинhttp://aakinshin.net

https://github.com/AndreyAkinshinhttps://twitter.com/andrey_akinshin

[email protected]

85/85 3. Заключение