Closed nikii-me closed 10 months ago
It is, technically speaking, true that allocating GC memory is cheaper than allocating non GC one. This picture changes diametrically once we take the cost of freeing that memory. GC is relatively costly, when compared to freeing the memory in traditional ways.
Rust's borrow checker can be, roughly speaking, described as a compile-time GC. At the cost of being less flexible and taking longer to compile, Rust is able to automatically manage memory without GC. This tends to be significantly faster than a runtime GC.
Rust also has very strict rules on the order memory is being freed in. This can't be mimicked with finalizers.
The project does provide ways of interacting with managed memory (by using the interop layer mycorrhiza), although they are separate from unmanaged versions. One of the principles of Rust is to be explicit about how allocations happen, so managed allocations are easy to spot.
I have also enabled discussions.
Is the issue of freeing memory important in the context of the GC however? While it is true that it's more expensive than in unmanaged memory, I'm not sure if that exactly matters, given the GC does its own thing memory-wise. Unless its an issue impossible to adapt to Rust's systems, I don't think freeing memory would be that important
The borrow checker is a big selling point of Rust, and it is significantly faster than GC. See this post about discord switching from Go to Rust. Admittedly, the Go GC and .NET implementation differ, but this can provide a rough estimate of performance benefits.
I plan for this project to fit the niche of writing memory intensive .NET code. Rust not only would reduce the frequency of GC passes, it would also speed up each GC pass. During GC, a lot of memory needs to be scanned and moved. By storing most data in unmanaged memory, we avoid those moves.
Rust memory model is also not very compatible with the .NET one. Rust can have references to references, which is something that .NET forbids.
This is valid Rust code:
struct Inner{
a:i32,
}
struct Outer{
inner:Inner,
b:f32,
}
struct RefInner{
ref:&Inner,
}
fn test(){
let outer = Outer::default();
// Taking a reference to a field - OK in .NET and Rust
let ref = &outer.inner;
// Storing a reference to a field in a struct - valid Rust, invalid .NET!
let ref_inner = RefInner{ref:ref};
// Geting a reference to a reference - valid Rust, invalid .NET!
let ref_inner = &ref;
}
Fair enough, got nothing else to add
Hello, I am not sure as to where to ask about this, so I'm opening an issue as there isn't a discussion tab on this repo. What is the philosophy behind the usage of unmanaged memory in place of managed? Correct me if I'm wrong, but from what I know this brings a few issues onto the table, the biggest being performance hits (allocation is slower in unmanaged memory than managed), as well as interop with other .NET languages. Is there a reason why managed memory isn't used instead?