河南省建设监理网站,wordpress支付宝微信收费吗,赤峰建网站,用什么网站做头像接上一篇文章垃圾回收 (GC) 在 .NET Core 中是如何工作的#xff1f;-CSDN博客
GC 会分配堆段#xff0c;其中每个段都是一系列连续的内存。 置于堆中的对象归类为 3 个代系之一#xff1a;0、1 或 2。 代系可确定 GC 尝试在应用不再引用的托管对象上释放内存的频率。 编号…接上一篇文章垃圾回收 (GC) 在 .NET Core 中是如何工作的-CSDN博客
GC 会分配堆段其中每个段都是一系列连续的内存。 置于堆中的对象归类为 3 个代系之一0、1 或 2。 代系可确定 GC 尝试在应用不再引用的托管对象上释放内存的频率。 编号较低的代系会更加频繁地进行 GC。
对象会基于其生存期从一个代系移到另一个代系。 随着对象生存期延长它们会移到较高代系。 如前所述较高代系进行 GC 的频率较低。 短期生存的对象始终保留在第 0 代中。 例如在 Web 请求存在期间引用的对象的生存期较短。 应用程序级别单一实例通常会迁移到第 2 代。
当 ASP.NET Core 应用启动时GC 会
为初始堆段保留一些内存。 在运行时加载时提交一小部分内存。 HttpClient
未正确使用 HttpClient 可能会导致资源泄漏。 系统资源如数据库连接、套接字、文件句柄等
比内存更短缺。在泄漏时出现的问题比内存更多。
经验丰富的 .NET 开发人员会对实现 IDisposable 的对象调用 Dispose。 未释放实现 IDisposable 的对象通常会导致内存泄漏或系统资源泄漏。
HttpClient 实现了 IDisposable但是不应在每次调用时进行释放。 而是应重用 HttpClient。
下面的api会对每个请求创建并释放新的 HttpClient 实例
[HttpGet(httpclient1)]
public async Taskint GetHttpClient1(string url)
{using (var httpClient new HttpClient()){var result await httpClient.GetAsync(url);return (int)result.StatusCode;}
}
上面的代码即使释放了 HttpClient 实例实际网络连接也需要一些时间才能由操作系统释放。 持续创建新连接时会发生端口耗尽。 每个客户端连接都需要自己的客户端端口。
防止端口耗尽的一种方法是重用同一个 HttpClient 实例
private static readonly HttpClient _httpClient new HttpClient();[HttpGet(httpclient2)]
public async Taskint GetHttpClient2(string url)
{var result await _httpClient.GetAsync(url);return (int)result.StatusCode;
}
HttpClient 实例会在应用停止时释放。
可以参阅以下内容了解处理 HttpClient 实例的生存期
HttpClient 和生存期管理HTTPClient 工厂博客 对象池
上面的示例演示了如何将 HttpClient 实例设为静态并由所有请求重用。 重用可防止资源耗尽。
对象池
使用重用模式。适用于创建成本高昂的对象。
池是预初始化对象的集合这些对象可以在线程间保留和释放。 池可以定义分配规则例如限制、预定义大小或增长速率。
下面的 API 会实例化 byte 缓冲区该缓冲区对每个请求使用随机数字进行填充
[HttpGet(array/{size})]public byte[] GetArray(int size){var random new Random();var array new byte[size];random.NextBytes(array);return array;} 可以使用 ArrayPoolT 创建 byte 缓冲区池从而优化上面的代码。 静态实例可在请求间重用。
此方法的不同之处在于会从 API 返回共用对象。 也就是说
从方法返回后对象会立即脱离控制。无法释放对象。
若要设置对象的释放请执行以下操作
将共用数组封装在可释放对象中。向 HttpContext.Response.RegisterForDispose 注册共用对象。
RegisterForDispose 会负责对目标对象调用 Dispose以便仅当 HTTP 请求完成时才会将其释放
private static ArrayPoolbyte _arrayPool ArrayPoolbyte.Create();private class PooledArray : IDisposable
{public byte[] Array { get; private set; }public PooledArray(int size){Array _arrayPool.Rent(size);}public void Dispose(){_arrayPool.Return(Array);}
}[HttpGet(pooledarray/{size})]
public byte[] GetPooledArray(int size)
{var pooledArray new PooledArray(size);var random new Random();random.NextBytes(pooledArray.Array);HttpContext.Response.RegisterForDispose(pooledArray);return pooledArray.Array;
} 主要差异是分配的字节数因而第 0 代回收数要少得多。