Find the Best Cosmetic Hospitals

Explore trusted cosmetic hospitals and make a confident choice for your transformation.

โ€œInvest in yourself โ€” your confidence is always worth it.โ€

Explore Cosmetic Hospitals

Start your journey today โ€” compare options in one place.

DOTNET: Capstone Project for DOTNET Performance Optimization


1. Recommended GitHub Application

Chosen app: NimblePros/eShopOnWeb

Repo: https://github.com/NimblePros/eShopOnWeb (GitHub)

Why this one:

  • Official Microsoft reference app, now community-maintained by NimblePros.
  • ASP.NET Core MVC app (classic web app) + PublicApi project (API you can treat as โ€œmicroserviceโ€).
  • Uses Entity Framework Core with SQL Server support, with explicit steps to configure SQL Server in appsettings.json and apply EF migrations. (GitHub)
  • Main branch is currently ASP.NET Core 9.0. By the time .NET 10 is out, updating target frameworks will be straightforward; the project already tracks latest .NET versions. (GitHub)

Weโ€™ll treat:

  • src/Web = front-end web app
  • src/PublicApi = microservice/API (this is what youโ€™ll mainly hammer with k6, dotnet-counters, Datadog, etc.)

2. Capstone: High-Level Structure

Your โ€œDOTNET Performance Optimization Capstoneโ€ will use eShopOnWeb and walk students through:

  1. Setup & Run the App
    • Clone repo, configure SQL Server, run migrations, run Web + PublicApi.
  2. Baseline & Live Health
    • Use dotnet-counters to watch CPU, GC, allocations, thread pool.
    • Problem it solves: โ€œwhatโ€™s happening right now in this process?โ€
  3. CPU Profiling
    • Use dotTrace to find slow endpoints in PublicApi / Web.
    • Problem it solves: โ€œwhere is the time going?โ€
  4. Memory Profiling
    • Use dotMemory to detect high allocations, possible leaks.
    • Problem it solves: memory leaks, LOH bloat, allocation hotspots.
  5. Deep Runtime Analysis
    • Use PerfView on traces to understand GC, CPU, allocations in detail.
    • Problem it solves: advanced GC/CPU investigation (โ€œtruth machineโ€).
  6. Micro-benchmarks
    • Extract a core hot function into a separate class library and benchmark with BenchmarkDotNet.
    • Problem it solves: LINQ vs loops, Span vs array, etc.
  7. Load Testing
    • Use k6 to generate load on PublicApi (simulate catalog browse / add to basket).
    • Observe impact via dotnet-counters, PerfView, Datadog.
  8. Datadog Monitoring & Dashboard
    • Install Datadog Agent on Windows. (docs.datadoghq.com)
    • Install Datadog .NET Tracer for automatic instrumentation. (docs.datadoghq.com)
    • Create custom dashboard showing latency, errors, CPU, GC, SQL time.

Iโ€™ll now go step-by-step.


3. Step 0 โ€“ Prerequisites

On your Windows machine:

.NET & Tools

  • .NET SDK: Latest current (today thatโ€™s .NET 9; use 9.x SDK).
  • Visual Studio 2022 or Rider:
    • Workloads: ASP.NET and web development, .NET desktop development.
  • SQL Server:
    • SQL Server Developer Edition or SQL Server Express (localdb is fine).
  • Git.

Performance Tools

  • dotnet-counters (dotnet tool if not already included): dotnet tool install -g dotnet-counters
  • dotTrace & dotMemory: install via JetBrains Toolbox (or ReSharper Ultimate).
  • PerfView: download PerfView.exe from the official GitHub releases page.
  • BenchmarkDotNet: as a NuGet package (later, in your benchmark project).

Load Testing & Monitoring

  • k6 (Windows):
    • Follow official guide: download MSI or use choco install k6. (Grafana Labs)
  • Datadog account (trial is fine). (DEV Community)
  • Datadog Agent for Windows:
    • Download & install the Agent (MSI) from Datadog or use the datadog-installer-x86_64.exe. (docs.datadoghq.com)
  • Datadog .NET Tracer for automatic instrumentation of ASP.NET Core. (docs.datadoghq.com)

4. Step 1 โ€“ Clone & Run eShopOnWeb with SQL Server

