使用 .NET 核心设置内存限制
Posted
技术标签:
【中文标题】使用 .NET 核心设置内存限制【英文标题】:Putting memory limits with .NET core 【发布时间】:2021-11-15 02:32:40 【问题描述】:我正在使用 ML.NET 构建一个用于二进制分类的 ML 应用程序。它将具有多个不同大小的 ML 模型(使用不同的训练数据构建),这些模型将作为 Blob 存储在 SQL Server 数据库中。客户端会随机发送物品到这个应用程序进行分类,并根据客户端ID,使用相应的模型进行分类。要对项目进行分类,需要从数据库中读取模型,然后将其加载到内存中。在内存中加载模型需要相当长的时间,具体取决于大小,我没有看到任何优化它的方法。因此,我计划将模型缓存在内存中。如果我缓存了许多重型模型,它可能会对内存造成压力,从而影响服务器上运行的其他进程的性能。所以没有直接的方法来限制缓存。所以寻找处理这个问题的建议。
【问题讨论】:
【参考方案1】:产生一个新进程
在我看来,这是完成您想做的事情的唯一可行选择。生成一个与您的“主应用程序”通信(通过 IPC?)的全新进程。您可以使用此属性 https://docs.microsoft.com/en-us/dotnet/api/system.gcmemoryinfo.totalavailablememorybytes?view=net-5.0 设置内存限制,或者甚至可以使用 3rd-party-library(例如 https://github.com/lowleveldesign/process-governor),如果它达到特定数量的 RAM,它将终止您的进程。这两种方法都很粗糙,基本上会杀死你的进程。
如果您可以控制边车应用程序的运行,那么使用 Getting a process's ram usage 之类的东西真正监控 RAM 使用情况并优雅地停止进程可能是有意义的。
自己动手解决方案(不推荐)
基本上没有内置的方式来限制线程或类似的内存使用。
内存限制计入什么?
共享资源
由于您有一个正在运行的进程,您需要定义内存限制的确切数量。例如,如果您有一些由正在运行的线程操作的静态Dictionary
- 它占用了什么?只有旧值和新值之间的差异?全新的价值?关键和价值?
还有更多这样的情况需要您考虑。
实测
您需要某种方法来计算实际内存使用量。这可能很难/几乎不可能“实施”:
需要引用计数吗?
如果你有一个敌对线程,它可能会产生对一个对象的无限量的引用,没有使用new
关键字。对于每个引用,您必须计算 32/64 位。
内置类型呢?
测量包含在您自己的类型定义中的byte[]
可能“容易”,但是内置类呢?如果有人初始化一个 100MB 的字符串,这可能是您需要跟踪的数量。
...还有更多...
正如您在之前的示例中可能注意到的那样,“线程使用的 RAM”没有简单的定义。这就是它的价值也不容易获得的原因。
在我看来,做这样的事情非常复杂,需要在你身边做很多定义工作。 很多 的努力可能是可行的,但我不确定这是否真的是你想要的。即使你设法 - 你会怎么做?仅杀死线程可能无法清理资源。
因此,我真的会考虑拥有一个由操作系统管理的独立进程,您可以随时杀死它。
【讨论】:
【参考方案2】:您的模型有多大?即使是 100meg+ 的大型模型,也可以很快从快速/SSD 存储中加载。我会考虑将它们缓存在快速驱动器/SSD 上,因为退出 SQL Server 将比原始磁盘慢得多。看看这是否有助于您的表现。
【讨论】:
以上是关于使用 .NET 核心设置内存限制的主要内容,如果未能解决你的问题,请参考以下文章