3 ms·
I am curious if there is a way to discard GC and free the memory by hand. This article might point me in the right direction to disable GC, but freeing memory
by DeathArrow 2y ago
I am curious if there is a way to discard GC and free the memory by hand.
This article might point me in the right direction to disable GC, but freeing memory can't be as simple.
- Dwedit 2y agoIf you really really want to, you can use Marshal.AllocHGlobal and allocate unmanaged memory. All access happens through pointers and `unsafe` code blocks.
- neonsunset 2y agoYou're supposed to use NativeMemory.Alloc/.Free methods instead. Obviously nothing prevents you from PInvoking malloc and free directly, or linking to a custom allocator, or even using https://www.nuget.org/packages/TerraFX.Interop.Mimalloc https://www.nuget.org/packages/TerraFX.Interop.Mimalloc which is a fully managed Mimalloc implementation (which is competitive with the original). There is also an advanced undocumented API to register a specific segment of memory as nongc-heap where you can allocate otherwise managed objects manually. But the most important thing to understand that normally in languages with generational GCs the objects are not freed, instead, the surviving objects are copied to an older generation while the rest of the memory is reclaimed and immediately made available for subsequent allocations. As a result, you can't "free" an object since such operation does not exist in the design. Overall, you're not forced to use objects in low-level code - structs can implement methods, interfaces, used in generics for zero cost abstractions,etc., and if you don't allocate or allocate only a little - the GC will never run.
- algorithmsRcool 2y agoI didn't realize that the GC copied the surviving objects to a separate location. Come to think of it, i don't actually know how the GC keeps track of what object lies in what generation.
- mystified5016 2y agoGC is free to move things all over memory, though I'm not savvy enough to say why this is necessary. C# allows you to "pin" a variable to combat this. Any pinned memory will never be moved by GC, so if you pass a pointer to an object out of your managed program, the pointer address will always stay valid.
- Dwedit 2y agoIf you can't move objects around in memory, you get memory fragmentation.
- kevingadd 2y agoModern C# has Span<T> and Memory<T> types to give you the ability to work with unmanaged memory without directly touching pointers or `unsafe`, FWIW. Worth messing with the next time you need to do it.
- pjc50 2y agoSee https://medium.com/@MStrehovsky/building-a-self-contained-game-in-c-under-8-kilobytes-74c3cf60ea04 https://medium.com/@MStrehovsky/building-a-self-contained-ga... (someone got very mad on Reddit when I posted this as proof that you can build C# applications without a GC)
- mystified5016 2y agoYou actually have a lot of control over the C# GC. One common technique is to suspend GC before entering a tight loop and then manually running GC when your program has downtime. For instance, you might pause GC during your game's frame render routine, then unpause in the space between frames. Otherwise, GC runs when it feels like it, which always seems to happen in an inconvenient place that causes visible stutter. You also have the concept of "pinning" a variable, which prevents GC from moving it around memory (for instance, if you pass a very long-lived pointer out of C#, you might want to pin it so the pointer address is always constant). So you can suspend and resume GC globally, you can manually run GC at any time, and you have ways of exempting certiain objects from GC. I don't know offhand if you can GC one specific object manually, but I would be very surprised if you couldn't. Also, all of the above is considered very bad practice. As a rule of thumb, you are not smarter than the GC and you will do a worse job unless you are very sure of what you're doing.
- Dwedit 2y agoThe thing really needed is a "Collect with timeout" function. Something like "Garbage collect now, but abandon the job in a consistent state if X milliseconds have passed". (Perhaps even some other event. Like "Do GC until a File IO operation finishes")
- kevingadd 2y agoI think this is referred to as Incremental GC, and runtimes like Spidermonkey, V8 and Lua have it. I'm not sure whether there's any hope of getting it for .NET or whether Java has one though.