Limiting the maximum memory used by a C# program

Viewed 654

I need to limit the maximum memory used by a C# program, that is, to arrange so that if its memory consumption goes over a certain limit, it will crash immediately rather than keep requesting more from the operating system.

(The code is already correct and efficient, but the memory consumption varies unpredictably at runtime depending on the input data. Some input data sets, it correctly concludes after using only a few megabytes. Others would cause it to use many terabytes. In practice, this means it will grind the entire machine to a halt while the virtual memory system tries frantically to satisfy the requests, and then crash. I want the program to crash immediately, without going through the 'grind the entire machine to a halt' part.)

This is running on 64-bit Windows; the limit should actually be, in most cases, somewhere in the tens of gigabytes, but the following test case tries to allocate one gigabyte; I'm trying to get it to crash rather than satisfy this request.

C:\t>type a.cs
using System;

class a
{
    static void Main(string[] args)
    {
                var a = new byte[1024*1024*1024];
                a[0] = 5;
                Console.WriteLine(a[0]);
    }
}

C:\t>csc a.cs
Microsoft (R) Visual C# Compiler version 3.5.0-beta4-20153-05 (20b9af91)
Copyright (C) Microsoft Corporation. All rights reserved.

https://docs.microsoft.com/en-us/dotnet/core/run-time-config/garbage-collector suggests that there is actually a way to set this as a runtime parameter, by specifying it in a file called runtimeconfig.json. Some parts of the documentation suggest the file name needs to be prefixed with the program name, and some don't; I'm trying it both ways.

C:\t>type runtimeconfig.json
{
   "runtimeOptions": {
      "configProperties": {
         "System.GC.HeapHardLimit": 209715200
      }
   }
}

C:\t>type a.runtimeconfig.json
{
   "runtimeOptions": {
      "configProperties": {
         "System.GC.HeapHardLimit": 209715200
      }
   }
}

The documentation also suggests this can be done by setting an environment variable.

C:\t>set DOTNET_GCHeapHardLimit=C800000

But none of the above has any effect.

C:\t>a
5

Am I missing something about how to use the above? Or is there some other way to impose a limit on maximum memory usage?

2 Answers

Assuming you are using powershell (tested with .net 6):

  1. $Env:DOTNET_GCHeapHardLimit = 0x2000000
  2. run your program.
  3. to check it is working in your c# code use: Console.WriteLine($"{GC.GetGCMemoryInfo().TotalAvailableMemoryBytes}");

You might also need to consider limiting the number of heaps (DOTNET_GCHeapCount)

Looking at an earlier .NET 6 console project I created in VS2022 called Mime.exe, during the build it creates a Mime.runtimeconfig.json file in the output directory. So definitely prefixed with the name of the executable. For reference, this is the content with a working heap limit:

{
  "runtimeOptions": {
    "tfm": "net6.0",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "6.0.0"
    },
    "configProperties": {
      "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
      "System.GC.HeapHardLimit": 1000000
    }
  }
}
Related