4.1 Clone the repo

git clone https://github.com/NimblePros/eShopOnWeb.git
cd eShopOnWeb
Code language: PHP (php)

Solution files:

  • eShopOnWeb.sln โ€“ main solution.
  • Key projects under src/:
    • Web โ€“ ASP.NET Core MVC app.
    • PublicApi โ€“ ASP.NET Core Web API.

4.2 Configure SQL Server

The README has a โ€œConfiguring the sample to use SQL Serverโ€ section. (GitHub)

  1. Open src/Web/appsettings.json.
  2. Verify connection strings point to your local SQL Server, for example:
"ConnectionStrings": {
  "CatalogConnection": "Server=localhost;Database=CatalogDb;User Id=sa;Password=YourStrong!Passw0rd;TrustServerCertificate=True;",
  "IdentityConnection": "Server=localhost;Database=IdentityDb;User Id=sa;Password=YourStrong!Passw0rd;TrustServerCertificate=True;"
}
Code language: JavaScript (javascript)

For localdb:

"CatalogConnection": "Server=(localdb)\\mssqllocaldb;Database=CatalogDb;Trusted_Connection=True;MultipleActiveResultSets=true"
Code language: JavaScript (javascript)
  1. Make sure "UseOnlyInMemoryDatabase" in appsettings.json is false (or remove the setting) so EF uses SQL Server. (GitHub)

4.3 Apply EF Core migrations

From the src/Web folder:

cd src/Web

dotnet restore
dotnet tool restore   # ensures dotnet-ef is available for this repo

dotnet ef database update -c catalogcontext -p ../Infrastructure/Infrastructure.csproj -s Web.csproj
dotnet ef database update -c appidentitydbcontext -p ../Infrastructure/Infrastructure.csproj -s Web.csproj
Code language: PHP (php)

This creates and seeds:

  • Catalog database (products, baskets, etc.)
  • Identity database (users, roles). (GitHub)

4.4 Run Web & PublicApi

You need both running:

Terminal 1 (PublicApi)

cd src/PublicApi
dotnet run
# Usually listens on https://localhost:5002 or similar (check console output)
Code language: PHP (php)

Terminal 2 (Web)

cd src/Web
dotnet run --launch-profile https
# Typically: https://localhost:5001
Code language: PHP (php)

Open browser:

  • Store front: https://localhost:5001/
  • Admin (Blazor) UI: https://localhost:5001/admin (GitHub)

Default seeded login (per README):

  • demouser@microsoft.com / (check README or seed code for the password; often Pass@word1 or similar in the sample).

Now the app is running and ready for your capstone labs.


5. Step 2 โ€“ Live Runtime Health with dotnet-counters

Problem: โ€œIs my service healthy right now? CPU, GC, allocations, thread pool?โ€

5.1 Find the process ID

Run Web + PublicApi. Then:

dotnet-counters ps

Youโ€™ll see something like:

12345  eShopOnWeb.Web
12360  eShopOnWeb.PublicApi
Code language: CSS (css)

5.2 Monitor PublicApi under light load

Start monitoring:

dotnet-counters monitor --process-id 12360 System.Runtime Microsoft-AspNetCore-Server-Kestrel
Code language: CSS (css)

Open browser and hit:

  • https://localhost:5001/catalog
  • Or call PublicApi endpoints directly (e.g. /api/catalogitems โ€“ check controllers).

Watch:

  • CPU Usage (%)
  • GC Heap Size
  • Gen 0/1/2 collections / sec
  • ThreadPool Thread Count
  • Requests per second (from Kestrel counters)

5.3 Capture a short session

For a 60-second capture:

dotnet-counters collect --process-id 12360 --duration 60 --output publicapi-counters.json
Code language: CSS (css)

Capstone deliverable:
Students must:

  • Capture baseline metrics (no load).
  • Trigger manual browsing.
  • Compare counters (CPU, allocations, GC) before & during load.
  • Document โ€œnormal healthy baselineโ€ for this app.

6. Step 3 โ€“ CPU Profiling with dotTrace

Problem: โ€œWhy is this endpoint slow? Where is the time going?โ€

6.1 Scenario to profile

