1. 数据库性能优化
正确使用索引
在经常查询的列上创建索引。
避免在选择性差的列上创建索引(例如:IsActive、Gender)。
示例:在 SQL Server 中添加索引
CREATE INDEX IX_Orders_CustomerId
ON Orders(CustomerId);
为什么? 通过减少全表扫描来提高查询性能。
*避免使用 SELECT (仅获取所需列)
而不是:
var orders = _context.Orders.ToList();
使用:
var orders = _context.Orders
.Select(o => new { o.Id, o.OrderNumber })
.ToList();
为什么? 减少数据传输和内存使用。
使用预加载(Include())优化查询
而不是懒加载(可能导致 N+1 查询):
var orders = _context.Orders
.Include(o => o.OrderItems)
.ToList();
为什么? 减少多个数据库调用,提高效率。
使用存储过程代替复杂的 LINQ 查询
存储过程执行更快,因为它们是预编译的。
var orders = _context.Orders
.FromSqlRaw("EXEC GetOrdersByCustomer @customerId", param)
.ToList();
为什么? 减少查询解析开销。
2. 内存管理与垃圾回收
使用 using 处理可释放的对象
当资源不再需要时,using 可以释放它们,避免内存泄漏。
using (var connection = new SqlConnection("your_connection_string"))
{
connection.Open();
}
为什么? 确保立即清理资源。
使用 StringBuilder 处理大型字符串操作
而不是:
string result = "";
for (int i = 0; i < 1000; i++)
{
result += "Test" + i;
}
使用:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
sb.Append("Test").Append(i);
}
string result = sb.ToString();
为什么? 避免不必要的内存分配。
实现对象池(Object Pooling)用于可重用的对象
而不是多次创建新对象:
public class ConnectionPool
{
private static readonly ObjectPool _pool =
new DefaultObjectPool(
new DefaultPooledObjectPolicy(), 10);
public static SqlConnection GetConnection()
{
return _pool.Get();
}
}
为什么? 减少频繁创建对象的开销。
3. 缓存以加快数据检索
内存缓存常用数据
使用 IMemoryCache 存储频繁使用的数据:
public classCacheService
{
privatereadonly IMemoryCache _cache;
public CacheService(IMemoryCache cache)
{
_cache = cache;
}
public List GetOrders()
{
return _cache.GetOrCreate("orders", entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10);
return FetchOrdersFromDatabase();
});
}
}
为什么? 减少不必要的数据库调用。
使用 Redis 进行分布式缓存
对于大型应用程序,将缓存存储在应用程序外部。
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost:6379";
});
为什么? 有助于高效地扩展应用程序。
4. 提升 API 性能
为 I/O 操作使用异步处理
而不是:
public List GetOrders()
{
return _context.Orders.ToList();
}
使用:
public async Task<List> GetOrdersAsync()
{
return await _context.Orders.ToListAsync();
}
为什么? 释放线程并提高可扩展性。
在 ASP.NET Core 中启用 GZIP 压缩
减少响应大小,加快 API 调用。
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression();
}
public void Configure(IApplicationBuilder app)
{
app.UseResponseCompression();
}
为什么? 减少带宽消耗。
实现速率限制
通过设置请求限制来防止 API 滥用。
services.AddRateLimiter(options =>
{
options.GlobalLimit = 100; // 每分钟允许 100 个请求
});
为什么? 保护服务器资源。
5. 多线程与并行处理
使用 Parallel.ForEach 进行 CPU 密集型任务
而不是:
foreach (var item in dataList)
{
ProcessData(item);
}
使用:
Parallel.ForEach(dataList, item =>
{
ProcessData(item);
});
为什么? 高效利用多个 CPU 核心。
使用后台作业处理长时间运行的任务
用于异步处理任务,而不会阻塞 API 请求。
public class OrderProcessingService : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
ProcessOrders();
await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
}
}
}
为什么? 将重任务从 API 请求中分离出来。
6. 减少启动时间与优化加载
使用懒初始化(Lazy)处理重量级对象
private static readonly Lazy _dbConnection =
new Lazy(() => new DatabaseConnection());
为什么? 仅在需要时加载对象,减少启动时间。
最小化 ASP.NET Core 中的中间件
移除不必要的中间件,减少请求处理开销。
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
为什么? 提高请求处理效率。
7. 优化 LINQ 查询
使用 Any()代替 Count()检查是否存在
if (orders.Any())
{
/* 更快 */
}
为什么? Count()扫描整个列表,而 Any()会在找到第一个匹配项时停止。
使用 FirstOrDefault()代替 Where().FirstOrDefault()
var user = users.FirstOrDefault(u => u.Id == 1); // 更好
为什么? 消除不必要的筛选。
8. 使用性能分析与监控
使用 Stopwatch 测量执行时间
var sw = Stopwatch.StartNew();
// 执行代码
sw.Stop();
Console.WriteLine($"执行时间: {sw.ElapsedMilliseconds} ms");
为什么? 帮助识别慢操作。
使用应用程序性能监控(APM)工具
Application Insights(Azure)
New Relic、Datadog
ELK Stack(Elasticsearch、Logstash、Kibana)
为什么? 实时诊断瓶颈。
结论
优化应用程序性能不仅仅是编写更快的代码——它是关于使你的系统高效、可扩展且具有韧性。通过优化数据库查询、有效的内存管理、缓存、异步编程和性能分析,你可以大幅提升 C#应用程序的速度和响应性。
优化数据库以减少查询开销。
利用缓存减少不必要的计算。
使用异步编程高效处理多任务。
编写简洁高效的 LINQ 查询,避免性能陷阱。
监控和分析应用程序,识别并修复瓶颈。
遵循这些最佳实践,确保你的应用程序运行更快,处理更高负载,并提供无缝的用户体验。现在,赶紧像专业人士一样,让你的 C#项目超级加速吧!
译文地址:csharp.com/blogs/boost-c-sharp-application-performance-like-a-pro2
翻译:chatgpt