{"id":54196,"date":"2025-11-26T02:56:12","date_gmt":"2025-11-26T02:56:12","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=54196"},"modified":"2025-11-26T02:56:12","modified_gmt":"2025-11-26T02:56:12","slug":"perfview-a-complete-tutorial-guide","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/perfview-a-complete-tutorial-guide\/","title":{"rendered":"PerfView: A Complete Tutorial Guide"},"content":{"rendered":"\n<p>PerfView is basically the <strong>Swiss-army knife for .NET performance<\/strong>\u2014CPU, GC, memory, thread time, and arbitrary ETW events\u2014all in one (slightly ugly but insanely powerful) tool. Let\u2019s turn this into the one-stop, end-to-end tutorial you asked for.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">1. What is PerfView?<\/h2>\n\n\n\n<p><strong>PerfView<\/strong> is a free Windows performance-analysis tool from Microsoft that focuses on:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>CPU usage<\/strong> (sampled stacks, call trees, wall-clock vs CPU time)<\/li>\n\n\n\n<li><strong>Managed memory &amp; GC<\/strong> (GC stats, allocation hotspots, heap snapshots)<\/li>\n\n\n\n<li><strong>Thread behavior<\/strong> (thread time, context switches, blocking)<\/li>\n\n\n\n<li><strong>General ETW\/EventPipe events<\/strong> (including app-specific providers)<\/li>\n<\/ul>\n\n\n\n<p>It:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Runs on <strong>Windows<\/strong> and requires <strong>.NET Framework 4.7.2+<\/strong>. ()<\/li>\n\n\n\n<li>Is distributed as a <strong>single EXE (PerfView.exe)<\/strong>\u2014no install wizard, just download and run. <\/li>\n\n\n\n<li>Is built on <code>Microsoft.Diagnostics.Tracing.TraceEvent<\/code>, so it can parse ETW and .NET EventPipe traces (.nettrace). ()<\/li>\n<\/ul>\n\n\n\n<p>Microsoft\u2019s own docs recommend PerfView for analyzing <strong>CPU, memory, GC, performance events, and wall-clock time<\/strong> in .NET apps. ()<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">2. Why do we need PerfView?<\/h2>\n\n\n\n<p>You reach for PerfView when you want <strong>deep, low-level truth<\/strong> about your .NET application, especially in production-like scenarios.<\/p>\n\n\n\n<p>Typical problems PerfView is great at:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>High CPU<\/strong>\n<ul class=\"wp-block-list\">\n<li>Identify hot methods, inefficient loops, excessive JSON parsing, etc.<\/li>\n\n\n\n<li>CPU Stacks + CallTree views make it clear where time is actually spent. ()<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>High GC \/ memory pressure<\/strong>\n<ul class=\"wp-block-list\">\n<li>GCStats for % Time in GC, collection counts, heap size growth. ()<\/li>\n\n\n\n<li>Heap snapshots and heap diffs to find <strong>which object graphs grow over time<\/strong>. ()<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Memory leaks \/ managed leaks<\/strong>\n<ul class=\"wp-block-list\">\n<li>Capture multiple heap snapshots, diff them, and see which types grew and who\u2019s holding them alive. ()<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Intermittent production issues<\/strong>\n<ul class=\"wp-block-list\">\n<li>\u201cFlight recorder\u201d style: collect ETW data in a <strong>ring buffer<\/strong> and stop when a trigger fires:\n<ul class=\"wp-block-list\">\n<li>Perf counter threshold (CPU, GC, memory)<\/li>\n\n\n\n<li>Long HTTP request<\/li>\n\n\n\n<li>Long GC<\/li>\n\n\n\n<li>Particular exception type or Event Log message ()<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Custom ETW analysis<\/strong>\n<ul class=\"wp-block-list\">\n<li>For example, Business Central, IIS, Visual Studio, or your own <code>EventSource<\/code> providers. ()<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p>PerfView trades pretty UI for <strong>power, low overhead, and precise control<\/strong> over what you collect and when.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">3. Installing PerfView<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">3.1. Download<\/h3>\n\n\n\n<p>The official way to get PerfView:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Go to <strong>GitHub Releases<\/strong>: (PerfView repo) \u2192 Releases. ()<\/li>\n\n\n\n<li>Or directly download the latest via the shortcut link documented by Microsoft (aka.ms\/perfview\/latest). ()<\/li>\n<\/ul>\n\n\n\n<p>You usually only need <strong>one file<\/strong>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">PerfView<\/span><span class=\"hljs-selector-class\">.exe<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Optional but recommended: verify the <strong>digital signature<\/strong> of PerfView.exe (right-click \u2192 Properties \u2192 Digital Signatures) to be sure it\u2019s the genuine Microsoft-signed binary. ()<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3.2. Prerequisites<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>OS<\/strong>: Supported Windows version (Windows 10+ \/ Server equivalents).<\/li>\n\n\n\n<li><strong>Runtime<\/strong>: <code>.NET Framework 4.7.2+<\/code> must be installed on the machine where you <em>run PerfView<\/em>. ()<\/li>\n\n\n\n<li>Admin rights:\n<ul class=\"wp-block-list\">\n<li>PerfView can collect some data without admin, but for <strong>full ETW (kernel + runtime)<\/strong> you should run it <strong>as Administrator<\/strong>. ()<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3.3. Running PerfView<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Put <code>PerfView.exe<\/code> into some tools folder, e.g. <code>C:\\tools\\PerfView<\/code>.<\/li>\n\n\n\n<li>Right-click \u2192 <strong>Run as administrator<\/strong> (especially on servers). ()<\/li>\n<\/ul>\n\n\n\n<p>No installation, no registry entries\u2014<strong>just xcopy<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">4. Key Terminology (PerfView &amp; ETW)<\/h2>\n\n\n\n<p>Understanding PerfView\u2019s vocabulary makes everything easier.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4.1. ETW, ETL, ETLX, and .etl.zip<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>ETW (Event Tracing for Windows)<\/strong><br>OS-level event pipeline used by PerfView. Kernel, .NET runtime, and many applications log events here. ()<\/li>\n\n\n\n<li><strong>ETL<\/strong><br>Raw ETW <strong>Event Trace Log<\/strong> file (<code>*.etl<\/code>). PerfView uses ETW sessions to write these. ()<\/li>\n\n\n\n<li><strong>ETLX<\/strong><br>PerfView\u2019s <strong>indexed\/processed<\/strong> version of ETL that speeds up viewing. When you open a trace, PerfView converts <code>*.etl<\/code> \u2192 <code>*.etlx<\/code>. ()<\/li>\n\n\n\n<li><strong>PerfViewData.etl.zip<\/strong><br>A zipped bundle that usually contains:\n<ul class=\"wp-block-list\">\n<li><code>PerfViewData.etl<\/code><\/li>\n\n\n\n<li>Possibly auxiliary ETL files and symbol\/PDB data<br>Used for <strong>sharing traces<\/strong> between machines. ()<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Merge<\/strong><br>Operation that merges kernel ETL with main ETL and grabs system-specific metadata into a single file for offline analysis. ()<\/li>\n\n\n\n<li><strong>Zip<\/strong><br>Optional step that compresses the merged trace and bundles relevant NGen PDBs. ()<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">4.2. Providers, Keywords, Levels<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Provider<\/strong><br>Source of events (e.g., <code>Microsoft-Windows-Kernel-Process<\/code>, <code>Microsoft-Windows-DotNETRuntime<\/code>, Business Central\u2019s <code>Microsoft-DynamicsNAV-Server<\/code>). ()<\/li>\n\n\n\n<li><strong>Keywords<\/strong><br>Bitmask controlling which categories of events are enabled for a provider (e.g. GC, loader, JIT, etc.). In Business Central docs you see things like <code>Microsoft-DynamicsNAV-Server:0x4<\/code> or <code>:0xC<\/code> to pick event classes. ()<\/li>\n\n\n\n<li><strong>Level<\/strong><br>Verbosity level (Critical, Error, Warning, Informational, Verbose).<\/li>\n<\/ul>\n\n\n\n<p>PerfView\u2019s <strong>\/Providers<\/strong> qualifier or \u201cAdditional Providers\u201d GUI textbox lets you specify <code>provider:keywords:level<\/code>. ()<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4.3. CPU sampling, Inclusive\/Exclusive time<\/h3>\n\n\n\n<p>PerfView\u2019s CPU analysis is built on <strong>sampling<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Every ~1 ms per CPU, ETW grabs a stack trace of the currently running thread. ()<\/li>\n\n\n\n<li>Each sample counts as ~1 ms of CPU.<\/li>\n<\/ul>\n\n\n\n<p>Terminology:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Exclusive metric<\/strong>: samples taken <em>in<\/em> a method itself.<\/li>\n\n\n\n<li><strong>Inclusive metric<\/strong>: samples taken in a method or <strong>anything it calls<\/strong> (the whole subtree). ()<\/li>\n<\/ul>\n\n\n\n<p>You normally optimize the <strong>inclusive heavy<\/strong> nodes in CPU Stacks \/ CallTree, then drill into them.<\/p>\n\n\n\n<p>PerfView also explains <strong>statistical error<\/strong>: you generally want <strong>1000+ samples<\/strong>, ideally ~5000, to reduce noise. ()<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4.4. GC, Generations, Heap, Allocation<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Generations (Gen 0 \/ 1 \/ 2, LOH)<\/strong>: tiers of the managed heap; Gen 0 is short-lived, LOH is for large objects.<\/li>\n\n\n\n<li><strong>GCStats<\/strong>: PerfView\u2019s view that summarizes GC counts, pause durations, heap size, % Time in GC, etc. ()<\/li>\n\n\n\n<li><strong>GC Heap Snapshot (.gcDump)<\/strong>: a snapshot of managed heap, whose \u201cHeap Stacks\u201d view tells you:\n<ul class=\"wp-block-list\">\n<li>Types using the most space<\/li>\n\n\n\n<li>How many instances<\/li>\n\n\n\n<li>Who\u2019s holding references to them ()<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">5. Getting Started \u2013 GUI, Step by Step<\/h2>\n\n\n\n<p>Let\u2019s walk through a <strong>simple CPU + GC investigation<\/strong> of a .NET app called <code>Orders.Api.exe<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5.1. Prepare<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Download <code>PerfView.exe<\/code> to <code>C:\\tools\\PerfView<\/code>. ()<\/li>\n\n\n\n<li>Create a working folder, e.g. <code>C:\\perf-traces<\/code>.<\/li>\n\n\n\n<li>Run PerfView as Administrator.<\/li>\n\n\n\n<li>In PerfView, set <strong>Current Directory<\/strong> (top text box) to <code>C:\\perf-traces<\/code>.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">5.2. Quick CPU trace using <em>Collect \u2192 Run<\/em><\/h3>\n\n\n\n<p>Best for <strong>short-lived EXEs or repeatable console scenarios<\/strong>. ()<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>In PerfView menu: <strong>Collect \u2192 Run<\/strong>.<\/li>\n\n\n\n<li>For <em>Command<\/em>: <code>C:\\MyApp\\Orders.Api.exe<\/code> (or your app).<\/li>\n\n\n\n<li>Click <strong>Start<\/strong>.<\/li>\n\n\n\n<li>PerfView:\n<ul class=\"wp-block-list\">\n<li>Starts ETW capture<\/li>\n\n\n\n<li>Launches your command<\/li>\n\n\n\n<li>Stops when the process exits<\/li>\n\n\n\n<li>Automatically opens the stack viewer<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p>This is ideal for development-time profiling of small repros.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5.3. CPU trace on a long-running service \u2013 <em>Collect \u2192 Collect<\/em><\/h3>\n\n\n\n<p>For ASP.NET\/Windows services, you can\u2019t easily \u201cwrap\u201d the process, so use <strong>Collect<\/strong>. ()<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Menu: <strong>Collect \u2192 Collect<\/strong>.<\/li>\n\n\n\n<li>In the dialog:\n<ul class=\"wp-block-list\">\n<li><strong>Collect<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Check <strong>CPU Samples<\/strong>.<\/li>\n\n\n\n<li>Check <strong>ThreadTime<\/strong> if you want wall-clock per thread.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Zip<\/strong>, <strong>Merge<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Check both if you plan to send the trace to someone else. ()<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Optionally, click <strong>Advanced Options<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Add extra providers (e.g. Business Central <code>Microsoft-DynamicsNAV-Server:0xC<\/code>). ()<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Click <strong>Start Collection<\/strong>.<\/li>\n\n\n\n<li>Exercise your scenario (e.g., hit <code>\/api\/orders<\/code> with load).<\/li>\n\n\n\n<li>Click <strong>Stop Collection<\/strong>.<\/li>\n<\/ol>\n\n\n\n<p>PerfView creates <code>PerfViewData.etl<\/code> and, if zipped, <code>PerfViewData.etl.zip<\/code> in current directory. ()<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5.4. Analyzing CPU Stacks<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>In the left tree, expand <code>PerfViewData.etl.zip<\/code> \u2192 <code>PerfViewData.etl<\/code>.<\/li>\n\n\n\n<li>Double-click <strong>CPU Stacks<\/strong>.<\/li>\n\n\n\n<li>In the <strong>Process<\/strong> dialog:\n<ul class=\"wp-block-list\">\n<li>Choose <code>Orders.Api<\/code> (or your process).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>You now see:\n<ul class=\"wp-block-list\">\n<li><code>By Name<\/code> view: methods sorted by <strong>inclusive CPU cost<\/strong>.<\/li>\n\n\n\n<li>Columns: <strong>Inc %<\/strong>, <strong>Exc %<\/strong>, <strong>Calls<\/strong>, etc.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p>Recommended first actions (from User\u2019s Guide): ()<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Check there are at least <strong>1000\u20135000 samples<\/strong> for your process.<\/li>\n\n\n\n<li>Confirm your process is actually CPU-bound (look at the \u201cWhen\u201d column).<\/li>\n\n\n\n<li>Ensure symbol resolution is working (no <code>?<\/code> names for important frames).<\/li>\n<\/ul>\n\n\n\n<p>Then:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use <strong>GroupPats<\/strong> and <strong>Fold % (F7)<\/strong> to collapse uninteresting modules and small nodes to focus on major costs. ()<\/li>\n\n\n\n<li>Double-click a method or right-click \u2192 <strong>Drill Into<\/strong> to zoom into only the samples involving that method. ()<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">5.5. Quick GC Overview<\/h3>\n\n\n\n<p>From the same trace:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Double-click <strong>GCStats<\/strong> under the trace node. ()<\/li>\n\n\n\n<li>Look for:\n<ul class=\"wp-block-list\">\n<li>Total <strong>% Time in GC<\/strong>.<\/li>\n\n\n\n<li>Number and duration of Gen 2 &amp; LOH collections.<\/li>\n\n\n\n<li>Trend of heap size over time.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>This quickly shows whether GC is a big part of your problem.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">6. Step-by-Step: Memory Leak \/ High Memory<\/h2>\n\n\n\n<p>Scenario: <code>Orders.Api<\/code> uses more and more memory until the process is huge.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6.1. Taking heap snapshots from a running process (GUI)<\/h3>\n\n\n\n<p>Workflow summarized from well-known PerfView memory leak tutorials: ()<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>In PerfView menu: <strong>Memory \u2192 Take Heap Snapshot<\/strong>.<\/li>\n\n\n\n<li>Select <code>Orders.Api<\/code> from the process list.<\/li>\n\n\n\n<li>Click <strong>Dump GC Heap<\/strong>.<\/li>\n\n\n\n<li>Wait while PerfView captures the GC heap \u2192 a <code>.gcDump<\/code> file appears in the tree.<\/li>\n\n\n\n<li>Double-click the <code>.gcDump<\/code> \u2192 <strong>Heap Stacks<\/strong>.<\/li>\n<\/ol>\n\n\n\n<p>In <strong>Heap Stacks<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>By default you see types sorted by total size, e.g. <code>System.String<\/code>, <code>MyApp.OrderCache<\/code>, etc.<\/li>\n\n\n\n<li>You can switch between:\n<ul class=\"wp-block-list\">\n<li><code>By Name<\/code> (grouped by type)<\/li>\n\n\n\n<li><code>By Size Stack<\/code> (grouped by allocation roots \/ owners)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">6.2. Compare two heap snapshots (diff)<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Let the app run; memory grows.<\/li>\n\n\n\n<li>Take a <strong>second<\/strong> heap snapshot the same way.<\/li>\n\n\n\n<li>With both heap stacks open, use <strong>Diff<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Choose first snapshot as baseline.<\/li>\n\n\n\n<li>Generate a diff view.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p>Diff columns show <strong>how much each type changed<\/strong> between snapshots (bytes &amp; percentage). ()<\/p>\n\n\n\n<p>Typical interpretation:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Types with <strong>large positive growth<\/strong> are likely leak candidates.<\/li>\n\n\n\n<li>Drill into their stacks to see <strong>who is holding references<\/strong>.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">6.3. Heap snapshot from a dump (Windows or Linux)<\/h3>\n\n\n\n<p>If you have a dump \/ core dump:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Memory \u2192 Take Heap Snapshot From Dump<\/code>\n<ul class=\"wp-block-list\">\n<li>Input: dump file (e.g. <code>core.1234<\/code> or <code>app.dmp<\/code>)<\/li>\n\n\n\n<li>Output: <code>.gcDump<\/code> file<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Then analyze it with <strong>Heap Stacks<\/strong> exactly like live snapshot. ()<\/li>\n<\/ul>\n\n\n\n<p>This is useful for production crash dumps or Linux <code>.core<\/code> files.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">7. Command-Line Usage \u2013 Basics to Advanced<\/h2>\n\n\n\n<p>PerfView has a powerful CLI for automation and headless collection. Most of it boils down to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Commands<\/strong>: <code>run<\/code>, <code>collect<\/code>, <code>start<\/code>, <code>stop<\/code>, <code>abort<\/code>, <code>HeapSnapshot<\/code>, etc.<\/li>\n\n\n\n<li><strong>Qualifiers<\/strong>: <code>\/LogFile<\/code>, <code>\/MaxCollectSec<\/code>, <code>\/StopOnPerfCounter<\/code>, <code>\/GCOnly<\/code>, etc.<\/li>\n<\/ul>\n\n\n\n<p>PerfView\u2019s User\u2019s Guide has a dedicated section on <strong>Collecting Data from the Command Line<\/strong> and a <strong>Command Line Reference<\/strong>. ()<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">7.1. PerfView <code>run<\/code> \u2013 wrap an executable<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">PerfView<\/span> <span class=\"hljs-selector-tag\">run<\/span> <span class=\"hljs-selector-tag\">C<\/span>:\\<span class=\"hljs-selector-tag\">MyApp<\/span>\\<span class=\"hljs-selector-tag\">Orders<\/span><span class=\"hljs-selector-class\">.Api<\/span><span class=\"hljs-selector-class\">.exe<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Starts collection, runs the EXE, and opens the viewer as soon as app exits. ()<\/li>\n\n\n\n<li>Great for <strong>development-time<\/strong> profiling of small, repeatable scenarios.<\/li>\n<\/ul>\n\n\n\n<p>Common variation (headless, scripted):<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">PerfView \/LogFile=PerfViewRun.log \/AcceptEula \/NoView run C:\\MyApp\\Orders.Api.exe\n<\/code><\/span><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li><code>\/LogFile=...<\/code> \u2192 no GUI; log messages to file. ()<\/li>\n\n\n\n<li><code>\/AcceptEula<\/code> \u2192 auto-accept license on first run (important for CI). ()<\/li>\n\n\n\n<li><code>\/NoView<\/code> \u2192 don\u2019t open viewer after collection. ()<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">7.2. PerfView <code>collect<\/code> \u2013 system-wide logging<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">PerfView collect\n<\/code><\/span><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Starts system-wide logging and pops a small console so you can stop collection manually.<\/li>\n\n\n\n<li>Typically used when profiling <strong>services \/ ASP.NET \/ server scenarios<\/strong> where you want to control start\/stop. ()<\/li>\n<\/ul>\n\n\n\n<p>Add useful qualifiers:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">PerfView \/LogFile=PerfViewCollect.log \/AcceptEula \/MaxCollectSec:10 collect\n<\/code><\/span><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Collect for <strong>10 seconds<\/strong> max, then stop automatically. ()<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">7.3. <code>start<\/code>, <code>stop<\/code>, <code>abort<\/code> \u2013 multi-step scripts<\/h3>\n\n\n\n<p>Useful when you want to:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Start tracing.<\/li>\n\n\n\n<li>Run some scenario via script.<\/li>\n\n\n\n<li>Stop tracing afterwards.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">PerfView start \/AcceptEula \/LogFile=PerfViewCollect.log\nREM Run workload here\u2026\nPerfView stop \/AcceptEula \/LogFile=PerfViewCollect.log\n<\/code><\/span><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li><code>start<\/code> begins logging.<\/li>\n\n\n\n<li><code>stop<\/code> stops logging and writes ETL.<\/li>\n\n\n\n<li><code>abort<\/code> can be used to <em>ensure<\/em> no PerfView session remains running (cleanup). ()<\/li>\n<\/ul>\n\n\n\n<p>Use with care: if the script fails between <code>start<\/code> and <code>stop<\/code>, logging could remain on, so <code>abort<\/code> is your safety net.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">7.4. Heap snapshot from CLI<\/h3>\n\n\n\n<p>From the maintainers\u2019 discussion: ()<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">PerfView<\/span> <span class=\"hljs-selector-tag\">HeapSnapshot<\/span> <span class=\"hljs-selector-tag\">Orders<\/span><span class=\"hljs-selector-class\">.Api<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>or<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">PerfView<\/span> <span class=\"hljs-selector-tag\">HeapSnapshot<\/span> 12345 <span class=\"hljs-selector-tag\">OrdersApiLeak<\/span><span class=\"hljs-selector-class\">.gcdump<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>First parameter: process ID or process name (without <code>.exe<\/code>).<\/li>\n\n\n\n<li>Optional second parameter: output file name.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">7.5. GC-focused collection: <code>\/GCOnly<\/code> and <code>\/GCCollectOnly<\/code><\/h3>\n\n\n\n<p>PerfView has special modes for long-term GC monitoring:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>GC Only<\/strong> \u2013 GC allocations plus some memory info, but not all other events. Good for hour-long traces. ()<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">PerfView \/GCOnly collect\n<\/code><\/span><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li><strong>GC Collect Only<\/strong> \u2013 only GC collection events (no allocation sampling). Good for day-long traces. ()<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">PerfView \/GCCollectOnly collect\n<\/code><\/span><\/pre>\n\n\n<p>These drastically reduce trace size, letting you monitor GC behavior over long periods (hours\/days).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">7.6. .NET allocation and call events: <code>\/DotNetAlloc<\/code>, <code>\/DotNetAllocSampled<\/code>, <code>\/DotNetCalls<\/code><\/h3>\n\n\n\n<p>From the User\u2019s Guide: ()<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>\/DotNetAlloc<\/code>\n<ul class=\"wp-block-list\">\n<li>Log an event for <strong>every<\/strong> managed allocation.<\/li>\n\n\n\n<li>High overhead, can lose events under heavy load.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><code>\/DotNetAllocSampled<\/code>\n<ul class=\"wp-block-list\">\n<li>Sampled allocations (much lower overhead).<\/li>\n\n\n\n<li>Recommended over full allocation logging.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><code>\/DotNetCalls<\/code>\n<ul class=\"wp-block-list\">\n<li>Event on <strong>every .NET method entry<\/strong> (no inlined methods).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><code>\/DotNetCallsSampled<\/code>\n<ul class=\"wp-block-list\">\n<li>Sampled version (1 in ~997 calls).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><code>\/DisableInlining<\/code>\n<ul class=\"wp-block-list\">\n<li>Turn off JIT inlining so you see every call (again, high overhead).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>Example: sample allocation-heavy parts of your app:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">PerfView \/DotNetAllocSampled \/GCOnly \/MaxCollectSec:30 collect\n<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">7.7. Kernel and .NET event selection: <code>\/KernelEvents<\/code>, <code>\/ClrEvents<\/code><\/h3>\n\n\n\n<p>You can tune ETW data volume by adjusting kernel and CLR event sets. ()<\/p>\n\n\n\n<p>Examples:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Disable most kernel events except minimal base:<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">PerfView \/KernelEvents=None collect\n<\/code><\/span><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Turn on kernel memory and VirtualAlloc events:<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">PerfView \/KernelEvents=<span class=\"hljs-keyword\">default<\/span>+Memory+VirtualAlloc+VAMap collect\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Disable all .NET runtime events:<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">PerfView \/ClrEvents=None collect\n<\/code><\/span><\/pre>\n\n\n<p>Or start with GC events only:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">PerfView \/ClrEvents=GC+Stack collect\n<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">7.8. Production \u201cflight recorder\u201d triggers<\/h3>\n\n\n\n<p>PerfView has <strong>\/StopOn<\/strong>* and <strong>\/MonitorPerfCounter<\/strong> qualifiers that turn it into a smart flight recorder. ()<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Stop when a perf counter crosses a threshold \u2013 <code>\/StopOnPerfCounter<\/code><\/h4>\n\n\n\n<p>Syntax (similar to PerfMon):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">PerfView collect <span class=\"hljs-string\">\"\/StopOnPerfCounter:CATEGORY:COUNTER:INSTANCE OP NUM\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Example: stop when global <code>% Time in GC<\/code> &gt; 20%:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">PerfView collect <span class=\"hljs-string\">\"\/StopOnPerfCounter:.NET CLR Memory:% Time in GC:_Global_&gt;20\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Example: stop when machine committed bytes &gt; 50 GB:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">PerfView collect <span class=\"hljs-string\">\"\/StopOnPerfCounter:Memory:Committed Bytes:&gt;50000000000\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Log perf counters into ETL \u2013 <code>\/MonitorPerfCounter<\/code><\/h4>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">PerfView <span class=\"hljs-string\">\"\/MonitorPerfCounter=Memory:Available MBytes:@10\"<\/span> collect\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Logs Available MBytes every 10 seconds as events in the trace. ()<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Stop on long HTTP request \u2013 <code>\/StopOnRequestOverMSec<\/code><\/h4>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">PerfView collect <span class=\"hljs-string\">\"\/StopOnRequestOverMSec:2000\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Stops when any IIS\/ASP.NET request takes longer than 2000 ms. ()<\/li>\n<\/ul>\n\n\n\n<p>Add <code>\/CollectMultiple:N<\/code> to capture multiple slow cases:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">PerfView collect <span class=\"hljs-string\">\"\/StopOnRequestOverMSec:2000\"<\/span> \/CollectMultiple:<span class=\"hljs-number\">3<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Stop on Event Log message \u2013 <code>\/StopOnEventLogMessage<\/code><\/h4>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">PerfView collect <span class=\"hljs-string\">\"\/StopOnEventLogMessage:MyErrorPattern\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Stops when a Windows Application log message matches the regex <code>MyErrorPattern<\/code>. ()<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Stop on exception \u2013 <code>\/StopOnException<\/code><\/h4>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">PerfView collect <span class=\"hljs-string\">\"\/StopOnException:ApplicationException\"<\/span> \/Process:Orders.Api \/ThreadTime\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>or more specific:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">PerfView collect <span class=\"hljs-string\">\"\/StopOnException:FileNotFound.*Foo.dll\"<\/span> \/ThreadTime\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Uses .NET regex to match exception type\/message. ()<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Multiple triggers and multiple captures<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>\/CollectMultiple:N<\/code> \u2192 keep collecting until N triggers hit, generating files <code>PerfViewData.etl.zip<\/code>, <code>PerfViewData.1.etl.zip<\/code>, etc. ()<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">8. PerfViewCollect and Containers \/ NanoServer<\/h2>\n\n\n\n<p>For <strong>Windows Server Core \/ containers \/ NanoServer<\/strong>, PerfView supports:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Running normal <code>PerfView.exe<\/code> in Windows Server Core containers (with caveats) using CLI only. ()<\/li>\n\n\n\n<li>A special <code>PerfViewCollect<\/code> tool (no GUI, .NET Core self-contained) which you build from source and run like:<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">PerfViewCollect.exe \/LogFile=log.txt \/MaxCollectSec=30 collect\n<\/code><\/span><\/pre>\n\n\n<p>It uses the <strong>same CLI<\/strong> as PerfView.exe but works where the full desktop runtime isn\u2019t available. ()<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">9. Advanced Workflows &amp; Best Practices<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">9.1. General CPU optimization workflow (summary of User\u2019s Guide) ()<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Confirm <strong>CPU is the bottleneck<\/strong> (not I\/O or waiting).<\/li>\n\n\n\n<li>Ensure you have <strong>enough samples<\/strong> (1000+).<\/li>\n\n\n\n<li>Start with <strong>ByName<\/strong> bottom-up view, group modules into <strong>\u201cJust My Code\u201d<\/strong> vs framework.<\/li>\n\n\n\n<li>Use <strong>Fold %<\/strong> and manual folding to hide noise.<\/li>\n\n\n\n<li>Identify top inclusive methods; drill into them.<\/li>\n\n\n\n<li>Apply optimizations; re-collect and compare.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">9.2. Memory \/ GC optimization workflow ()<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Run a <strong>GCOnly<\/strong> or normal trace to check if GC is actually expensive.<\/li>\n\n\n\n<li>If GC is high or memory grows:\n<ul class=\"wp-block-list\">\n<li>Capture heap snapshots over time (live or from dumps).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Use Heap Stacks in <strong>diff mode<\/strong> to find growing types.<\/li>\n\n\n\n<li>Examine their reference chains to find leak roots (e.g. static caches, event handlers).<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">9.3. Using PerfView with ASP.NET Core on Linux<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>On Linux, you can use <strong>PerfCollect<\/strong> (bash script) + native tools (<code>perf<\/code>, <code>LTTng<\/code>) to collect traces that can be analyzed in PerfView on Windows. ()<\/li>\n<\/ul>\n\n\n\n<p>Typical pattern:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>On Linux: <code>perfcollect collect mytrace<\/code>.<\/li>\n\n\n\n<li>Copy resulting trace to Windows.<\/li>\n\n\n\n<li>Open in PerfView to inspect CPU &amp; .NET events.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">10. Quick Command Cheat Sheet<\/h2>\n\n\n\n<p>Here\u2019s a condensed set you can turn into your own cheatsheet:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\"># Basic dev run<\/span>\nPerfView run C:\\MyApp\\Orders.Api.exe\n\n<span class=\"hljs-comment\"># System-wide trace, 20 seconds, headless<\/span>\nPerfView \/LogFile=collect.log \/AcceptEula \/MaxCollectSec:<span class=\"hljs-number\">20<\/span> collect\n\n<span class=\"hljs-comment\"># Heap snapshot from running process<\/span>\nPerfView HeapSnapshot Orders.Api OrdersApiLeak.gcdump\n\n<span class=\"hljs-comment\"># GC only, 1-hour flight recorder, stop when % Time in GC &gt; 20%<\/span>\nPerfView \/GCOnly collect `\n  <span class=\"hljs-string\">\"\/StopOnPerfCounter:.NET CLR Memory:% Time in GC:_Global_&gt;20\"<\/span> `\n  \/LogFile=gcflight.log \/AcceptEula\n\n<span class=\"hljs-comment\"># ASP.NET slow request &gt; 5s (collect 3 examples)<\/span>\nPerfView collect <span class=\"hljs-string\">\"\/StopOnRequestOverMSec:5000\"<\/span> \/CollectMultiple:<span class=\"hljs-number\">3<\/span>\n\n<span class=\"hljs-comment\"># Stop when ApplicationException thrown in MyService<\/span>\nPerfView collect <span class=\"hljs-string\">\"\/StopOnException:ApplicationException\"<\/span> \/Process:MyService \/ThreadTime\n\n<span class=\"hljs-comment\"># Log memory available every 10s<\/span>\nPerfView <span class=\"hljs-string\">\"\/MonitorPerfCounter=Memory:Available MBytes:@10\"<\/span> collect\n\n<span class=\"hljs-comment\"># Automated CLI-only run for profiling tutorial.exe<\/span>\nPerfView \/LogFile=PerfViewRun.log \/AcceptEula \/NoView run tutorial.exe\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">11. Final summary<\/h2>\n\n\n\n<p>If you remember only a few things:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>PerfView<\/strong> = serious <strong>.NET CPU + GC + ETW<\/strong> profiler, production-friendly, scriptable, and trusted by Microsoft\u2019s own teams. ()<\/li>\n\n\n\n<li>Use <strong>Collect \u2192 Run<\/strong> or <code>PerfView run<\/code> for test apps, <strong>Collect \u2192 Collect<\/strong> or <code>PerfView collect<\/code> for services.<\/li>\n\n\n\n<li>Learn <strong>CPU Stacks<\/strong>, <strong>CallTree<\/strong>, <strong>GCStats<\/strong>, and <strong>Heap Stacks<\/strong>\u2014those four views solve 80% of perf problems. ()<\/li>\n\n\n\n<li>For automation and production:\n<ul class=\"wp-block-list\">\n<li><code>run<\/code>, <code>collect<\/code>, <code>HeapSnapshot<\/code>, <code>\/LogFile<\/code>, <code>\/MaxCollectSec<\/code>, <code>\/StopOn*<\/code> triggers, <code>\/GCOnly<\/code>, <code>\/GCCollectOnly<\/code>.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>PerfView is basically the Swiss-army knife for .NET performance\u2014CPU, GC, memory, thread time, and arbitrary ETW events\u2014all in one (slightly ugly but insanely powerful) tool. Let\u2019s turn this into the&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[11138],"tags":[],"class_list":["post-54196","post","type-post","status-publish","format-standard","hentry","category-best-tools"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/54196","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=54196"}],"version-history":[{"count":1,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/54196\/revisions"}],"predecessor-version":[{"id":54197,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/54196\/revisions\/54197"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=54196"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=54196"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=54196"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}