[英]Limit maximum memory usage for a C# method
有没有办法限制允许C#方法分配的最大内存? 我们正在处理复杂的用户提供的输入,我们意识到可以通过提供一定的特殊输入来帮助我们的服务。 我们无法检测到DoS攻击的所有变化,因此我们希望限制ProcessInput()
方法的处理时间和内存分配。
处理时间“简单”,我们只需运行一个计时器并通过CancellationToken取消ProcessInput操作。 但是,我们还没有找到(简单)内存分配的解决方案。 我们不想编写自己的内存管理器并使用对象数组或类似的东西。
GC堆是每个进程,而不是每个AppDomain - 所以为了正确估计,您需要生成一个单独的进程。
您甚至可以自己托管CLR以影响细分受众群规模并获取通知。 但是,如果在此过程中没有其他任何内容正在运行,那么您可以使用估计值GC.GetTotalMemory()。 然而,如果您对“在方法运行期间消耗的总内存”感兴趣,而不是“在任何时间点使用的最大总内存”,则需要在'NoGC'区域执行 - 因为GC可以在期间多次触发你的方法运行。
为了限制产生进程的性能/资源影响,您可以生成N个进程 - 其中N是您所需的并发级别 - 并且让每个进程从中央进程中的工作窃取队列中提取任务,而子进程同步处理请求。
一个肮脏的想法它是什么样的(你需要处理结果报告加上100个其他'次要'的东西):
主要流程:
public void EnqueueWork(WorkRequest request)
{
_workQueue.Enqueue(request);
}
ConcurrentQueue<WorkRequest> _workQueue = new ConcurrentQueue<WorkRequest>();
[OperationContract]
public bool GetWork(out WorkRequest work)
{
return _workQueue.TryDequeue(out work);
}
工人流程:
public void ProcessRequests()
{
WorkRequest work;
if (GetWork(out work))
{
try
{
//this actually preallocates 2 * _MAX_MEMORY - for ephemeral segment and LOH
// it also performs full GC collect if needed - so you don't need to call it yourself
if (!GC.TryStartNoGCRegion(_MAX_MEMORY))
{
//fail
}
CancellationTokenSource cts = new CancellationTokenSource(_MAX_PROCESSING_SPAN);
long initialMemory = GC.GetTotalMemory(false);
Task memoryWatchDog = Task.Factory.StartNew(() =>
{
while (!cts.Token.WaitHandle.WaitOne(_MEMORY_CHECK_INTERVAL))
{
if (GC.GetTotalMemory(false) - initialMemory > _MAX_MEMORY)
{
cts.Cancel();
//and error out?
}
}
})
DoProcessWork(work, cts);
cts.Cancel();
GC.EndNoGCRegion();
}
catch (Exception e)
{
//request failed
}
}
else
{
//Wait on signal from main process
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.