【.NET】| 作者/Mike Rousos
本文来自Microsoft Docs官方文档,提供了ASP.NET Core性能最佳做法的准则。
1充分利用缓存
缓存在本文档的多个部分中进行了讨论。有关详细信息,请参阅 ASP.NET Core 中的响应缓存。
参考:https://docs.microsoft.com/zh-cn/aspnet/core/performance/performance-best-practices?view=aspnetcore-6.0
2了解热代码路径
在本文档中,热代码路径定义为经常调用并形成大量执行时间的代码路径。热代码路径通常会限制应用横向扩展和性能,在本文档的多个部分中进行了讨论。
3避免阻塞调用
ASP.NET Core 应用应设计为可同时处理许多请求。异步 API 允许较小线程池处理数千个并发请求,无需等待阻塞调用。线程可以处理另一个请求,而不是等待长时间运行的同步任务完成。
ASP.NET Core 应用中的一个常见性能问题是阻塞可以异步进行的调用。许多同步阻塞调用都会导致线程池饥饿和响应时间降低。
禁止行为:
建议做法:
探查器(例如 PerfView)可用于查找频繁添加到线程池中的线程。 Microsoft-Windows-DotNETRuntime/ThreadPoolWorkerThread/Start
事件指示添加到线程池的线程。
4跨多个较小页面返回大集合
网页不应一次加载大量数据。返回对象集合时,请考虑它是否会导致性能问题。确定设计是否可能会产生以下不良结果:
请添加分页以缓解以上情形。使用页面大小和页面索引参数时,开发人员应支持返回部分结果的设计。当需要详尽结果时,应使用分页来异步填充结果批次,以避免锁定服务器资源。
有关分页和限制返回的记录数的详细信息,请参阅:
5返回IEnumerable<T>或IAsyncEnumerable<T>
从操作返回 IEnumerable<T>
会导致序列化程序同步集合迭代。因此会阻止调用,并且可能会导致线程池资源不足。若要避免同步枚举,请在返回可枚举内容前使用 ToListAsync
。
从 ASP.NET Core 3.0 开始,IAsyncEnumerable<T>
可用作异步枚举的 IEnumerable<T>
的替代方法。有关详细信息,请参阅控制器操作返回类型。
6最大程度减少大型对象分配
.NET Core 垃圾回收器在 ASP.NET Core 应用中自动管理内存分配和释放。自动垃圾回收通常意味着开发人员无需担心如何或何时释放内存。但是,清理未引用的对象会占用 CPU 时间,因此开发人员应最大限度减少热代码路径中的对象分配。垃圾回收在大型对象(> 85 K 字节)上成本特别高昂。大型对象存储在大型对象堆上,需要完整(第 2 代)垃圾回收才能清理。与第 0 代和第 1 代回收不同,第 2 代回收需要临时暂停应用执行。频繁分配和取消分配大型对象可能会导致性能不一致。
建议:
可以通过在 PerfView 中查看垃圾回收 (GC) 统计信息并检查以下内容来诊断内存问题(如前面的问题):
有关详细信息,请参阅垃圾回收和性能。
参考:https://docs.microsoft.com/zh-CN/dotnet/standard/garbage-collection/performance
7优化数据访问和I/O
与数据存储和其他远程服务的交互通常是 ASP.NET Core 应用的最慢部分。高效读取和写入数据对于良好的性能至关重要。
建议:
.Select
或 .Sum
语句),以便数据库执行筛选。请参阅 EF 高性能,以了解可提高大规模应用性能的方法:
建议在提交基本代码之前衡量前面高性能方法的影响。已编译查询的额外复杂性可能无法证明性能改进的合理性。
通过使用 Application Insights 或分析工具查看访问数据所用的时间,可以检测到查询问题。大多数数据库还提供有关频繁执行的查询的统计信息。
8与HttpClientFactory之间的池HTTP连接
虽然 HttpClient 实现了 IDisposable
接口,但它是为重复使用而设计的。关闭的 HttpClient
实例使套接字在短时间内以 TIME_WAIT
状态保持打开。如果经常使用创建和释放 HttpClient
对象的代码路径,则应用可能会耗尽可用的套接字。在 ASP.NET Core 2.1 中引入了 HttpClientFactory,以作为此问题的解决方案。它会处理池 HTTP 连接以优化性能和可靠性。
建议:
9使常用代码路径保持快速
你希望所有代码都可快速执行。经常调用的代码路径是优化的关键。其中包括:
建议:
10在HTTP请求外部完成长时间运行任务
对 ASP.NET Core 应用进行的大多数请求可以由调用必要服务并返回 HTTP 响应的控制器或页面模型进行处理。对于涉及长时间运行的任务的一些请求,最好使整个请求-响应过程异步进行。
建议:
11缩小客户端资产
具有复杂前端的 ASP.NET Core 应用会经常处理许多 JavaScript、CSS 或图像文件。初始加载请求的性能可以通过以下方式得到提高:
建议:
12压缩响应
减小响应大小通常可显著提高应用的响应速度。减小有效负载大小的一种方式是压缩应用的响应。有关详细信息,请参阅响应压缩。
参考:https://docs.microsoft.com/zh-cn/aspnet/core/performance/response-compression?view=aspnetcore-6.0
13使用最新ASP.NET Core版本
每个新版本的 ASP.NET Core 都包含性能改进。.NET Core 和 ASP.NET Core 中的优化意味着较新版本的性能通常优于较旧版本。例如,.NET Core 2.1 添加了对已编译正则表达式的支持,可受益于 SpanT>。ASP.NET Core 2.2 添加了对 HTTP/2 的支持。 ASP.NET Core 3.0 添加了许多改进,可减少内存使用量并提高吞吐量。如果性能是优先事项,请考虑升级到当前版本的 ASP.NET Core。
14尽量减少异常
异常应很少出现。相对于其他代码流模式,引发和捕获异常的速度较慢。因此,不应使用异常来控制正常程序流。
建议:
应用诊断工具(如 Application Insights)可帮助识别应用中可能会影响性能的常见异常。