{"id":23084,"date":"2019-05-08T09:00:57","date_gmt":"2019-05-08T16:00:57","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=23084"},"modified":"2019-05-08T09:05:47","modified_gmt":"2019-05-08T16:05:47","slug":"introducing-diagnostics-improvements-in-net-core-3-0","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/introducing-diagnostics-improvements-in-net-core-3-0\/","title":{"rendered":"Introducing diagnostics improvements in .NET Core 3.0"},"content":{"rendered":"<p>In .NET Core 3.0, we are introducing a suite of tools that utilize new features in the .NET runtime that make it easier to diagnose and solve performance problems.<\/p>\n<p>These runtime features help you answer some common diagnostic questions you may have:<\/p>\n<ol type=\"1\">\n<li>Is my application healthy?<\/li>\n<li>Why does my application have anomalous behavior?<\/li>\n<li>Why did my application crash?<\/li>\n<\/ol>\n<h3 id=\"is-my-application-healthy\">Is my application healthy?<\/h3>\n<p>Often times an application can slowly start leaking memory and eventually result in an out of memory exception. Other times, certain problematic code paths may result in a spike in CPU utilization. These are just some of the classes of problem you can pro-actively identify with <strong>metrics<\/strong>.<\/p>\n<h4 id=\"metrics\">Metrics<\/h4>\n<p>Metrics are a representation of data measures over intervals of time. Metrics (or time-series) data allow you to observe the state of your system at a high-level. Unlike the .NET Framework on Windows, .NET Core doesn\u2019t emit perf counters. Instead, we had introduced a new way of emitting metrics in .NET Core via the <a href=\"https:\/\/github.com\/dotnet\/corefx\/blob\/master\/src\/Common\/src\/CoreLib\/System\/Diagnostics\/Tracing\/EventCounter.cs\">EventCounter<\/a> API.<\/p>\n<p>EventCounters offer an improvement over Windows perf counters as these are now usable on all OSes where .NET Core is supported. Additionally, unlike perf counters, they are also usable in low privilege environments (like xcopy deployments). Unfortunately, the lack of a tool like Performance Monitor (perfmon) made it difficult to consume these metrics in real time.<\/p>\n<h4 id=\"dotnet-counters\"><code>dotnet-counters<\/code><\/h4>\n<p>In 3.0-preview5, we are introducing a new command-line tool for observing metrics emitted by .NET Core Applications in real time.<\/p>\n<p>You can install this .NET global tool by running the following command<\/p>\n<p><code><code class=\"sourceCode bash\"><span class=\"ex\">dotnet<\/span> tool install --global dotnet-counters --version 1.0.3-preview5.19251.2<\/code><\/code><\/p>\n<p>In the example below, we see the CPU utilization and working set memory of our application jump up when we point a load generator at our web application.<\/p>\n<p><script id=\"asciicast-244927\" src=\"https:\/\/asciinema.org\/a\/244927.js\" async><\/script><\/p>\n<p>For detailed instructions on how to use this tool, look at the <a href=\"https:\/\/github.com\/dotnet\/diagnostics\/blob\/master\/documentation\/dotnet-counters-instructions.md\">dotnet-counters readme<\/a>. For known limitations with <code>dotnet-counters<\/code>, look at the <a href=\"https:\/\/github.com\/dotnet\/diagnostics\/issues?q=is%3Aopen+is%3Aissue+label%3Adotnet-counters\">open issues on GitHub<\/a>.<\/p>\n<h3 id=\"why-does-my-application-have-anomalous-behavior\">Why does my application have anomalous behavior?<\/h3>\n<p>While metrics help identify the occurence of anomalous behavior, they offer little visibility into what went wrong. To answer the question why your application has anomalous behavior you need to collect additional information via traces.\u00a0As an example, CPU profiles collected via tracing can help you identify the hot path in your code.<\/p>\n<h4 id=\"tracing\">Tracing<\/h4>\n<p>Traces are immutable timestamped records of discrete events. Traces contain local context that allow you to better infer the fate of a system. Traditionally, the .NET Framework (and frameworks like ASP.NET) emitted diagnostic traces about its internals via Event Tracing for Windows (ETW). In .NET Core, these trace were written to ETW on Windows and LTTng on Linux.<\/p>\n<h4 id=\"dotnet-trace\"><code>dotnet-trace<\/code><\/h4>\n<p>In 3.0-preview5, every .NET Core application opens a duplex pipe named <code>EventPipe<\/code> (Unix domain socket on *nix\/named pipe on Windows) over which it can emit events. While we\u2019re still working on the controller protocol, <code>dotnet-trace<\/code> implements the preview version of this protocol.<\/p>\n<p>You can install this .NET global tool by running the following command<\/p>\n<p><code><code class=\"sourceCode bash\"><span class=\"ex\">dotnet<\/span> tool install --global dotnet-trace--version 1.0.3-preview5.19251.2<\/code><\/code><\/p>\n<div id=\"cb1\" class=\"sourceCode\"><\/div>\n<figure><\/figure>\n<p><script id=\"asciicast-245028\" src=\"https:\/\/asciinema.org\/a\/245028.js\" async><\/script><\/p>\n<p>In the example above, I\u2019m running <code>dotnet trace<\/code> with the default profile which enables the CPU profiler events and the .NET runtime events.<\/p>\n<p>In addition to the default events, you can enable <a href=\"https:\/\/github.com\/dotnet\/diagnostics\/blob\/master\/documentation\/dotnet-trace-instructions.md\">additional providers<\/a> based on the investigation you are trying to perform.<\/p>\n<p>As a result of running <code>dotnet trace<\/code> you are presented with a <code>.netperf<\/code> file. This file contains both the runtime events and sampled CPU stacks that can be visualized in <a href=\"https:\/\/github.com\/Microsoft\/perfview\">perfview<\/a>. The next update of Visual Studio (16.1) will also add support for visualizing these traces.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/user-images.githubusercontent.com\/4734691\/57052078-c5dc5e00-6c39-11e9-91d1-c515b8c00f49.png\" alt=\"VS visualization\" \/><\/figure>\n<p>If you\u2019re running on OS X or Linux when you capture a trace, you can choose to convert these <code>.netperf<\/code> files to <code>.speedscope.json<\/code> files that can be visualized with <a href=\"https:\/\/www.speedscope.app\/\">Speedscope.app<\/a>.<\/p>\n<p>You can convert an existing trace by running the following command<\/p>\n<p><code><code class=\"sourceCode bash\"><span class=\"ex\">dotnet<\/span> trace convert &lt;input-netperf-file&gt;<\/code><\/code><\/p>\n<div id=\"cb2\" class=\"sourceCode\"><\/div>\n<p>The image below shows the icicle chart visualizing the trace we just captured in speedscope.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/user-images.githubusercontent.com\/4734691\/57051263-9297d000-6c35-11e9-8b7d-94bc2b70e45a.png\" alt=\"icicle\" \/><\/figure>\n<p>For detailed instructions on how to use this tool, look at the <a href=\"https:\/\/github.com\/dotnet\/diagnostics\/blob\/master\/documentation\/dotnet-trace-instructions.md\">dotnet-trace readme<\/a>. For known limitations with <code>dotnet-trace<\/code>, look at the <a href=\"https:\/\/github.com\/dotnet\/diagnostics\/issues?q=is%3Aopen+is%3Aissue+label%3Adotnet-trace\">open issues on GitHub<\/a>.<\/p>\n<h3 id=\"why-did-my-application-crash\">Why did my application crash?<\/h3>\n<p>In some cases, it is not possible to ascertain what caused anomalous behavior by just tracing the process. In the event that the process crashed or situations where we may need more information like access to entire process heap, a process dump may be more suitable for analysis.<\/p>\n<h4 id=\"dump-analysis\">Dump Analysis<\/h4>\n<p>A dump is a recording of the state of working virtual memory of a process usually captured when the process has terminated unexpectedly. Diagnosing core dump is commonly used to identify the causes of application crashes or unexpected behavior.<\/p>\n<p>Traditionally, you relied on your operating system to capture a dump on application crash (e.g., Windows Error Reporting) or used a tool like <a href=\"https:\/\/docs.microsoft.com\/en-us\/sysinternals\/downloads\/procdump\">procdump<\/a> to capture a dump when certain trigger criteria are met.<\/p>\n<p>The challenge thus far with capturing dumps with .NET on Linux was capturing dumps with <code>gcore<\/code> or a debugger resulted extremely large dumps as the existing tools didn\u2019t know what virtual memory pages to trim in a .NET Core process.<\/p>\n<p>Additionally, it was challenging to analyze these dumps even after you had collected them as it required acquiring a debugger and configuring it to load <code>sos<\/code>, a debugger extension for .NET.<\/p>\n<h4 id=\"dotnet-dump\"><code>dotnet-dump<\/code><\/h4>\n<p>3.0.0-preview5, we\u2019re introducing a new tool that allows you to capture and analyze process dumps on both Windows and Linux.<\/p>\n<p><code>dotnet-dump<\/code> is still under active development and the table below shows what functionality is currently supported on what operating systems.<\/p>\n<table style=\"height: 84px; width: 265px; border-style: solid;\">\n<tbody>\n<tr style=\"height: 28px;\">\n<td style=\"width: 60px; text-align: center; height: 28px;\"><\/td>\n<td style=\"width: 68px; text-align: center; height: 28px;\"><strong>Windows<\/strong><\/td>\n<td style=\"width: 69.6px; text-align: center; height: 28px;\"><strong>OS X<\/strong><\/td>\n<td style=\"width: 66.4px; text-align: center; height: 28px;\"><strong>Linux<\/strong><\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"width: 60px; height: 28px;\"><strong>Collect<\/strong><\/td>\n<td style=\"text-align: center; width: 68px; height: 28px;\">\n<div>\n<div>\u2705<\/div>\n<\/div>\n<\/td>\n<td style=\"text-align: center; width: 69.6px; height: 28px;\">\n<div>\n<div>\u274c<\/div>\n<\/div>\n<\/td>\n<td style=\"text-align: center; width: 66.4px; height: 28px;\">\n<div>\n<div>\u2705<\/div>\n<\/div>\n<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"width: 60px; height: 28px;\"><strong>Analyze<\/strong><\/td>\n<td style=\"text-align: center; width: 68px; height: 28px;\">\n<div>\n<div>\u274c<\/div>\n<\/div>\n<\/td>\n<td style=\"text-align: center; width: 69.6px; height: 28px;\">\n<div>\n<div>\u274c<\/div>\n<\/div>\n<\/td>\n<td style=\"text-align: center; width: 66.4px; height: 28px;\">\n<div>\n<div>\u2705<\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>You can install this .NET global tool by running the following command<\/p>\n<p><code><code class=\"sourceCode bash\"><span class=\"ex\"><span class=\"ex\">dotnet<\/span> tool install --global dotnet-dump --version 1.0.3-preview5.19251.2<\/span><\/code><\/code><\/p>\n<p>Once you\u2019ve installed <code>dotnet dump<\/code>, you can capture a process dump by running the following command<\/p>\n<p><code><code class=\"sourceCode bash\"><span class=\"ex\"><span class=\"ex\">sudo<\/span> $HOME\/.dotnet\/tools\/dotnet-dump collect -p &lt;pid&gt;<\/span><\/code><\/code><\/p>\n<p>On Linux, the resulting dump can be analyzed by loading the resulting dump by running the following command<\/p>\n<p><code><code class=\"sourceCode bash\"><span class=\"ex\"><span class=\"ex\">dotnet<\/span> dump analyze &lt;dump-name&gt;<\/span><\/code><\/code><\/p>\n<p>In the following example, I try to determine ASP.NET Core Hosting Environment of a crashed dump by walking the heap.<\/p>\n<p><script id=\"asciicast-245026\" src=\"https:\/\/asciinema.org\/a\/245026.js\" async><\/script><\/p>\n<p>For detailed instructions on how to use this tool, look at the <a href=\"https:\/\/github.com\/dotnet\/diagnostics\/blob\/master\/documentation\/dotnet-dump-instructions.md\">dotnet-dump readme<\/a>. For known limitations with <code>dotnet-dump<\/code>, look at the <a href=\"https:\/\/github.com\/dotnet\/diagnostics\/issues?q=is%3Aopen+is%3Aissue+label%3Adotnet-dump\">open issues on GitHub<\/a>.<\/p>\n<h3 id=\"closing\">Closing<\/h3>\n<p>Thanks for trying out the new diagnostics tools in .NET Core 3.0. Please continue to give us feedback, either in the comments or on <a href=\"https:\/\/github.com\/dotnet\/diagnostics\">GitHub<\/a>. We are listening carefully and will continue to make changes based on your feedback.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In .NET Core 3.0, we are introducing a suite of tools that utilize new features in the .NET runtime that make it easier to diagnose and solve performance problems. These runtime features help you answer some common diagnostic questions you may have: Is my application healthy? Why does my application have anomalous behavior? Why did [&hellip;]<\/p>\n","protected":false},"author":1233,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[196],"tags":[9,59],"class_list":["post-23084","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet-core","tag-net-core","tag-diagnostics"],"acf":[],"blog_post_summary":"<p>In .NET Core 3.0, we are introducing a suite of tools that utilize new features in the .NET runtime that make it easier to diagnose and solve performance problems. These runtime features help you answer some common diagnostic questions you may have: Is my application healthy? Why does my application have anomalous behavior? Why did [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/23084","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/1233"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=23084"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/23084\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=23084"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=23084"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=23084"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}