- PVSM.RU - https://www.pvsm.ru -
Заглянуть «под капот» кода или посмотреть на внутреннее устройство CLR можно с помощью множества инструментов. Этот пост родился из твита [1], и я должен поблагодарить всех, кто помог составить список подходящих инструментов. Если я пропустил какие-то из них, напишите в комментариях.
Во-первых, я должен упомянуть, что хороший отладчик уже присутствует в Visual Studio [2] и VSCode [3]. Также существует множество хороших (коммерческих) профилировщиков .NET [4] и инструментов мониторинга приложений [5], на которые стоит взглянуть. Например, недавно я попробовал поработать с Codetrack [6] и был впечатлён его возможностями.
Однако оставшийся пост посвящён инструментам для выполнения отдельных задач, которые позволят лучше понять, что происходит. Все инструменты имеют открытый исходный код.
PerfView – великолепный инструмент, который я использую уже несколько лет. Он работает на основе трассировки событий Windows [9] (ETW) и позволяет лучше понять, что происходит внутри CLR, а также даёт возможность получить профиль использования памяти и центрального процессора. Чтобы освоить инструмент, придётся впитать много информации, например с помощью обучающих видео [10], но это стоит потраченного времени и усилий.
Инструмент настолько полезен, что сами инженеры Microsoft используют его, а многие из недавних улучшений производительности в MSBuild [11] появились после анализа узких мест [12] с помощью PerfView.
Инструмент создан на базе библиотеки Microsoft.Diagnostics.Tracing.TraceEvent library [13], которую можно использовать для создания собственных инструментов. Кроме того, поскольку исходный код библиотеки является открытым, в ней благодаря сообществу появилось множество полезных функций, например графики flame-graphs [14]:
SharpLab появился как инструмент для проверки IL-кода, генерируемого компилятором Roslyn, и со временем превратился в нечто большее [17]:
SharpLab – интерактивная среда для запуска кода .NET, в которой отображаются промежуточные шаги и результаты компиляции кода. Некоторые функции языка – всего лишь обёртки для других, например using() становится try/catch. С помощью SharpLab вы увидите код, как его видит компилятор и лучше поймёте суть языков .NET.
Инструмент поддерживает C#, Visual Basic и F#, но самыми интересными функциями в нём являются Decompilation/Disassembly:
Функции декомпиляции/дизассемблирования можно использовать для:
Вы правильно поняли: инструмент выводит код ассемблера [18], который .NET JIT генерирует из вашего кода C#:
С помощью этого инструмента вы сможете проанализировать структуру .NET объектов в памяти, т.е. как JITter расположил поля, принадлежащие вашему классу или структуре. Это полезно при написании высокопроизводительного кода. Кроме того, приятно иметь инструмент, который сделает сложную работу за нас.
Официальной документации, которая бы описывала структуру полей, не существует, поскольку авторы CLR оставили за собой право изменить её в будущем. Но знания о структуре могут быть полезны, если вы работаете над быстродействующим приложением.
Как можно изучить структуру? Можно посмотреть на необработанную память в Visual Studio или использовать команду !dumpobj
в SOS Debugging Extension [21]. Оба подхода требуют много усилий, поэтому мы создадим инструмент, который будет выводить структуру объекта во время выполнения.
Согласно примеру в репозитории GitHub, если вы используете TypeLayout.Print<NotAlignedStruct>()
с подобным кодом:
public struct NotAlignedStruct
{
public byte m_byte1;
public int m_int;
public byte m_byte2;
public short m_short;
}
появится следующий вывод, который точно покажет, как CLR расположит struct в памяти на основании правил оптимизации и заполнения байтами.
Size: 12. Paddings: 4 (%33 of empty space)
|================================|
| 0: Byte m_byte1 (1 byte) |
|--------------------------------|
| 1-3: padding (3 bytes) |
|--------------------------------|
| 4-7: Int32 m_int (4 bytes) |
|--------------------------------|
| 8: Byte m_byte2 (1 byte) |
|--------------------------------|
| 9: padding (1 byte) |
|--------------------------------|
| 10-11: Int16 m_short (2 bytes) |
|================================|
Как сказано на странице GitHub [24], TUNE – многообещающий инструмент. Он поможет изучить внутреннее устройство .NET и способы повышения производительности с помощью экспериментов с кодом C#.
Подробную информацию о нём можно узнать из этого поста [22], но на высоком уровне он функционирует следующим образом [24]:
Выглядит это следующим образом:
Наконец, давайте взглянем на определённую категорию инструментов. С момента выхода .NET разработчики всегда могли использовать WinDBG [25] и SOS Debugging Extension [21], чтобы посмотреть, что происходит в среде выполнения .NET. Однако, это не самые простые инструменты для первого знакомства и, как сказано в следующем твите, не всегда самые продуктивные:
К счастью, Microsoft сделал доступной библиотеку ClrMD [28] (также известную, как Microsoft.Diagnostics.Runtime [29]), и теперь любой может создать инструмент для анализа дампов памяти программ .NET. Подробную информацию можно прочитать в официальном блоге [30]. Я также рекомендую взглянуть на ClrMD.Extensions [31], которые “… обеспечивают интеграцию с LINPad и делают использование ClrMD ещё проще”.
Я хотел собрать список всех существующих инструментов и призвал на помощь твиттер [1]. Напоминалочка самому себе: осторожнее с твитами. Менеджер, ответственный за WinDBG, может прочитать их и расстроиться!
Большинство этих инструментов работают на базе ClrMD, потому что так проще всего. Но при желании можно использовать COM-интерфейсы напрямую [35]. Также нужно заметить, что любой инструмент на базе ClrMD не является кроссплатформенным, поскольку сама ClrMD предназначена только для Windows. Описание кроссплатформенных вариантов можно найти в Analyzing a .NET Core Core Dump on Linux [36].
Наконец, чтобы как-то соблюсти баланс, недавно появилась улучшенная версия WinDBG [37], которой сразу же попытались добавить функциональность:
После всех этих слов переходим к списку:
!DumpHeap
в Windbg может определить, какие объекты занимают больше всего места в куче без необходимости устанавливать отладчик.Вы можете найти множество других инструментов, которые используют ClrMD [62]. Сделать её доступной было хорошей идеей Microsoft.
Стоит упомянуть и другие инструменты:
Автор: Stanislav Sidristij
Источник [67]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/c-2/327451
Ссылки в тексте:
[1] твита: https://twitter.com/matthewwarren/status/973940550473797633
[2] хороший отладчик уже присутствует в Visual Studio: https://msdn.microsoft.com/en-us/library/sc65sadd.aspx?f=255&MSPPError=-2147217396
[3] VSCode: https://code.visualstudio.com/docs/editor/debugging
[4] профилировщиков .NET: https://stackoverflow.com/questions/3927/what-are-some-good-net-profilers
[5] инструментов мониторинга приложений: https://www.quora.com/What-is-the-best-NET-Application-Server-Monitoring-Tool
[6] Codetrack: http://www.getcodetrack.com/
[7] PerfView: https://github.com/Microsoft/perfview
[8] Вэнса Моррисона: https://blogs.msdn.microsoft.com/vancem/
[9] трассировки событий Windows: https://msdn.microsoft.com/en-us/library/windows/desktop/bb968803(v=vs.85).aspx?f=255&MSPPError=-2147217396
[10] обучающих видео: https://channel9.msdn.com/Series/PerfView-Tutorial
[11] улучшений производительности в MSBuild: https://blogs.msdn.microsoft.com/dotnet/2018/02/02/net-core-2-1-roadmap/#user-content-build-time-performance
[12] анализа узких мест: https://github.com/Microsoft/msbuild/search?q=PerfView&type=Issues
[13] Microsoft.Diagnostics.Tracing.TraceEvent library: https://www.nuget.org/packages/Microsoft.Diagnostics.Tracing.TraceEvent/
[14] графики flame-graphs: https://github.com/Microsoft/perfview/pull/502
[15] SharpLab: https://sharplab.io/
[16] Андрея Щёкина: https://twitter.com/ashmind
[17] в нечто большее: https://github.com/ashmind/SharpLab
[18] код ассемблера: https://sharplab.io/#v2:EYLgZgpghgLgrgJwgZwLQBEJinANjASQDsYIFsBjCAgWwAdcIaITYBLAeyIBoYQpkNAD4ABAAwACEQEYA3AFgAUCIDMUgEwSAwhIDeSiYalqRAFgkBZABQBKPQaOOAblAQTSyGBIC8EgKwAdGIKio6OMgCcVh4wNiGOAL5KCUA==
[19] Object Layout Inspector: https://github.com/SergeyTeplyakov/ObjectLayoutInspector
[20] Сергея Теплякова: https://twitter.com/STeplyakov
[21] SOS Debugging Extension: https://docs.microsoft.com/en-us/dotnet/framework/tools/sos-dll-sos-debugging-extension
[22] The Ultimate .NET Experiment (TUNE): http://tooslowexception.com/the-ultimate-net-experiment-project/
[23] Конрада Кокосы: https://twitter.com/konradkokosa
[24] на странице GitHub: https://github.com/kkokosa/Tune
[25] WinDBG: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/getting-started-with-windbg
[26] https://t.co/jQanX9LVtz: https://t.co/jQanX9LVtz
[27] March 14, 2018: https://twitter.com/omerraviv/status/973923339906486272?ref_src=twsrc%5Etfw
[28] ClrMD: https://mattwarren.org/2016/09/06/Analysing-.NET-Memory-Dumps-with-CLR-MD/
[29] Microsoft.Diagnostics.Runtime: https://www.nuget.org/packages/Microsoft.Diagnostics.Runtime
[30] в официальном блоге: https://blogs.msdn.microsoft.com/dotnet/2013/05/01/net-crash-dump-and-live-process-inspection/
[31] ClrMD.Extensions: https://github.com/JeffCyr/ClrMD.Extensions
[32] https://t.co/sg0RY0xVUH: https://t.co/sg0RY0xVUH
[33] pic.twitter.com/XBYuSLSL2y: https://t.co/XBYuSLSL2y
[34] March 14, 2018: https://twitter.com/matthewwarren/status/973940550473797633?ref_src=twsrc%5Etfw
[35] COM-интерфейсы напрямую: https://twitter.com/goldshtn/status/973941389791809540
[36] Analyzing a .NET Core Core Dump on Linux: http://blogs.microsoft.co.il/sasha/2017/02/26/analyzing-a-net-core-core-dump-on-linux/
[37] улучшенная версия WinDBG: https://blogs.msdn.microsoft.com/windbg/2017/08/28/new-windbg-available-in-preview/
[38] Extending the new WinDbg, Part 1 – Buttons and commands: http://labs.criteo.com/2017/09/extending-new-windbg-part-1-buttons-commands/
[39] Extending the new WinDbg, Part 2 – Tool windows and command output: http://labs.criteo.com/2018/01/extending-new-windbg-part-2-tool-windows-command-output/
[40] Extending the new WinDbg, Part 3 – Embedding a C# interpreter: http://labs.criteo.com/2018/05/extending-new-windbg-part-3-embedding-c-interpreter/
[41] WinDBG extension + UI tool extensions: https://github.com/chrisnas/DebuggingExtensions
[42] здесь: https://github.com/kevingosse/windbg-extensions
[43] NetExt: https://github.com/rodneyviana/netext
[44] облегчает отладку в .NET: https://blogs.msdn.microsoft.com/rodneyviana/2015/03/10/getting-started-with-netext/
[45] эту статью InfoQ: https://www.infoq.com/news/2013/11/netext
[46] SuperDump: https://www.slideshare.net/ChristophNeumller/large-scale-crash-dump-analysis-with-superdump
[47] GitHub: https://github.com/Dynatrace/superdump
[48] msos: https://github.com/goldshtn/msos/wiki
[49] GitHub: https://github.com/goldshtn/msos
[50] MemoScope.Net: https://github.com/fremag/MemoScope.Net/wiki
[51] GitHub: https://github.com/fremag/MemoScope.Net
[52] dnSpy: https://github.com/0xd4d/dnSpy#dnspy
[53] GitHub: https://github.com/0xd4d/dnSpy
[54] MemAnalyzer: https://aloiskraus.wordpress.com/2017/08/17/memanalyzer-v2-5-released/
[55] GitHub: https://github.com/Alois-xx/MemAnalyzer
[56] DumpMiner: https://mycodingplace.wordpress.com/2016/11/24/dumpminer-ui-tool-for-playing-with-clrmd/
[57] GitHub: https://github.com/dudikeleti/DumpMiner
[58] появится в будущем: https://twitter.com/dudi_ke/status/973930633935409153
[59] Trace CLI: http://devops.lol/tracecli-a-production-debugging-and-tracing-tool/
[60] GitHub: https://github.com/ruurdk/TraceCLI/
[61] Shed: https://github.com/enkomio/shed
[62] которые используют ClrMD: https://github.com/search?p=2&q=CLRMD&type=Repositories&utf8=%E2%9C%93
[63] DebugDiag: https://support.microsoft.com/en-gb/help/2895198/debug-diagnostics-tool-v2-0-is-now-available
[64] SOSEX: http://www.stevestechspot.com/SOSEXANewDebuggingExtensionForManagedCode.aspx
[65] VMMap: https://docs.microsoft.com/en-us/sysinternals/downloads/vmmap
[66] использование памяти в CLR: https://mattwarren.org/2017/07/10/Memory-Usage-Inside-the-CLR/
[67] Источник: https://habr.com/ru/post/463305/?utm_source=habrahabr&utm_medium=rss&utm_campaign=463305
Нажмите здесь для печати.