5 ms·
A design goal of Rust is to target the performance of well-written, safe C++. It doesn't (today) even ship with a garbage collector, discourages heap allocation
by wycats 12y ago
A design goal of Rust is to target the performance of well-written, safe C++. It doesn't (today) even ship with a garbage collector, discourages heap allocation (which is your only option in normal Go), and avoids dynamic dispatch in the vast majority of cases. In contrast, idiomatic Go code is garbage collected, heap allocation heavy, and dynamic dispatch heavy.
That isn't always going to mean that Rust code is faster, but for benchmark games like this, when Rust is slower it almost always means that the benchmark is wrong.
- SwellJoe 12y agoI read an article recently about memory in Go (the "why is my go program 138GB!?" article), which was enlightening and also weird. I don't have any experience with either language, but have plans to learn a smattering of both in 2015. As for dynamic dispatch...does Rust not support it, or is there some language construct that allows solving the problems dynamic dispatch solves without imposing annoying limitations or needless verbosity? And, aren't there fast implementations of dynamic dispatch?
- steveklabnik 12y agoRust supports both. You might enjoy reading http://programmers.stackexchange.com/a/247313 http://programmers.stackexchange.com/a/247313
- wycats 12y ago> As for dynamic dispatch...does Rust not support it, or is there some language construct that allows solving the problems dynamic dispatch solves without imposing annoying limitations or needless verbosity? Rust supports dynamic dispatch if you truly need it, but the normal approach is to use trait bounds, which the compiler expands when used. Here's an example: fn main() { let r = MemReader::new("hello world\n".as_bytes()); get_line(&r); } fn get_line<R: Buffer>(r: &R) -> IoResult<String> { r.read_line() } In this very simple example, the `get_line` function takes any value that implements the `Buffer` trait, which provides the `read_line` method. When `get_line` is called inside of `main`, the compiler creates a special version of `get_line` that takes a `MemReader`, and dispatches to its implementation of `read_line` statically. In practice, this feels a lot like dynamic dispatch, but using trait bounds always results in static dispatch in practice. Also, in this example, the `MemReader` is stack-allocated, and lent to the `get_line` method. In very rare cases, you may want dynamic dispatch. For example, imagine you have an array of Buffers, and want to read a line from each of them. In this case, you use a "trait object" (a `Box<Buffer>`), which moves the object to the heap and allows dynamic dispatch. In practice, I have written many thousands of lines of production Rust code and have only encountered a need for trait objects a handful of times. This means that idiomatic, normal Rust code is stack-allocated and statically dispatched. The verbosity of trait bounds has decreased more and more over time, and my favorite proposal (by aturon) for making it pretty close to maximally ergonomic is: fn main() { let r = MemReader::new("hello world\n".as_bytes()); get_line(&r); } fn get_line(r: &impl Reader) -> IoResult<String> { r.read_line() } I hope this lands as new syntax after 1.0 :)
- allan_s 12y agoit would indeed be great to have this syntax, can you link to the RFC if you have it? so that we can follow how is this proposal going.
- deleted 12y ago[deleted]
- tterrace 12y agoCould you link the "why is my go program 138GB!" article?
- dbaupp 12y agoI believe it's http://utcc.utoronto.ca/~cks/space/blog/programming/GoBigVirtualSize http://utcc.utoronto.ca/~cks/space/blog/programming/GoBigVir... Permalink to the relevant section of the Go source, with descriptive comments: https://github.com/golang/go/blob/04cf881fbea55d5bca584c78b15454b189af11f5/src/runtime/malloc1.go#L106 https://github.com/golang/go/blob/04cf881fbea55d5bca584c78b1...
- shanemhansen 12y agoTechnically it's not true that heap allocation is your only option on go. In Go you have 0 options but stack allocation is automatically done in some cases.
- TheHydroImpulse 12y agoYes, escape analysis does tend to eliminate some unnecessary heap allocations but they're specifically isolated to a single subroutine (it's better than not having it). Whereas with Rust, you can safely pass around references to stack allocated memory to other subroutines, given proper lifetimes.