But what happens if your application is a memory consumer (and most GIS applications are)?
You may find out your application tends to crash and burn once reaching a memory signature of a little over 1GB.
It’s a common knowledge for developers (I hope) that a useful way to measure application’s true memory consumption is using the Task manager’s “VM Size” column (as the “Mem Usage” column only indicates the size of the application’s Working Set). So why does the application crash when supposedly there is still plenty of free memory?
There are 2 possible answers:
- Although a certain size of memory is allocated to the application, fragmentation to the memory may cause the application to actually consume more than that. This may also be related to the GC behavior in relation to 2nd generation objects, which I’ll discuss later.
- The VM Size column does not represent the actual Virtual address space allocated to the application, which is limited to 2-3GB on a 32bit OS. In addition to the allocated memory the OS may have designated addition shared memory (shared with other applications, but still counts towards the 2GB limit). To view the actual size of memory allocated by the OS to the application, use the Perfmon.exe tool’s Virtual Size counter:
The .Net Garbage Collector and 2nd generation (gen2) collections
The GC algorithm divides the allocated objects to 3 generations (0-2), when generation 0 objects are retrieved most frequently and “live” for the shortest amount of time. Generation 1 objects are collected less frequently and generation 2 collections are truely a rare occasion.
But when does the GC collects generation 2 allocations (”full” collection)? What triggers such a collection?
Surprisingly I found very little information of this subject, but the information I did find, combined with experimentation led to the conclusion such collection occurs when the overall system is low on physical memory.
Now, let’s consider the implications for a 4GB computer running a 32bit OS. While the gen2 heap may inflate over time (especially considering large objects are also collected only in gen2 collections), the GC will never trigger as a single application can never consume the entire amount of memory on the computer (being limited to 2GB). However, this may lead to a memory leak and eventually crashing the application (once it’s virtual address space reaches 2GB).
The solution? Call the GC.Collect() method yourself to trigger a full collection.