C# 如何减少代码运行时间:7 个实战技巧
·
var query = numbers.Where(n => n > 1);
// 错误:每次都重新执行
if (query.Any()) // 执行一次
{
var first = query.First(); // 又执行一次
var count = query.Count(); // 再执行一次
}
// 正确:缓存结果
var list = numbers.Where(n => n > 1).ToList();
if (list.Any())
{
var first = list.First(); // 从缓存读取
var count = list.Count(); // 从缓存读取
}
性能对比
| 操作 | 延迟执行 | 立即执行 (ToList) |
|---|---|---|
| 多次访问 | 每次重新计算 | 一次计算,多次读取 |
| 内存占用 | 低 | 需要存储结果 |
| 适用场景 | 单次遍历 | 多次访问 |
六、避免装箱拆箱
什么是装箱拆箱?
int value = 42;
object obj = value; // 装箱:值类型 → 引用类型
int back = (int)obj; // 拆箱:引用类型 → 值类型
每次装箱都会:
- 在堆上分配内存
- 触发 GC
错误示范
var list = new ArrayList(); // 非泛型集合
list.Add(1); // 装箱
list.Add(2); // 装箱
int sum = 0;
foreach (int i in list) // 拆箱
{
sum += i;
}
正确做法
var list = new List<int>(); // 泛型集合
list.Add(1); // 无装箱
list.Add(2); // 无装箱
int sum = 0;
foreach (int i in list) // 无拆箱
{
sum += i;
}
性能差异
循环 100 万次:
- ArrayList:约 50ms
- List:约 5ms
10 倍差距,这就是泛型的威力。
七、对象池:复用而非重建
为什么需要对象池?
频繁创建销毁对象会:
- 增加 GC 压力
- 触发频繁 GC 暂停
- 影响应用响应时间
使用 ArrayPool
using System.Buffers;
// 传统方式:每次分配新数组
byte[] buffer = new byte[1024];
ProcessData(buffer);
// 对象池方式:复用数组
var pool = ArrayPool<byte>.Shared;
byte[] buffer = pool.Rent(1024);
try
{
ProcessData(buffer);
}
finally
{
pool.Return(buffer); // 归还池中
}
使用 MemoryPool
using System.Buffers;
var pool = MemoryPool<byte>.Shared;
using var memoryOwner = pool.Rent(1024);
ProcessData(memoryOwner.Memory);
// 自动归还
适用场景
- 高频临时数组
- 网络缓冲区
- 游戏中的临时对象
- 图像处理中的像素缓冲
更多推荐
所有评论(0)