Как мы
оптимизировали
ReSharper

Скрыган Кирилл,
JetBrains
DotTrace
Алгоритмическая производительность
• DotTrace – как инструмент анализа
  производительности
• Sampling: почти «честное» время выполнения,
  профилирование практически не накладное по
  производительности
Алгоритмическая производительность
• Tracing: дорогое профилирование, не отражает
  реального времени выполнения, но показывает
  количество вызов
• Timeline: инструмент для анализа
  производительности многопоточных приложений
Типичные продолбы
• Алгоритмический «взрыв» (квадрат или больше)
• Ожидание на lock’ах
• Memory traffic (о нём поподробнее )
Memory traffic: GC
• В деталях, механику CLR GC не знает никто, кроме
  самих CLR team. Алгоритмы и принципы CLR GC
  весьма закрыты.
Memory traffic: GC
• «Stop-the-world» - блокировка всех трэдов
• Чем больше memory traffic – тем чаще вызывается
  GC
• LOH – Large Object Heap (>82 Кб) – специальная
  куча для больших объектов
Memory traffic
• Стараемся не создавать новых объектов, там, где
  не нужно.
• Объекты зачастую неожиданно создаются в
  неочевидных местах.
Замыкания: то, что видим мы
Замыкания: что генерируется
Params: что мы видим
Params всегда аллоцирует объект!
Две лямбды…
…и только один замыкающий класс!
Yield
Во что компилируется yield
Closure scope
Ну и самое «сладкое»: IList vs List 
Memory traffic: прочие примеры
• LinQ, Select and others
• Guid.ToString() создаёт дважды. Можно переписать
  через stackalloc
ReSharper: статический анализ
Соображения о структурах данных
• Equals вызывается чаще чем GetEntry? – см.
  коллизии
• Интернирующие структуры данных
• StringSlice – лекарство против SubString
StringSlice в лексере


                        INTERN
Неочевидные соображения о структурах
данных : LocalList
LOH
• Объекты в LOH никогда не перемещаются
• LOH только растет и никогда не уменьшается (т.е.
  если объект собран сборщиком мусора, размер
  LOH все равно остается неизменным)
• Хип LOH освобождается только тогда, когда LOH
  полностью пуст
• Как следствие – OutOfMemory из-за сильно
  фрагментированной памяти
Пример: ChunkList
Boxing
• Очевидные проблемы: используем value types в
  качестве reference types
• public struct ToBeBoxed : IMySuperInterface {…}
• Не забываем что все итераторы – struct’ы!
.NET method group bug
                                 Lambda
Delegate target   Method group                Ratio
                                 expression

Class             329            463          0.71


Interface         24474          461          53.1


Struct            28372          400          71.0
Более общие соображения
• «Кризис среднего возраста» для объектов
• Есть смысл задумать о том, в каком поколении
  собираются объекты. Желательно, чтобы в Gen0 
• WeakReferences – только в крайнем случае.
Caches: тонкости
• LevelDb – храним кэши на диске
• DirectMappedCache, LRUWeakReferenceCache –
  «вытесняющие» словари с ограниченным
  размером
UI Thread: тонкости в обращении
• Chunked operations – прерываем операции в
  других потоках, чтобы не зависать в UI потоке
• InterruptableReadactivityCookie – операция,
  прерываемая в том числе по WriteLock.Acquire() из
  UI потока
Tools
• ReSharper – статический анализ кода на
  performance issues.
• DotTrace – профилятор
• DotMemory, .NET Memory Profiler – memory-
  профилятор
• DotPeek (ReSharper) – декомпилятор
• Ildasm.exe
Вопросы?


Скрыган Кирилл,
JetBrains
Kirill.skrygan@jetbrains.com
twitter.com/kskrygan

CodeFest 2013. Скрыган К. — Оптимизация .Net приложений на примере Resharper

Editor's Notes

  • #9 Конкретный пример здесь!