Section 6 of 6

Profiling Tools

🎯 What You'll Learn

  • MiniProfiler
  • Application Insights
  • dotnet-trace
  • BenchmarkDotNet
  • SQL Server Profiler

MiniProfiler

Lightweight profiler for ASP.NET Core applications.

Install Package Bash
dotnet add package MiniProfiler.AspNetCore.Mvc
dotnet add package MiniProfiler.EntityFrameworkCore
Program.cs C#
builder.Services.AddMiniProfiler(options =>
{
    options.RouteBasePath = "/profiler";
}).AddEntityFramework();

var app = builder.Build();

app.UseMiniProfiler();
_Layout.cshtml HTML
<head>
    <mini-profiler />
</head>

Application Insights

Azure's application performance management service.

Install Package Bash
dotnet add package Microsoft.ApplicationInsights.AspNetCore
Program.cs C#
builder.Services.AddApplicationInsightsTelemetry();
appsettings.json JSON
{
  "ApplicationInsights": {
    "InstrumentationKey": "your-key-here"
  }
}

dotnet-trace

Command-line tool for collecting performance traces.

Install Tool Bash
dotnet tool install --global dotnet-trace
Collect Trace Bash
# List processes
dotnet-trace ps

# Collect trace
dotnet-trace collect --process-id <PID>

BenchmarkDotNet

Powerful benchmarking library for .NET.

Install Package Bash
dotnet add package BenchmarkDotNet
Benchmark Example C#
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

[MemoryDiagnoser]
public class ProductBenchmarks
{
    private List<Product> _products;

    [GlobalSetup]
    public void Setup()
    {
        _products = Enumerable.Range(1, 1000)
            .Select(i => new Product { Id = i, Name = $"Product {i}" })
            .ToList();
    }

    [Benchmark]
    public List<Product> FilterWithWhere()
    {
        return _products.Where(p => p.Id > 500).ToList();
    }

    [Benchmark]
    public List<Product> FilterWithFor()
    {
        var result = new List<Product>();
        for (int i = 0; i < _products.Count; i++)
        {
            if (_products[i].Id > 500)
                result.Add(_products[i]);
        }
        return result;
    }
}

// Run benchmarks
BenchmarkRunner.Run<ProductBenchmarks>();

SQL Server Profiler

Monitor SQL queries generated by EF Core.

Enable Sensitive Data Logging C#
builder.Services.AddDbContext<InvenTrackDbContext>(options =>
{
    options.UseSqlServer(connectionString)
        .EnableSensitiveDataLogging() // Development only!
        .LogTo(Console.WriteLine, LogLevel.Information);
});

Performance Checklist

  • Cache frequently accessed data: Use in-memory or distributed caching
  • Use async/await: For I/O operations
  • Optimize queries: Use Include, AsNoTracking, projections
  • Enable response caching: For static content
  • Profile regularly: Use MiniProfiler or Application Insights
  • Monitor SQL: Check generated queries
  • Benchmark critical paths: Use BenchmarkDotNet

Key Takeaways

  • MiniProfiler: Lightweight profiling for dev
  • Application Insights: Production monitoring
  • dotnet-trace: Performance trace collection
  • BenchmarkDotNet: Micro-benchmarking
  • SQL logging: Monitor EF Core queries
  • Profile early: Find bottlenecks before production
🎉 Part XVII Complete!

Congratulations! You've completed Part XVII: Performance & Caching. You now understand:

  • ✅ In-memory caching (IMemoryCache, expiration, eviction)
  • ✅ Distributed caching (Redis, SQL Server, serialization)
  • ✅ Response caching ([ResponseCache], cache profiles)
  • ✅ Async best practices (async all the way, avoid blocking)
  • ✅ EF Core performance (Include, AsNoTracking, projections)
  • ✅ Profiling tools (MiniProfiler, Application Insights, BenchmarkDotNet)

Your applications are now fast and scalable! ⚡