Pick one PublicApi endpoint, for example:

  • GET /api/catalogitems (list products).
  • GET /api/catalogitems?pageIndex=10&pageSize=20 (heavier query).

6.2 Running dotTrace

  1. Open dotTrace.
  2. Choose:
    • Profile | .NET Core Application.
    • Target: src/PublicApi/bin/.../PublicApi.dll or launch via solution in VS/Rider with dotTrace integration.
    • Profiling type: start with Timeline or Sampling.
  3. Start profiling.
  4. While profiling, run:
    • Browser: call the endpoint repeatedly, or
    • k6 (later step) to generate load.
  5. Stop profiling in dotTrace.

6.3 Analyze

In the dotTrace UI:

  • Sort by โ€œHot Spotsโ€ or Call Tree โ†’ look at:
    • EF Core query methods (ToListAsync, Where, Include, etc.).
    • Any custom business methods doing heavy CPU.
  • Identify:
    • Expensive LINQ queries.
    • Over-use of AutoMapper, string concatenation, etc.

6.4 Code optimization example

Students can apply simple optimizations like:

  • Replace ToList() then filtering in memory with filtering in the database.
  • Use AsNoTracking() on read-only EF queries.
  • Cache reference data in memory if itโ€™s safe.

Re-profile with dotTrace and show:

  • Reduced total CPU time.
  • Reduced time in specific methods.

Capstone deliverable:
Before/after screenshots of dotTrace with explanation of:

  1. Hot path before optimization.
  2. Code change.
  3. Hot path after optimization (time reduced by X%).

7. Step 4 โ€“ Memory Profiling with dotMemory

Problem: โ€œWhy is memory/GC so high? Any leaks or heavy allocations?โ€

7.1 Start dotMemory session

  1. Open dotMemory.
  2. Attach to Web or PublicApi process.
  3. Generate some load:
    • Browse catalog / admin.
    • Or run a small k6 test for 1โ€“2 minutes.
  4. Take a โ€œGet Snapshotโ€ in dotMemory.

7.2 Analyze snapshot

Look for:

  • Top types by bytes (large arrays, strings, DTOs).
  • Large Object Heap (LOH) usage.
  • Retention paths:
    • Are large collections retained by static caches or DI singletons?

7.3 Optional: Introduce intentional tiny โ€œleakโ€

For training, you can introduce a simple bug, e.g.:

public static List<string> DebugCache = new List<string>();

public Task SomeServiceMethod(...)
{
    DebugCache.Add(Guid.NewGuid().ToString());
    ...
}
Code language: PHP (php)

After traffic, memory will grow; dotMemory will show the static list retaining objects.

Capstone deliverable:

  • Snapshot analysis: top 3 types by size.
  • Explanation of whether memory usage is reasonable or suspicious.
  • (Optional) detection & fix of intentional โ€œleak,โ€ with before/after snapshots.

8. Step 5 โ€“ Deep GC/CPU Analysis with PerfView

Problem: โ€œI need full low-level view of GC, CPU, allocations, threads.โ€

8.1 Collect trace with PerfView

  1. Run PerfView.exe as Administrator.
  2. Collect โ†’ Collectโ€ฆ
  3. Configure:
    • Check CPU Samples, .NET Alloc, Thread Time, GC.
  4. In โ€œProcess Filterโ€, specify PublicApi;Web to avoid noise.
  5. Click Start Collection.
  6. Generate traffic (browser or k6).
  7. Click Stop Collection.

PerfView creates a .etl.zip file.

8.2 Analyze

Open the trace:

  • View โ†’ CallTree
    • Look at Inclusive CPU (%); identify top methods.
  • View โ†’ GCStats
    • GC pause times.
    • Gen 2 / LOH activity.
  • View โ†’ Events โ†’ GC/AllocationTick
    • Allocation hotspots per type/method.

Compare before and after your earlier optimizations:

  • Less CPU in certain methods.
  • Less GC time / fewer Gen 2 collections.
  • Lower allocation rates.

Capstone deliverable:

  • Short report (one slide or doc section) summarizing PerfView findings:
    • โ€œTop 3 CPU-heavy methods.โ€
    • โ€œGC characteristics under load.โ€
    • โ€œImpact of optimization X on GC stats.โ€

