1. What is dotTrace?
Definition
- dotTrace is a .NET performance profiler from JetBrains.
- It supports:
- .NET Framework, .NET Core, modern .NET
- ASP.NET / ASP.NET Core (IIS, Kestrel)
- Desktop (WPF, WinForms, Windows Services)
- Unity / Mono
- Remote and command-line scenarios. ()
What it actually does
- Hooks into your process and samples/traces function calls.
- Collects data like:
- Which methods ran
- How many times
- How much CPU time and wall-clock time they consumed
- How threads were blocked, waiting or contending for resources (Timeline mode).
- Produces a snapshot file which you open in dotTrace Viewer (stand-alone, Rider, or Visual Studio integration) and analyze using:
- Call Tree / Hotspots
- Threads / Timeline view
- Filters (by thread, time range, namespace, etc.). ()
Profiling modes (high level)
- Sampling – low overhead, good for finding hot methods (CPU).
- Tracing – higher overhead, more precise call details.
- Line-by-line – very detailed but expensive; used on small scopes.
- Timeline – shows CPU, async, GC, I/O, blocking, context switching over time; great for ASP.NET, services, UI freezes. ()
2. Why and When to Use dotTrace
Why use dotTrace?
Use dotTrace when you need answers to questions like:
- “Why is this request taking 2 seconds instead of 100 ms?”
- “Which method is burning the CPU?”
- “Why does my WPF UI freeze for 3 seconds when I click this button?”
- “Is my app blocked on I/O, locks, or GC?”
Typical problems it helps you solve:
- Slow HTTP endpoints / APIs
- High CPU usage on servers or background services
- Long-running batch jobs
- UI freezes / jank in WPF/WinForms
- Thread contention, lock issues, sync-over-async
- Excessive database or network calls (e.g., N+1 queries).
When to use (scenarios in lifecycle)
- During development
- New feature feels slow → profile locally before even committing.
- On a performance test / staging environment
- Performance tests show regressions → run dotTrace against test environment.
- On production (carefully)
- Use Timeline or sampling mode with as little overhead as possible.
- Or collect snapshots using dotTrace command line / self-profiling API and download the snapshot for analysis offline. ()
3. How dotTrace Works (Conceptual Model)
- You start a profiling session:
- From standalone dotTrace, Visual Studio, or Rider, or via command line. ()
- You run or attach to the target:
- Start a new process (standalone app, web app) or
- Attach to an already running .NET process.
- dotTrace collects a snapshot while you reproduce the problem.
- You stop or detach → snapshot is saved.
- You open the snapshot in dotTrace Viewer and:
- Navigate hotspots
- Drill down into call stacks and threads
- Filter by thread, time range, namespace, or method.
- You change code based on findings, redeploy, and re-profile to verify improvement.
4. How to Install dotTrace
4.1 Options
You can get dotTrace in several ways: ()
- JetBrains Toolbox (recommended)
- Install JetBrains Toolbox.
- From Toolbox, install dotTrace as a standalone tool.
- Part of ReSharper Ultimate / Rider
- If you use ReSharper in Visual Studio or Rider, dotTrace profiling is integrated.
- Standalone installer
- Download installer from JetBrains dotTrace site (32/64-bit).
- dotTrace Command Line Tools
- Free redistributable console profiler, useful for CI, servers, and automation. ()
4.2 Basic installation steps (Windows)
- Go to JetBrains profiler site and download dotTrace installer. ()
- Run installer (requires admin privileges).
- Follow wizard → choose:
- Standalone dotTrace
- Integration with Visual Studio (if ReSharper installed).
- Finish and launch dotTrace from:
- Start Menu → JetBrains → dotTrace, or
- JetBrains Toolbox.
(For Rider/VS integration, dotTrace features appear in menus like ReSharper | Profile or Rider’s Run | Profile.)
5. Step-by-Step: Using dotTrace to Troubleshoot an App
I’ll structure this as a concrete lab you can reuse in training:
We’ll assume:
- .NET 6/7/8 API:
Orders.Api.exe(or any app) - Running on Windows, profiling locally
- Using Standalone dotTrace + Timeline mode (good for web apps).
You can adapt the same logic for WPF, ASP.NET under IIS, services, etc. The run configuration types differ but the flow is identical. ()
Step 0 – Prepare
- Install dotTrace.
- Build your app in Release configuration.
- Have a clear repro scenario:
- Example: calling
/api/orders?customerId=123is slow.
- Example: calling
Step 1 – Start dotTrace
Standalone mode (recommended for generic training): ()
- Open JetBrains Toolbox.
- Click dotTrace.
- You’ll see the Home window with “New Process Run / Attach to Process / …”.
Visual Studio mode (if you prefer integrated):
- Open your solution in Visual Studio.
- Use menu: ReSharper | Profile | Run Startup Configuration Performance Profiling…. ()
(For your training, show both once; then standardize on standalone to keep steps universal.)
Step 2 – Create a Run Configuration
This tells dotTrace how to run your app. ()
- In dotTrace Home → under New Process Run, click Add run configuration.
- Choose application type:
- For console / worker / self-hosting web → “.NET and .NET Core”.
- For IIS/IIS Express → choose IIS or IIS Express.
- For Windows service, WCF, etc. there are dedicated types.
- For .NET/.NET Core:
- Path to executable: e.g.
C:\Apps\Orders.Api\Orders.Api.exe- Or the
dllif framework-dependent deployment.
- Or the
- Command-line arguments (if any).
- Working directory: usually where your exe/dll lives.
- Any environment variables if needed (connection strings, ASPNETCORE_ENVIRONMENT, etc.).
- Path to executable: e.g.
Save the configuration as Orders.Api – Timeline.
Step 3 – Choose Profiling Type and Options
Decide what you want to see vs overhead.
For web/API performance:
- Profiling type: choose Timeline.
- (Optional) Adjust:
- Sampling rate – trade-off between detail and snapshot size.
- Process filters – to focus only on your process (exclude child processes).
- Scope – if there are multiple processes (IIS w3wp, etc.).
For a basic first run, keep defaults and use Timeline.
Step 4 – Start Profiling Session
- From dotTrace Home, select your run configuration (
Orders.Api – Timeline). - Click Run (or Run | Local).
- dotTrace:
- Starts your app.
- Opens the profiling controller window (a separate small window). ()
In the controller you’ll see buttons like:
- Get Snapshot and Start / Get Snapshot and Save
- Detach
- Kill Process
Step 5 – Reproduce the Problem Under Profiling
With your app now under profiler:
- Use your test client:
curl, Postman, browser, or load test tool.
- Hit the problematic endpoint:
- e.g.,
GET /api/orders?customerId=1235–10 times, or trigger your scenario.
- e.g.,
- Watch for the app to behave slowly as usual (you’re now capturing profiling data for that period).
Step 6 – Capture a Snapshot
While the issue is being reproduced:
- In the controller window, click:
- Get Snapshot (wording may differ slightly; e.g., “Get Snapshot and Wait”). ()
- dotTrace:
- Freezes collection momentarily
- Saves a snapshot file (.dtp / .dt).
- You can:
- Continue profiling (take multiple snapshots for different scenarios), or
- Detach / Stop to end the session.
Once done, stop the app OR detach the profiler.
Step 7 – Open Snapshot in dotTrace Viewer
If you used standalone dotTrace, it automatically opens dotTrace Viewer with your snapshot. ()
You’ll see:
- Overview of the snapshot
- Thread list and timeline (for Timeline mode)
- Options to switch to:
- Call Tree
- Top Methods / Hotspots
- Events (GC, I/O, etc.)
Step 8 – Basic Analysis Workflow (Timeline)
The core training story: “Follow the time”.
- Identify the time range of the slow operation
- In Timeline view, find the spike where CPU or execution for relevant thread is high.
- You can zoom/select a time range.
- Filter to relevant threads
- For ASP.NET Core, you often look at thread pool worker threads handling requests.
- Open Call Tree / Hotspots for that range
- Switch to Call Tree or Top Methods filtered by your time selection.
- Sort by “Self Time” or “Total Time”
- Self Time = method’s own work
- Total Time = method + callees
- Drill down
- Find your controller or service methods (e.g.,
OrdersController.GetOrders) - Expand down the call tree:
- Look for heavy LINQ, EF calls, repeated DB queries, large JSON serialization, or blocking I/O.
- Find your controller or service methods (e.g.,
Examples of what you might find:
OrdersRepository.GetOrdersByCustomercalling EF’sToList()in a loop.HttpClient.GetAsyncorTask.Wait()causing sync-over-async.Thread.Sleepor expensive logging.
From here you can create a story:
“The
/api/ordersrequest spends 800 ms inGetOrdersByCustomer, mostly on N+1 EF queries; optimizing this to a single query or adding caching should reduce latency.”
Step 9 – Repeat: Optimize and Re-profile
dotTrace is most valuable when you use it iteratively:
- Apply code changes:
- Optimize queries, add caching, reduce allocations, switch to async, remove redundant work, etc.
- Rebuild and rerun the app.
- Repeat Steps 1–8.
- Compare snapshots before & after:
- dotTrace can help compare snapshots to see improvements.
6. Step-by-Step Scenario: UI Freeze in WPF/WinForms (Quick Outline)
dotTrace has dedicated guidance for UI freezes. ()
- Start dotTrace (Timeline or sampling mode).
- Run your WPF/WinForms app.
- Reproduce UI freeze (click the button that hangs).
- In Timeline:
- Filter by UI thread.
- Look for time where UI thread is Running but not pumping messages (or blocked).
- Analyze call stack on UI thread during freeze:
- Find heavy work: DB call, file I/O, or heavy CPU loops.
- Move that work off UI thread:
- Use
async/await, background worker,Task.Run, etc.
- Use
- Re-profile to confirm UI remains responsive.
7. dotTrace Command Line & Self-Profiling (Advanced)
For automation and production-like environments, you may not want to open GUI.
Command line profiler
JetBrains provides dotTrace command line tools: ()
dotTrace start– run or attach to a process.- Control profiling via stdin/file messages like:
##dotTrace["get-snapshot"]##dotTrace["disconnect"]
- Output is snapshot files which you open later in the GUI.
This is perfect for:
- CI pipelines (run performance tests + profile).
- Remote servers (scripted profiling during a specific test window).
JetBrains Profiler API / Self-Profiling API
You can also trigger profiling from inside your code with the JetBrains Profiler API / Self-Profiling API: ()
- Add
JetBrains.Profiler.ApiNuGet package. - From your code, call methods that:
- Attach profiler,
- Start collecting data,
- Save snapshot.
- Allows collecting snapshots from environments where full profiler isn’t installed.
Great for:
- Capturing performance snapshots on customer environments.
- Rare production bugs that only show up in their environment.
8. What to Take Away from dotTrace for Your Apps
When you finish a dotTrace session, you should come out with concrete, actionable insights, not just screenshots.
Key “takeaways” per session
- Top 5 slowest operations
- Methods or call chains with highest Total Time.
- Root causes
- “CPU bound in algorithm X”
- “Blocked on DB query Y”
- “Stuck on lock in Z”
- Code paths to change
- Exact namespaces/classes/methods for developers to optimize.
- Before/After metrics
- Latency of key operation before (e.g. 2.5s) vs after optimization (e.g. 200 ms).
- CPU usage before vs after.
Things you typically log into your JIRA/issue:
- DotTrace snapshot file name/path.
- Screenshot of call tree/hotspots with highlighted methods.
- Short text summary:
- “During
/api/orderscall, 83% of time is spent inOrderService.GetOrderLinesdue to N+1 EF query pattern.”
- “During
- Suggested fixes:
- “Replace per-line query with
Includeor custom join; consider caching static configuration data.”
- “Replace per-line query with
9. Why dotTrace is So Useful Compared to Other Options
- Deep integration with Rider / ReSharper / Visual Studio. ()
- Multiple profiling modes (Sampling, Tracing, Line-by-line, Timeline).
- Supports modern .NET, Unity, Mono, Unreal etc., and keeps getting updated with new presets and OS support. ()
- Great Timeline UI:
- See CPU, async, GC, I/O, thread states all in one place.
- Strong filtering and navigation:
- By thread, namespace, method, time range, etc.
- Command line + API options for automation.
- Good official docs and videos: quick start, timeline tutorials, FAQ, etc. ()
10. Best Practices & Tips (for your training material)
You can turn this into a checklist slide.
- Always profile Release builds, not Debug.
- Warm up the app:
- Run it once before capturing snapshot to avoid JIT noise.
- Profile one scenario at a time:
- Take separate snapshots for different use cases (login, search, checkout).
- Keep snapshots small and focused:
- Start profiling just before reproducing issue; stop right after.
- Prefer Timeline for servers, Sampling/Timeline for desktop.
- Don’t trust intuition alone:
- Use dotTrace data to confirm where time is really spent.
- Repeat after changes:
- Always verify performance improvements with a new snapshot.
- Document findings:
- Save snapshots and summary to your performance wiki / JIRA.
- Combine with other tools:
- dotTrace for code-level performance,
- dotMemory for memory leaks/allocations,
- dotnet-counters / PerfMon for runtime metrics,
- APM tools for production telemetry.
I’m a DevOps/SRE/DevSecOps/Cloud Expert passionate about sharing knowledge and experiences. I have worked at Cotocus. I share tech blog at DevOps School, travel stories at Holiday Landmark, stock market tips at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at TrueReviewNow , and SEO strategies at Wizbrand.
Do you want to learn Quantum Computing?
Please find my social handles as below;
Rajesh Kumar Personal Website
Rajesh Kumar at YOUTUBE
Rajesh Kumar at INSTAGRAM
Rajesh Kumar at X
Rajesh Kumar at FACEBOOK
Rajesh Kumar at LINKEDIN
Rajesh Kumar at WIZBRAND