8 ms·
Rust is not fast
- gnur 13y agoI cannot know for sure but this seems like a post of someone trying to write rust like you write a different language. The idioms are different and if you stick to your old routine it won't work like you would want to.
- chalst 13y agoAnd the reason you can't know is that he says nothing concrete, in the sense that none of his criticisms are grounded in examples.
- cscottnet 13y agoPlease see http://cananian.livejournal.com/68747.html http://cananian.livejournal.com/68747.html and https://github.com/cscott/rusty-turtle https://github.com/cscott/rusty-turtle. Yes, the post is brief since it was written from notes several months after I had been talking to the rust guys. I couldn't justify the time to spend making the examples more concrete (and wasn't exactly encouraged to do so at the time). Sorry, that is as far as I've carried the load, you've got to take it from here.
- Pxtl 13y agoThe "message-only parallelism oops we need shared memory" thing seems to be a common problem - at the beginning every language thinks they don't need the hellish headache of shared memory. This is not new - Ada went through this like 25 years ago.
- pcwalton 13y agoYeah, we went through the same thing. But what's curious about this post is that Rust had safe shared memory for almost a year at the time it was written. I actually think one of the most interesting parts about Rust is its shared memory story: if you use mutex-protected shared memory, the compiler enforces that you take the locks properly, eliminating data races.
- DanWaterworth 13y ago> the compiler enforces that you take the locks properly, eliminating data races. I assume you don't mean the compiler prevents deadlocks, but I'd be very happy to be proved wrong.
- kibwen 13y agoHere's a rather old post that describes the kinds of races that the Rust compiler prevents: http://winningraceconditions.blogspot.com/2012/10/what-is-data-race-and-when-is-race-not.html http://winningraceconditions.blogspot.com/2012/10/what-is-da... "[...] Rust's type system guarantees that concurrent tasks cannot share state but instead must use message-passing to communicate, which precludes the possibility of data races completely by enforcing happens-before relationships on all data accesses (or in the case of this post,[1] by enforcing mutual-exclusion relationships). Yet it's still possible to write nondeterministic programs in Rust (using select2, failure propagation, etc), and so race conditions are still possible." ...Though I'm not sure if this is all that pcwalton is referring to. [1] http://winningraceconditions.blogspot.com/2012/09/rust-4-typesafe-shared-mutable-state.html http://winningraceconditions.blogspot.com/2012/09/rust-4-typ...
- pcwalton 13y agoYeah, we don't prevent deadlocks. Stylistically, we try to avoid mutex locks for this reason, but sometimes you need them, so they're there.
- pcwalton 13y agoUnsurprisingly, I disagree with most of this post. * The part about Rust having no shared memory is just wrong. Rust has a very rich set of concurrency primitives at this point: you can use immutable shared memory (Arc), mutexes (MutexArc), reader-writer locks (RWarc), and atomic variables (AtomicInt and friends). And if you're willing to drop down to unsafe code, you get the full set of LLVM concurrency primitives. * The complaint about smart dereferencing strikes me as odd. Almost every new systems language—Objective-C, D, Go, and Rust (and also Nimrod I think?)—does the same thing that Rust does in that the "." operator also works on pointers. It's type-directed: if you don't know whether you're working with a pointer or not, just go look at the type of the value you're working with. If you don't know a value's type, then you have much bigger problems than knowing whether you'll get an extra memory access on ".". Hiding the difference between a memory access and a cheaper operation is something compilers have done ever since the invention of register allocation. * I don't know what the complaint about "bugs with small objects" is, but all word-sized objects were made into LLVM Values a while back, making us as efficient there as you can be. Unless I'm misunderstanding the complaint. * Doing code duplication to accommodate different types of smart pointers doesn't work. The smart pointers have different semantics: that's why they exist in the first place. You can't just copy and paste your code. * The GC in Rust does need work. But so does C++'s GC and nobody is saying "C++ is not fast" because of it. About the only part I agree with is is "fork-join parallelism and work-stealing should be better supported". This is an area we'll need to flesh out more fully at some point. Note that there is now a much more advanced work-stealing scheduler. (It's not using the most efficient data structures for work stealing yet though.)
- tete 13y agoA few small addendum: * Objective-C is from 1983, do you? It's not exactly new. ;) * Nimrod is pretty fast and as the only language even supports soft-realtime applications out of the box. Besides that it feels the nicest to use and has a fat standard library with stuff like Redis. Sorry, I only played with that language, but already feel like a fanboy * About GC. Yes, that's a problem of all newer languages, but whatever implementation you choose there are advantages and disadvantages and which one is the right one also depends a lot on the language itself. Sometimes you are better off with your big fancy algorithm and sometimes you really just want good old reference counting. But yeah, GC is the big great topic and I am sure it will be for the next few decades.
- emillon 13y agoThe big problem for me is the compilation time, which is very slow (this may or may not be because the compiler itself is written in Rust). I dedicated a few days to hacking on rustc this summer, and while the tooling and community are very nice, the compilation times are really high. Git pull && make ? 20 min. Edit a file && make ? 5 min. IIRC the major was that metadata got serialized/unserialized all the time, but anyway it's one of the priorities. I'll hack again on it with pleasure when I'll have more time.
- kibwen 13y ago> this may or may not be because the compiler itself is written in Rust Well, due to the nature of self-hosting compilers, it's certainly greatly exacerbated by being written in Rust. :) To wit, a self-hosting compiler must actually compile itself no less than three times to ensure that the generated artifacts "converge" upon a single point. This is as true for Rust as it is for GCC.
- graue 13y agoThree times, so: 1. Old version compiles new version 2. New version, compiled by old version, compiles new version 3. New compiled by new-compiled-by-old compiles new version I hadn't heard of this before and initially didn't see why #3 is special. But I guess the idea is, the output object code is a function of both the input source code and the compiler version. And those two are the same for #2 and #3. So you expect the output of both #2 and #3 to be identical, and if it's not, that's a bug in the compiler. Is that how it works?
- asdfs 13y agoYes, the third compile is effectively a single very large test.
- tete 13y agoAnd Go is even slower, so what? If you want to squeeze out every little bit of performance, use C and not a fairly young, mostly unoptimized, heavily changing, not-yet-1.0 language.
- cliffbean 13y agoHe complains about message-passing being prone to races, when earlier in that same paragraph he complains about the lack of shared memory between tasks? It sounds like he has some legitimate concerns, but this blog post reads more like a rant than a considered criticism.
- kibwen 13y ago> This post is written from my experience with Rust in May 2013. This post is based on an experience with a version of Rust with the old runtime, with pervasive internal iterators, with managed pointers (which we haven't recommended using for years, and are in the process of chucking out), and is missing all the perf work we've achieved over the past six months. Suffice to say, any experience with Rust (especially in terms of performance) from that long ago is so dated by this point as to be completely unrepresentative. That isn't to say that Rust is fast yet, because we refuse to say that until we're as fast as C++. But a headline like this seems needlessly sensational (perhaps consider "Performance pitfalls in the implementation of Rust 0.6").
- deleted 13y ago[deleted]
- cscottnet 13y agoOh, look, my rant finally got noticed. ;) First off -- yes, it is a rant. I actually had some more nuanced in-person conversations, but those aren't nearly as fun to post. So you get the version that was fun for me to write. Sorry. That said, I'm glad to hear Rust is all wonderful now. It sounds like pcwalton agrees with most of my points and got them fixed. Kudos. I look forward to better GC, fork-join parallelism, and work-stealing. It doesn't seem like anything significant was done with the type system, though. How does Rust handle "find_and_insert" now? If folks are interested in actually critiquing code style, feel free to check out the rusty-turtle code at http://cananian.livejournal.com/68747.html http://cananian.livejournal.com/68747.html. I disagree that I was trying to write Rust as if it were some different language -- my frustration was in part because I was trying to write things with Rusty ownership types, etc, and getting that to work properly was so frustrating (and the error messages so opaque). If I just stuck managed boxes around everything my life would have been simpler -- but then I would not have been programming in Rust, really. I'm interested to hear more discussion on the primary point made in my blog: is Rust supposed to be 'safe and fast'? Or just 'safe'?
- mattgreenrocks 13y ago> I actually had some more nuanced in-person conversations, but those aren't nearly as fun to post Meta: I'm pretty disappointed with this sentiment. I would have loved to read those discussions instead of a rant. They seem far more intellectually honest.
- cscottnet 13y agoSorry, I gave Mozilla about 3 weeks of free work, then travelled to SFO and talked with Rust folk in person. That's a lot of donated time. I was working on another project by the time I wrote this post (from my written notes). Try not to look the gift horse in the mouth.
- kibwen 13y ago> I'm glad to hear Rust is all wonderful now. Nope, we're not saying that yet, Rust still needs a ton of work! > How does Rust handle "find_and_insert" now? Google doesn't return any obvious results for this string, what is it supposed to do? > is Rust supposed to be 'safe and fast'? Or just 'safe'? If Servo (written in Rust) isn't faster than Gecko (written in C++), then Mozilla won't continue funding Rust. Rust needs to be fast in a very existential way. :) And it will be! Initial benchmarks of Servo's performance are incredibly promising (pcwalton could go into more detail here), and there's still bushels of low-hanging fruit to be plucked.
- eonil 13y agoI don't care performance a lot if it's sane enough. At least for me, I would use Rust if it supports (1) safe and nice symmetric coroutine with automatically growing stack (2) devices for correct programming - such as const-correctness. (3) a device guarantees safe communication between threads - like Go channel. (4) stable implementation. (5) full support for C interop. AFAIK, Rust now has all except #4. So I am waiting it to be stabilized. Actually I want something like C++ with symmetric coroutine, but D is too unstable for coroutine…
- sixbrx 13y agoI've been using Rust for finite element method research, and I've been pretty happy with the results, the code is faster than my previous effort in Julia. That may be somewhat of a second system effect, though. I had trouble with detecting in Julia what the effect of the garbage collector was, I don't know if that's improved or not. The code in Rust has no shared/gc usage at all, so I'm pretty sure what the effect of garbage collection is :) One thing I like about Rust is that it makes doing allocation-free performance-critical calculations somewhat easier and safer. This is because I can preallocate my data before critical loops, inside the constructors of implementation objects, then hand out borrowed, non-mutable pointers to this data to clients from these objects. That way the clients don't have to pass in buffers to use, which is none of their business -- it would break encapsulation for them to even know what kind and how large of buffers to pass. The clients cannot detect that they are actually receiving a pre-allocated, shared buffer. In other languages that would ordinarily be very dangerous without extra effort, because if they or some other code turned around and called routines that used that same pre-allocated buffer again, then the data would be silently written over, in an "action at a distance" way which would be a nightmare to maintain. But Rust "freezes" the contents behind the immutable borrow, making sure that it can't be borrowed mutably again and thus cannot be changed, while the immutable borrow is in use, from anywhere in the program, all resolved at compile time. This allows getting very aggressive with the pre-allocation strategy.
- kibwen 13y agoThis is fascinating. If you ever have the time, would you be willing to post this along with some of your code to the mailing list (https://mail.mozilla.org/listinfo/rust-dev https://mail.mozilla.org/listinfo/rust-dev)? We love getting informative feedback like this. And if you have any suggestions for improvement, we entertain those as well. :)
- sixbrx 13y agoI'd be happy to, I'll make the code somewhat presentable and post a message to the list sometime soon.