gpt4 book ai didi

c# - 如何减少C#程序中Sql连接池占用的内存量

转载 作者:行者123 更新时间:2023-11-30 14:58:02 26 4
gpt4 key购买 nike

我有一个 C# 程序,它充当多线程 Web 服务器。它对保存在 Sql Server 数据库中的 Xml 结构进行大量处理。

随着这些 Xml 结构的大小增加,我发现应用内存不足。

我已经部署了 ANTS 内存分析器来查看发生了什么,并设法减少了处理过程中内存中保存的大字符串的数量,并做了一些改进。

但是,我现在留下了一个碎片化的大对象堆,这是由连接池中保存的大字节数组引起的。大字节数组是

TdsParserStateObject._bTmp
in TdsParser._physicalStateObj
in SqlInternalConnectionIds._parser
in DbConnectionInternal[0]
in DbConnectionPool._objectList

我 99.9% 确定我只在 using 语句中使用连接,尽管我确实在线程运行时为每个线程打开一个连接(这是一种优化,但我怀疑它是否会使事情变得更糟).

我可以对连接做些什么来减少它持有的内存量(除了关闭或处置它之外)吗?

或者我应该总是在每次使用时立即关闭或处置每个连接?

[稍后 - 根据我的评论]我重构了代码,为每个数据库访问使用一个新连接,然后处理它(当然,事务除外,我从事务开始到结束使用相同的连接,并将其与事务一起处理)。

即使程序空闲(即没有使用中的连接),连接池中仍有连接占用大量内存,并导致碎片。

为什么已释放的连接会在连接池中占用 58MB 的内存?

[更晚]我有一个解决方案可以防止 Sql Server 连接池将大堆碎片化 - 这是为了检测哪些连接可能有一个巨大的缓冲区,并标记它们以便在处理时从池中删除,使用

SqlConnection.ClearPool(连接)

我目前以一种相当 hacky 的方式执行此操作,方法是将 DataReader 子类化并检测返回的任何字段的大小是否超过 10MB。

欢迎提出有关检测哪些连接具有大缓冲区的更好方法的建议。

请注意,我已经恢复了在每次访问数据库时打开和处理连接的更改,因为跟踪在事务内部使用哪个连接(显然必须是事务)正在做我的工作.

在线程开始时打开并在结束时关闭的连接很好,因为几乎所有线程都是短暂的(作为对单个 Web 请求的响应)。异常(exception)情况是无论如何都可能在单个事务的上下文中运行的批处理。

最佳答案

使用 ADO.NET 时无需保持连接打开。默认情况下,连接将被合并(除非您自己关闭合并),ADO.NET 将完成池的所有管理工作。您甚至不必担心不同的用户凭据等,因为只有在连接参数相同时才会合并连接。从内存使用的角度来看,处理连接只会有帮助。

更多相关信息:

关于c# - 如何减少C#程序中Sql连接池占用的内存量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19868282/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com