Skip to content

Latest commit

 

History

History
169 lines (135 loc) · 4.86 KB

dotmemory.md

File metadata and controls

169 lines (135 loc) · 4.86 KB

dotMemory

↑ dotMemory is a .NET memory profiler.

Table of contents

Generating large strings to fill up LOH

Set memory limit to 300 MB using System.GC.HeapHardLimit setting inside runtimeconfig.template.json config:

{
  "configProperties": {
    "System.GC.HeapHardLimit": 300000000
  }
}

Code of /api/generate-large-strings minimal API endpoint:

public static class GenerateLargeStringsEndpoint
{
    public static void GenerateLargeStrings(this IEndpointRouteBuilder builder, string routePattern)
    {
        builder.MapPost(routePattern, (ILoggerFactory loggerFactory) =>
            {
                var logger = loggerFactory.CreateLogger(nameof(GenerateLargeStringsEndpoint));
                logger.LogInformation(
                    $"TotalAvailableMemoryBytes: {GC.GetGCMemoryInfo().TotalAvailableMemoryBytes}");

                var list = new List<string>();
                var counter = 1;

                while (true)
                {
                    var randomString = RandomNumberGenerator.GetString(
                        choices: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
                        length: 10_000_000);

                    list.Add(randomString);
                    logger.LogInformation("Added string " + counter);

                    counter++;

                    Thread.Sleep(500);

                    if (counter > 10)
                    {
                        break;
                    }
                }

                logger.LogInformation("Broke the loop");

                return Results.Ok();
            })
            .WithOpenApi(x => new OpenApiOperation(x) { Summary = "Generate large strings" });
    }
}

// Output:
// 
// [22:22:05 INF] TotalAvailableMemoryBytes: 300000000
// [22:22:07 INF] Added string 1
// [22:22:09 INF] Added string 2
// [22:22:12 INF] Added string 3
// [22:22:14 INF] Added string 4
// [22:22:16 INF] Added string 5
// [22:22:19 INF] Added string 6
// [22:22:21 INF] Added string 7
// [22:22:23 INF] Added string 8
// [22:22:25 INF] Added string 9
// [22:22:27 INF] Added string 10
// [22:22:28 INF] Broke the loop

Setting heap hard limit to 100 MB throws OOM exception on the first endpoint call. OOM exception does not cause process crash though.

[22:43:37 INF] TotalAvailableMemoryBytes: 100000000
[22:43:38 INF] Added string 1
[22:43:40 INF] Added string 2
[22:43:42 INF] Added string 3
[22:43:44 INF] Added string 4
[22:43:45 ERR] HTTP POST /api/generate-large-strings responded 500 in 7627.7617 ms
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
...
...

Memory diagram after calling /api/generate-large-strings endpoint 3 times:

Memory diagram

Generate large arrays of class and struct

class

public class Class
{
    public int Id { get; set; }
}
public static class GenerateLargeArrayEndpoint
{
    public static void GenerateLargeArray(this IEndpointRouteBuilder builder, string routePattern)
    {
        builder.MapPost(routePattern, () =>
            {
                var array = new Class[10_000_000];
                for (var i = 0; i < 10_000_000; i++)
                {
                    array[i] = new Class { Id = i };
                }

                return Results.Ok();
            })
            .WithOpenApi(x => new OpenApiOperation(x) { Summary = "Generate large arrays" });
    }
}

Profile after calling endpoint about ten times:

Memory diagram

struct

public struct Structure
{
    public int Id { get; set; }
}
public static class GenerateLargeArrayEndpoint
{
    public static void GenerateLargeArray(this IEndpointRouteBuilder builder, string routePattern)
    {
        builder.MapPost(routePattern, () =>
            {
                var array = new Structure[10_000_000];
                for (var i = 0; i < 10_000_000; i++)
                {
                    array[i] = new Structure { Id = i };
                }

                return Results.Ok();
            })
            .WithOpenApi(x => new OpenApiOperation(x) { Summary = "Generate large arrays" });
    }
}

Profile after calling endpoint about seventeen times:

Memory diagram