Questions about Unity WebGL texture memory usage

  1. I made a test scene that contains 10 large images (RGBA32), each of which is 16MB.

  2. Get the current memory usage from the code. Here we mainly observe MonoHeap and WebAssembly.Memory.

Question:
We can see that DynamicMemory has increased by 160M, and MonoHeap has not changed.
At the same time, the measurement of the entire process occupies an increase of 320MB. This means that gfx and main memory use 160MB respectively?

Through dev build, there is such an allocation stack. What I don’t understand is that after the texture is uploaded to the GPU, will the main memory of ShareTextureData continue to be occupied?

After analysis, the main memory should have been deleted. There is such a phenomenon:

  1. Using “_malloc()” in the js glue layer found that Heap(wasm.Memory) did not grow. Explain that the memory(unmanagerd or native) can be reused?
  2. But when memory is allocated in C#, Heap(wasm.Memory) will grow:
    byte[ ] TestArray = new byte[sizeInMB * 10];
    for (int i = 0; i != sizeInMB * 10; ++i)
    {
    TestArray = 1;
    }
    totalMem.Add(TestArray);
    Does this mean that Unity Native(unmanagerd or native) memory and C# use different memory pools? Although both of them come from Wasm.Memory, they can’t be shared?

Hi! The WASM heap memory is allocated in power of 2 chunks. What you’re seeing there is the current Total Heap Size=256MB. That doesn’t mean it’s all used by the mono memory manager. When it will need to allocate more than that it will bump the heap to 512MB. Your peak used memory size = GetStackMemorySize()+GetDynamicMemorySize() = around 180MB. You won’t see this number go down even though the garbage collection works and your actual current used mono heap size is smaller. Please take note that Profiler memory functions don’t work in release builds. You can try to make debug builds, but they are so bloated, they lose relevance in terms of metrics.
As for the textures you’re loading, you’re right that they are freed from WASM heap, as long as they are not read/write enabled textures. So, make sure you don’t have that enabled.

1 Like

Texuture does not have a read/write attribute. It stands to reason that WASM Memory has been recycled (although Heap remains unchanged).
If so, my second piece of code should be able to reuse the small array allocated in C#, and Heap may not continue to grow. The fact is that the array allocated by C# will cause Heap to continue to grow and cannot reuse the part of Texture freed.
What I guess is that the WASM memory released by Unity Native cannot be used by C#? Native and Mono are two independent memory pools in WASM.Memory and cannot be reused with each other?

In my impression, if I use the second piece of code to allocate C# memory, Profiler.MonoUsedSize has a value, but the decompressed texture is Unity Native memory so it is 0

Generally speaking, yes, the managed and native systems should be split and won’t reuse each other’s memory. The native memory is allocated in pools that might the in your case be empty but will only be reused for other native memory. The managed memory is allocated in heap chunks that might fragment. Not sure if Unity’s WebGL implementation does anything different with memory system but you might want to try this out in a Standalone build and check it out with the Memory Profiler Package?