在C#项目开发过程中,性能问题往往不会在开发初期暴露,随着业务量增长和数据量积累,才会出现响应变慢、资源占用飙升的情况,掌握系统的性能测试与调优方法对开发者来说非常重要。

C#性能测试核心方法
常用性能测试工具
做性能测试首先要选对工具,不同场景适合的工具有所区别:
- BenchmarkDotNet:适合做代码级别的性能基准测试,能精准对比不同实现方式的性能差异,输出详细的统计结果。
- dotnet-trace:.NET官方提供的诊断工具,可采集程序运行时的CPU、内存等 trace 数据,用于分析运行时的性能瓶颈。
- Visual Studio 诊断工具:开发阶段可直接使用,能实时查看内存分配、CPU占用、函数调用耗时等信息,方便快速定位问题。
基础性能测试示例
使用BenchmarkDotNet测试两种字符串拼接方式的性能差异,代码如下:
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace PerformanceTestDemo
{
[MemoryDiagnoser] // 开启内存诊断,输出内存分配数据
public class StringConcatTest
{
private const int LoopCount = 10000;
private List<string> _testData;
[GlobalSetup]
public void Setup()
{
_testData = new List<string>();
for (int i = 0; i < LoopCount; i++)
{
_testData.Add(i.ToString());
}
}
// 测试使用+拼接字符串的性能
[Benchmark]
public string TestPlusConcat()
{
string result = "";
foreach (var item in _testData)
{
result += item;
}
return result;
}
// 测试使用StringBuilder拼接字符串的性能
[Benchmark]
public string TestStringBuilderConcat()
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (var item in _testData)
{
sb.Append(item);
}
return sb.ToString();
}
}
class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<StringConcatTest>();
}
}
}
运行后可以看到,StringBuilder的拼接方式在耗时和内存分配上都远优于+拼接,这就是典型的性能测试指导代码优化的场景。
常见性能问题调优经验
内存泄漏排查与优化
C#虽然有垃圾回收机制,但不当的代码写法还是会导致内存泄漏,常见问题包括:
- 事件订阅后没有取消订阅,导致订阅者对象无法被回收。
- 静态变量持有大对象的引用,大对象生命周期和应用程序一致,无法被释放。
- 非托管资源没有正确释放,比如没有调用
Dispose方法或者没有正确使用using语句。
排查内存泄漏可以使用dotnet-dump工具获取内存快照,对比不同时间点的对象存活情况,定位未被回收的异常对象。优化时要及时取消事件订阅,避免静态变量持有不必要的引用,所有实现了IDisposable接口的对象都要用using包裹或者手动调用Dispose。
CPU占用过高优化
CPU占用过高的常见原因和对应优化方式:
| 问题原因 | 优化方式 |
|---|---|
| 高频的装箱拆箱操作 | 避免值类型和引用类型不必要的转换,比如使用泛型集合代替非泛型集合,避免object类型作为参数传递值类型 |
| 大量重复的计算逻辑 | 对重复计算的结果做缓存,比如使用MemoryCache缓存频繁查询且不常变化的数据 |
| 同步阻塞操作占用线程 | IO操作、耗时任务尽量使用异步编程,避免阻塞线程池线程,减少线程上下文切换开销 |
数据库访问性能优化
数据库访问往往是C#应用性能瓶颈的重灾区,优化经验包括:
- 避免循环内执行单条数据库查询,尽量使用批量查询,减少数据库往返次数。
- 合理使用索引,避免全表扫描,同时不要过度建索引,影响写入性能。
- 使用
DbContext时避免长生命周期的上下文实例,及时释放不需要的上下文,减少内存占用。 - 查询时只返回需要的字段,不要使用
select *,减少数据传输和序列化开销。
代码层面通用调优技巧
除了针对具体问题的优化,日常编码时养成好的习惯也能提升整体性能:
- 选择合适的集合类型,比如频繁查找用
Dictionary,频繁插入删除用LinkedList,不要所有场景都用List。 - 避免在循环内做不必要的操作,比如重复创建对象、重复调用相同的方法,把不变的逻辑移到循环外。
- 字符串操作优先使用
StringBuilder,尤其是拼接次数多或者拼接内容大的场景。 - 异步方法不要滥用,只有IO操作、耗时任务才适合用异步,简单的CPU计算用异步反而会增加开销。
性能调优不是一次性的工作,需要在开发、测试、上线全阶段关注,结合性能测试数据针对性优化,才能让C#应用保持稳定的高性能表现。
C#性能测试性能调优dotnet_diagnostic修改时间:2026-07-20 14:36:34