繁体   English   中英

限制C#方法的最大内存使用量

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM