C#应用程序性能优化:.NET实用技巧与实践

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么C#性能很重要

C#和.NET平台是构建高负载Web服务、桌面应用和Unity游戏的强大工具。然而,如果你不了解CLR(公共语言运行时)、垃圾回收器(GC)和JIT编译机制的工作方式,即使是最优雅的代码也可能运行缓慢。

本文将分析优化C#应用程序性能的关键方法,帮助你减少响应时间、降低内存消耗并提高系统吞吐量。所有建议均附有实用代码示例。



1. 内存管理和垃圾回收(GC)

.NET的主要特点之一是自动内存管理。但不正确地使用对象会导致频繁的垃圾回收,从而造成应用程序"暂停"(卡顿)。



1.1. 避免在热路径中分配内存

尽量不要在循环内部或频繁调用的方法中创建新对象。相反,应使用对象池或重用实例。

// 不好:每次迭代都会创建新的StringBuilderfor (int i = 0; i < 1000; i++){    var sb = new StringBuilder();    sb.Append(i);}

// 好:使用池或重用var sbPool = new StringBuilder();for (int i = 0; i < 1000; i++){ sbPool.Clear(); sbPool.Append(i);}


1.2. 对于小型数据使用结构体而非类

结构体存储在栈上,不会给GC带来负担。但要注意:大型结构体(超过16字节)复制时可能较慢。

public struct Point{    public int X;    public int Y;}

// 现在调用方法时不会在堆上创建对象void ProcessPoint(Point p) { /* ... */ }


1.3. 为服务器应用程序启用服务器GC模式

默认情况下,控制台应用程序使用工作站GC。对于Web服务(ASP.NET Core),在csproj文件中切换到服务器GC:

<PropertyGroup>    <ServerGarbageCollection>true</ServerGarbageCollection></PropertyGroup>


2. 优化LINQ和集合的使用

LINQ是一个方便但可能较慢的工具,如果你不了解它的"陷阱"。



2.1. 避免多次枚举

每次调用.Count()、.ToList()或.Any()都可能重新执行查询。将结果保存到变量中。

// 不好:对集合进行两次遍历if (items.Where(x => x.IsActive).Count() > 0) { /* ... */ }var activeList = items.Where(x => x.IsActive).ToList();

// 好:一次遍历var activeItems = items.Where(x => x.IsActive).ToList();if (activeItems.Count > 0) { /* ... */ }


2.2. 使用专用集合

对于频繁的基于键的查找,使用Dictionary<TKey, TValue>而不是List<T>。对于"先进先出"操作,使用Queue<T>。

// 快速查找:O(1) 而不是 O(n)var dict = new Dictionary<int, string>();dict.Add(1, "one");if (dict.ContainsKey(1)) { /* ... */ }


2.3. 在关键部分用循环替代LINQ

对于简单操作(求和、过滤),for或foreach循环比LINQ快2-3倍。

// LINQ(慢)int sum = numbers.Sum();

// 循环(快)int sum = 0;for (int i = 0; i < numbers.Length; i++){ sum += numbers[i];}


3. 异步编程和减少阻塞

正确使用async/await可以不阻塞线程,这对可扩展性至关重要。



3.1. 对经常同步返回的结果使用ValueTask

博客

书籍推荐