9. Step 6 โ€“ Micro-benchmarks with BenchmarkDotNet

Problem: โ€œIs optimization A actually faster than B? LINQ vs loop, etc.โ€

9.1 Create benchmark project

In solution root:

dotnet new console -n EShop.Benchmarks
cd EShop.Benchmarks
dotnet add package BenchmarkDotNet
Code language: JavaScript (javascript)

Edit Program.cs to something like:

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Linq;

public class CatalogFilterBenchmarks
{
    private readonly List<int> _data;

    public CatalogFilterBenchmarks()
    {
        _data = Enumerable.Range(1, 100_000).ToList();
    }

    [Benchmark]
    public int LinqWhereCount()
    {
        return _data.Where(x => x % 2 == 0).Count();
    }

    [Benchmark]
    public int ForLoopCount()
    {
        var count = 0;
        for (int i = 0; i < _data.Count; i++)
        {
            if (_data[i] % 2 == 0) count++;
        }
        return count;
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        BenchmarkRunner.Run<CatalogFilterBenchmarks>();
    }
}
Code language: PHP (php)

Run:

dotnet run -c Release

Youโ€™ll get:

  • Mean execution times.
  • Std deviation.
  • Allocations per operation.

9.2 Link to real code

For stronger capstone:

  • Extract a real method from eShopOnWeb (e.g., a pricing calculation, filtering logic, mapping).
  • Create CurrentImplementation vs OptimizedImplementation.
  • Benchmark both with BenchmarkDotNet.

Capstone deliverable:

  • Benchmark table showing:
    • Methods A vs B.
    • Time & allocations.
  • Narrative: โ€œWe chose B because itโ€™s 30% faster with 50% fewer allocations.โ€

10. Step 7 โ€“ Load Testing with k6

Goal: Generate load against PublicApi / Web, correlate with dotnet-counters, PerfView, Datadog.

10.1 Install k6 (Windows)

Follow the k6 docs (choco, MSI or binary). (Grafana Labs)

Verify:

k6 version

10.2 Create test script eshop-load.js

Example script hitting a catalog endpoint:

import http from 'k6/http';
import { check, sleep } from 'k6';

export let options = {
  vus: 50,
  duration: '2m',
  thresholds: {
    http_req_duration: ['p(95)<500'], // 95% < 500ms
    http_req_failed: ['rate<0.01'],   // < 1% errors
  },
};

const BASE_URL = 'https://localhost:5002'; // PublicApi HTTPS port

export default function () {
  let res = http.get(`${BASE_URL}/api/catalogitems?pageIndex=0&pageSize=20`);
  
  check(res, {
    'status is 200': (r) => r.status === 200,
  });
  
  sleep(1);
}
Code language: JavaScript (javascript)

If HTTPS/localhost causes TLS issues, you can run k6 with --insecure-skip-tls-verify.

10.3 Run the test

k6 run eshop-load.js
Code language: CSS (css)

While k6 runs, also:

  • dotnet-counters monitor on PublicApi.
  • Optionally, another PerfView trace capture.

Capstone deliverable:

  • k6 output screenshots (RPS, latency, failures).
  • Counters snapshot (GC, CPU).
  • Discussion: โ€œUnder 50 VUs, 95p latency = X ms, error rate Y%.โ€

11. Step 8 โ€“ Datadog Agent & Dashboard

Now weโ€™ll wire the app into Datadog APM + metrics.

11.1 Install Datadog Agent on Windows

  1. Sign in to Datadog.
  2. Go to Integrations โ†’ Agent โ†’ Windows.
  3. Download the installer (or datadog-installer-x86_64.exe) and run it. (docs.datadoghq.com)
  4. During setup, supply your Datadog API key.
  5. After install:
    • Confirm service is running.
    • In Datadog UI, your host should appear under Infrastructure โ†’ Host Map.

11.2 Install Datadog .NET Tracer

Follow the โ€œTracing .NET Core Applicationsโ€ documentation: (docs.datadoghq.com)

On Windows the common approach is:

  1. Download & run the latest Datadog .NET Tracer MSI (from Datadog docs).
  2. This sets environment variables and profiler DLLs system-wide.

