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

标签 c# .net

有没有办法限制允许 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
        }
    }

关于c# - 限制 C# 方法的最大内存使用量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46463758/

相关文章:

c# - 过滤 ICollectionView 中的重复条目

.net - 从 3.5 调用 .NET 4 库

.net - 为 Citrix/终端服务器编程 .NET 应用程序 : Compliance and Pitfalls

c# - 以编程方式使用选中的选项填充 CheckBoxList

.net - log4net ADO.NET Appender 在 Dev Fabric 上工作,但在 Azure 上无提示地失败

c# - 在 APK 中保护字符串

c# - Monotouch 和异步 CTP

c# - 内联构造函数和 InjectFrom 调用返回对象

c# - 将 .net 4.0 语法 OfType 转换为 .net 3.5

c# - WPF TextBlock 中的自动垂直滚动条?