Project Snowflake: Non-blocking safe manual memory management in .NET

Project Snowflake: Non-blocking safe manual memory management in .NET by Matthew Parkinson, Kapil Vaswani, Manuel Costa, Pantazis Deligiannis, Aaron Blankstein, Dylan McDermott, Jonathan Balkind, Dimitrios Vytiniotis:

Garbage collection greatly improves programmer productivity and ensures memory safety. Manual memory management on the other hand often delivers better performance but is typically unsafe and can lead to system crashes or security vulnerabilities. We propose integrating safe manual memory management with garbage collection in the .NET runtime to get the best of both worlds. In our design, programmers can choose between allocating objects in the garbage collected heap or the manual heap. All existing applications run unmodified, and without any performance degradation, using the garbage collected heap. Our programming model for manual memory management is flexible: although objects in the manual heap can have a single owning pointer, we allow deallocation at any program point and concurrent sharing of these objects amongst all the threads in the program. Experimental results from our .NET CoreCLR implementation on real-world applications show substantial performance gains especially in multithreaded scenarios: up to 3x savings in peak working sets and 2x improvements in runtime.

Rather than trying to solve safe manual memory management using compile-time reasoning, you can move some of it into the runtime and raise dynamic failures on use-after-free and other hazards. With some judicious special types that track ownership and a type of borrowing, and some reasonable restrictions on how these types can be handled, you can achieve a nice framework for integrating manual and automatic memory management. The performance benefits for large heaps looks pretty clear.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Mark phase

I saw the video but didn't watch it to the end. It mostly looks like a solution where you give the programmer an explicit mark construct in the form of delete. I.e., you push mark to the front and maybe don't need that phase anymore but you need a sweep still.

I don't think it will make it into C#'s runtime.

Each thread has a TLS buffer

Each thread has a TLS buffer of "shielded" (borrowed) references, and this buffer is used during marking for the owner handles, IIRC. I think the owner handles refcount how many shielded refs are made, so you get immediate reclamation semantics if no shields exist.

It probably won't go anywhere, but it shows that manual and automatic memory management can integrate quite nicely, and you can enjoy many of the benefits of manual memory management without introducing unsafety.