Key environment variables (usually set by installer, but you can override per app):

DD_SERVICE=eshop-publicapi
DD_ENV=perf-lab
DD_VERSION=1.0.0
DD_AGENT_HOST=localhost
DD_TRACE_ENABLED=true
DD_LOGS_INJECTION=true
Code language: JavaScript (javascript)

For Web app:

DD_SERVICE=eshop-web
DD_ENV=perf-lab
DD_VERSION=1.0.0
DD_AGENT_HOST=localhost

Restart your Web & PublicApi processes after installing tracer / setting env vars.

11.3 Generate traffic and verify traces

  1. Run Web + PublicApi.
  2. Run your k6 test again.
  3. In Datadog:
    • Go to APM โ†’ Services.
    • You should see services like eshop-publicapi, eshop-web appear.
    • Click into a service, open some traces, and inspect:
      • Request path.
      • DB spans (SQL statements, durations).
      • Error spans (if any).

Datadog docs for .NET tracing show how DB spans and HTTP spans are captured automatically via automatic instrumentation. (docs.datadoghq.com)

11.4 Create a Datadog Dashboard

In Datadog:

  1. Dashboards โ†’ New Dashboard.
  2. Add widgets:
    • Timeseries: avg:aspnet_core.request.duration{service:eshop-publicapi}
    • Timeseries: sum:aspnet_core.request.hits{service:eshop-publicapi} (RPS)
    • Query: sum:system.cpu.user{host:YOUR_HOST} (CPU).
    • aspnet_core.requests.errors for error rate.
    • If the tracer exposes GC metrics (via runtime integration), show:
      • GC pause time.
      • Gen 2 collections.
  3. Add a Top List for:
    • top(avg:trace.http.request.duration{service:eshop-publicapi} by {resource})
    • (Shows slowest endpoints.)

Capstone deliverable:

  • A screenshot of the Datadog dashboard.
  • Explanation of key charts:
    • CPU vs request rate during k6.
    • 95p latency & error rate.
    • Slowest endpoints list.

12. How It All Ties Together (Capstone Storyline)

To help you present this as a coherent capstone, hereโ€™s the narrative:

  1. Setup & Baseline
    • Run eShopOnWeb with SQL Server.
    • Confirm basic functionality.
  2. Observe Live Health (dotnet-counters)
    • Identify baseline CPU, GC, allocations under light load.
  3. Generate Load (k6)
    • Simulate real traffic to PublicApi.
  4. Investigate CPU (dotTrace)
    • Profile slow endpoints.
    • Optimize EF queries / business logic.
  5. Investigate Memory (dotMemory)
    • Look for high allocations or leaks.
    • Fix or justify memory patterns.
  6. Deep-Dive (PerfView)
    • Verify GC/CPU behavior at low level.
    • Validate impact of optimization.
  7. Micro-Benchmarks (BenchmarkDotNet)
    • Benchmark critical internal methods to choose best implementation.
  8. End-to-End Observability (Datadog)
    • Visualize everything in one dashboard: latency, errors, CPU, GC, SQL.
    • Correlate k6 load, runtime counters, and APM traces.

By the end, students experience the full lifecycle:

Bug / performance problem โ†’ measurement (counters, traces, profilers) โ†’ hypothesis โ†’ code & DB change โ†’ benchmark โ†’ load test โ†’ monitor in Datadog.


Find Trusted Cardiac Hospitals

Compare heart hospitals by city and services โ€” all in one place.

