# Investigate a slow .NET workflow

Locate the cost, choose a targeted measurement, and test one change against the original workload.

Dotnetguides · Published by Mottobits · Updated 2026-09-30 · AI-generated

Written with AI and not reviewed by a human. It may contain mistakes.

Choose one slow customer operation. Record where its time goes before asking AI to propose changes. An engineer owns diagnostic access, interpretation, and release decisions; the agent helps organize evidence and compare hypotheses.

## Define the workload and the target

Record the application commit, runtime, instance size, database state, parameter mix, data volume, arrival rate or concurrency, warm-up, and measurement window. Agree latency, throughput, error, and resource limits. Keep ordinary and slow cases.

- Repeat the baseline and retain all runs, including failures. Measure completed work alongside latency.
- Separate startup and warm-cache behavior. Observe the load generator and dependencies so their limits are visible.
- Preserve authorization, tenant boundaries, result ordering, totals, and other business behavior in functional checks.

## Follow the time to the next measurement

Correlate request timing with application, database, and dependency observations from the same slow interval. Each branch below selects a next check, not a diagnosis.

- Application CPU is high: collect a CPU profile and inspect the hot call paths before rewriting code.
- Latency rises while ThreadPool thread count climbs and CPU is not saturated: inspect worker stacks for blocking. For intermittent failures, use a trace spanning the symptom.
- Database time dominates: count commands per request. Repeated commands suggest a loading or loop problem; one expensive command calls for a plan, reads, parameter groups, and wait analysis.
- SQL lock waits dominate: follow the blocking chain to the head blocker and inspect transaction duration. A missing-index hint alone does not explain the wait.
- Memory rises over repeated workload cycles: compare managed heap and process memory, then inspect retention or allocation evidence. Growth alone does not prove a managed leak.
- Database commands finish quickly but the request remains slow: measure result transfer, materialization, serialization, connection acquisition, and other dependency waits.

## Write one hypothesis the evidence can reject

Use four fields: observation; proposed mechanism; competing explanation; next check. Give the agent a sanitized summary and bounded source files. Require it to keep missing measurements explicit.

- State which signal should change if the fix addresses the cause. Keep unrelated refactoring out of the experiment.
- Review query/index changes against representative parameters, write cost, and contention.
- Treat caching as a separate design decision with agreed freshness, tenant isolation, and invalidation rules.
- Keep production dumps, credentials, and unapproved customer data out of AI inputs. Diagnostic collection needs an approved environment and retention policy.

## Compare the result under the original conditions

Repeat the workload and measurement method. Compare latency distributions, completed work, errors, CPU, memory, and relevant dependency signals. Explain run-to-run variation and tradeoffs; a best run is not a reliable comparison.

- Run long enough to expose the original symptom. A short test cannot rule out slow memory growth.
- Retain configuration, commands, raw results, and functional checks with the change. Record a negative result when the hypothesis fails.
- Before rollout, name the owner, observation window, stop conditions, and recovery procedure. Confirm production behavior against those conditions.

## Illustrative example — not customer results

Illustrative reasoning only; no trace or benchmark was executed. Suppose a correlated request log shows one order-list query followed by one line-item query for every returned order. Each statement is short, while the request spends much of its time making sequential database calls. The first hypothesis is repeated round trips. Check whether the screen needs line items before choosing a query rewrite.

- If the screen needs only order summaries, test a scalar projection without loading line entities. If it needs lines, compare an explicit bounded load; do not assume that adding multiple collection joins is cheaper.
- Hold the tenant, parameters, page size, data, and load constant. Verify that command count no longer grows with the number of displayed rows and that required results are unchanged.
- If commands become fewer but request latency barely changes, investigate the remaining time. The experiment has rejected repeated round trips as the main explanation for that latency.
- Adopt the change only if the agreed request target and resource limits pass. Record actual measurements when this experiment is run; this example supplies no speed-up claim.

## Deliverables

- Workload, target, and repeated baseline runs
- Observation-to-hypothesis decision log
- One proposed change and its falsifiable check
- Before-and-after evidence when the change is tested
- Functional checks, rollout limits, and recovery notes

## Limits

- This is an investigation method and an illustrative decision, not a customer case study or a measured result.
- Use tooling compatible with the runtime and operating system. The linked dotnet diagnostic tools target modern .NET; .NET Framework needs compatible alternatives.
- Profiling and detailed logging can affect the workload. Limit collection, protect diagnostic files, and record that overhead.

## Sources

- [Microsoft: dotnet-counters](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-counters)
- [Microsoft: dotnet-trace](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-trace)
- [Microsoft: Debug ThreadPool starvation](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/debug-threadpool-starvation)
- [Microsoft: Efficient querying in EF Core](https://learn.microsoft.com/en-us/ef/core/performance/efficient-querying)
- [Microsoft: debug high CPU usage](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/debug-highcpu)
- [Microsoft: debug a memory leak](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/debug-memory-leak)
- [Microsoft: understand and resolve SQL Server blocking](https://learn.microsoft.com/en-us/troubleshoot/sql/database-engine/performance/understand-resolve-blocking)

Written with AI and not reviewed by a human. It may contain mistakes. Examples are illustrative unless an article explicitly provides executed results. These are working methods, not customer case studies or guaranteed outcomes.
