Description
Context
Working on an attempt to improve array pooling strategies in ImageSharp. I wanted to use GCMemoryInfo.MemoryLoadBytes
in a similar manner as done by TlsOverPerCoreLockedStacksArrayPool
Issue
I have a small test app doing some stressing work by allocating and retaing arrays of 1MB, and querying GC.GetGCMemoryInfo
which seems to report weird values:
https://gist.github.com/antonfirsov/01bb6b7b8569027cd71988ff33c66228
My test environment: Windows 10, 64bit physical memory, i9 with 10 physical cores
A couple of unexpected things about GCMemoryInfo.MemoryLoadBytes
:
- .NET Core 3.1 + 32bit seems to be the only configuration, where it works as I would expect:
MemoryLoadBytes
is gradually scaling with my actual memory usage. - .NET 5.0/6.0 + 32bit:
GCMemoryInfo.MemoryLoadBytes
reports values 10-50 times higher than the actual memory usage. These values do not make sense in a 32 bit process. - 64 bit (3.1, 5.0, 6.0): after allocating the first array,
GCMemoryInfo.MemoryLoadBytes
immediately jumps to a constant ~21GB value which doesn't change even ifGC.GetTotalMemory()
passes that threshold.
TotalAvailableMemoryBytes
and HighMemoryLoadThreshold
are also weird:
- 3.1 + 32 bit: again, this is the only configuration that seems to report expected values: 2GB / 1.8 GB
- 5.0/6.0 32 bit: 64 GB / 59GB
- 64bit all versions: it's reported to 64 GB / 59 GB, but my test app is fine passing the 64GB threshold without an OOM, which makes me wonder about the semantics of
TotalAvailableMemoryBytes
. Is it only reporting the amount of physical memory on my PC without any impact on GC behavior?
Note that if the MemoryLoadBytes
issue is a bug, it must be breaking the pressure-triggered trimming of ArrayPool<T>.Shared
.
/cc @Maoni0