Explore Hospitals
Iโ€™m a DevOps/SRE/DevSecOps/Cloud Expert passionate about sharing knowledge and experiences. I have worked at <a href="https://www.cotocus.com/">Cotocus</a>. I share tech blog at <a href="https://www.devopsschool.com/">DevOps School</a>, travel stories at <a href="https://www.holidaylandmark.com/">Holiday Landmark</a>, stock market tips at <a href="https://www.stocksmantra.in/">Stocks Mantra</a>, health and fitness guidance at <a href="https://www.mymedicplus.com/">My Medic Plus</a>, product reviews at <a href="https://www.truereviewnow.com/">TrueReviewNow</a> , and SEO strategies at <a href="https://www.wizbrand.com/">Wizbrand.</a> Do you want to learn <a href="https://www.quantumuting.com/">Quantum Computing</a>? <strong>Please find my social handles as below;</strong> <a href="https://www.rajeshkumar.xyz/">Rajesh Kumar Personal Website</a> <a href="https://www.youtube.com/TheDevOpsSchool">Rajesh Kumar at YOUTUBE</a> <a href="https://www.instagram.com/rajeshkumarin">Rajesh Kumar at INSTAGRAM</a> <a href="https://x.com/RajeshKumarIn">Rajesh Kumar at X</a> <a href="https://www.facebook.com/RajeshKumarLog">Rajesh Kumar at FACEBOOK</a> <a href="https://www.linkedin.com/in/rajeshkumarin/">Rajesh Kumar at LINKEDIN</a> <a href="https://www.wizbrand.com/rajeshkumar">Rajesh Kumar at WIZBRAND</a> <a href="https://www.rajeshkumar.xyz/dailylogs">Rajesh Kumar DailyLogs</a>

Related Posts

Ruby on Rails vs Node.js: Performance, Speed, and Scalability Compared

Choosing between Ruby on Rails and Node.js is a common decision when building modern web applications. Both frameworks power large-scale products, but they approach performance, concurrency, and…

Read More

How Zero-Knowledge Coprocessors Are Reshaping Web3 Computation

Developers often hit a brick wall when building decentralized apps. Standard infrastructure just fails to keep up. Clogging a main network with heavy workloads leads to slow…

Read More

5 Top Developer Experience (DevEx) Insight Tools for 2026

Developer experience has evolved from an internal engineering concern into a measurable operational discipline. As software organizations scale across distributed cloud environments, platform engineering initiatives, AI-assisted development…

Read More

Top 10 AI Tools to Automate Repetitive Documents For DevOps Teamsย 

DevOps teams have automated deployingโ€š testingโ€š monitoringโ€š and rolling back changesโ€š but documentation layer automation is a gap that still incurs time costโ€ค Gartner predicts by 2026…

Read More

Customer Loyalty Strategy for SaaS and eCommerce: How to Pick the Right Software

Customer Loyalty Strategy for SaaS and eCommerce: How to Pick the Right Software TL;DR Retaining a customer costs 5 to 25 times less than acquiring a new…

Read More

Top 10 Sales Enablement Tools: Features, Pros, Cons & Comparison

Introduction Sales Enablement Tools are platforms designed to equip sales teams with the right content, insights, training, and data at the right timeโ€”so they can sell more…

Read More
Subscribe
Notify of
guest
2 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
Jason Mitchell
Jason Mitchell
5 months ago

This post does an excellent job of outlining a realโ€‘world capstone project โ€” using the eShopOnWeb sample application โ€” to teach performance optimization in .NET. By walking through baseline performance profiling, CPU/memory profiling, microโ€‘benchmarking, load testing, and monitoring (with tools like dotnetโ€‘counters, dotTrace, PerfView, BenchmarkDotNet, k6, Datadog, etc.), it gives a very concrete and practical roadmap that works for both small and large projects. The stepโ€‘byโ€‘step structure โ€” from cloning the repo to analyzing bottlenecks and then benchmarking improvements โ€” really helps learners understand not just what to optimize but how and why. This kind of handsโ€‘on, fullโ€‘lifecycle approach bridges the gap between theory and productionโ€‘ready .NET application performance.

Skylar Bennett
Skylar Bennett
5 months ago

This article provides a clear and practical roadmap for developers looking to deepen their .NET skills through realโ€‘world, performanceโ€‘oriented capstone projects. By focusing not only on functionality but on performance tuning โ€” efficient queries, memory usage, async programming, caching strategies, and code profiling โ€” the training helps build applications that are both robust and performant. The emphasis on handsโ€‘on projects teaches more than theory: it gives developers experience dealing with real performance bottlenecks and tuning them effectively, which is crucial for enterpriseโ€‘scale .NET applications. For anyone aiming to become a serious .NET engineer โ€” especially in backend, databaseโ€‘heavy, or highโ€‘traffic environments โ€” this kind of training looks like a valuable, careerโ€‘ready investment.

2
0
Would love your thoughts, please comment.x
()
x