Live data from Hacker News

Speed of Rust vs. C

kornel.ski

251–260 of 546 posts

Re: Speed of Rust vs. C

#251

Earlier quoted context omitted.

No, I didn't. An fst is a compressed data structure, which means you use it in its compressed form without decompressing it first. If you ported the fst crate to C, it would use the same technique. And in C, you have to design your data structures to be mmap friendly anyway. Same deal in Rust. But this is moving the goal posts. This thread started with "you can't do this." But you can. And I have. Multiple times. And…

> which means you use it in its compressed form without decompressing it first. So your code operates directly on a block of raw bytes? I can see how that can work with mmap without much problems. My argument was more about structured data (created using the type system), which is a level higher than raw bytes.

> So your code operates directly on a block of raw bytes? I can see how that can work with mmap without much problems.

Correct. It's a finite state machine. The docs of the crate give links to papers if you want to drill down.

> My argument was more about structured data (created using the type system), which is a level higher than raw bytes.

Yes. You should be able to do in Rust whatever you would do in C. You can tag your types with `repr(C)` to get a consistent memory layout equivalent to whatever C does. But when you memory map stuff like this, you need to take at least all the same precautions as you would in C. That is, you need to build your data structures to be mmap friendly. The most obvious thing that is problematic for mmap structures like this that is otherwise easy to do is pointer indirection.

With that said, this technique is not common in Rust because it requires `unsafe` to do it. And when you use `unsafe`, you want to be sure that it's justified.

This is all really besides the point. You'd have the same problems if you read a file into heap memory. The main problem in Rust land with memory maps is that they don't fit into Rust's safety story in an obvious way. But this in and of itself doesn't make them inaccessible to you. It just makes it harder to reason about safety.

Re: Speed of Rust vs. C

#252

Earlier quoted context omitted.

It doesn’t say it “works badly” it says the borrow checker can’t protect against external modifications to the file while memory-mapped, which has a host of issues in C as well. You can mmap files in Rust just fine, but it’s generally as dangerous as it is in C.

I don’t get this obsession with “dangerous.” Honestly, what does that even mean? I think a better word is “error-prone.” Danger is more like, “oh my god a crocodile!”

There can be real danger when the code is used in certain applications. For example when controlling the gate of the crocodile cage in a zoo.

Re: Speed of Rust vs. C

#253

Earlier quoted context omitted.

> Doesn't this just move the hard part, the maintenance, configuration and understanding, to a different (and equally complex) abstraction layer? That's true indeed, but I find it more manageable that way. To me, managing independent processes instead of threads is especially powerful when the lifecycle of the concurrent work can vary. A typical example that happens quite often is when you have some kind of producer/…

You can make exactly this argument the other way around: If implemented with processes it becomes quite messy very fast. You end up with a bunch of processes that do whatever the hell they want, and need some complex orchestrator script to tell it how many processes you want, and need some notifications to the orchestrator to increase or decrease the number of workers With threads, you can have a main thread that rea…

> if you want more/less workers you just spawn worker threads to read from the queue.

My point is precisely that's its not trivial to do that.

You now need some signal mechanism to tell your main process to spawn or kill workers. That's an additional layer of complexity.

Things get even worse if you want to add new types of workers that were unplanned.

Say I want a new type of worker that is just a forwarder, or a new type of worker that stores the queue on disk for replaying it.

With a monolithic thread based design, you now need to stop your whole main and worker threads and start a newly built process that support these workers.

With a process based design, you just spawn a new worker process and point it to the existing shared memory without any interruption.

Re: Speed of Rust vs. C

#254

Earlier quoted context omitted.

C being barebones does not mean it is faster. Because it has such weak typing and gives a huge amount of programmer freedom, compilers have to do a lot of work to be able to understand a C program well enough to optimise it. Rust, on the other hand, requires the programmer to give the compiler more information about what they're doing. A very simple example: void foobar(struct foo *f) { f->a += 2; foo(); f->a += 2; b…

> Sadly, Rust doesn't do this by default due to problems with LLVM, but eventually it can. Can it, though? I keep hearing/reading FUD around both unsafe and Pin making it unlikely to ever be able to ubiquitously enable the noalias stuff.

Code affected by unsafe already has to go through `UnsafeCell` which disables most aliasing optimizations, and the stacked borrow semantics have explicit opt-outs for such cases. I don't believe there are any Rust semantic issues standing in the way of exploiting aliasing information in this way, just LLVM bugs (and the fact that its restrict model isn't currently equipped to handle the information at such a fine granularity).

Re: Speed of Rust vs. C

#255

Its just amusing, in this thread everyone with critical thinking and skeptical is down voted, even if one expresses himself moderately. It shows how much of zealots, Rust fanboys have become.

Can you point to some specific comments like this? None of the top threads seem to show this, as of this writing it's mostly about thread versus process parallelism and which kinds of conditions require unsafe.

Re: Speed of Rust vs. C

#256
post #142

> For example, in C I'd be tempted to reuse a buffer allocated for one purpose for another purpose later (a technique known as HEARTBLEED). You can do that in Java (with byte arrays) or in Common Lisp, so what is the point here? It is not practice in Java, Lisp nor in C and C++. > It's convenient to have fixed-size buffers for variable-size data (e.g. PATH_MAX) to avoid (re)allocation of growing buffers This is becau…

Any book you'd recommend to back up your claims?

"The C Programming Language" from K&R is something everyone should read, even if they are not fond of C.

"Expert C Programming" [1]. Not up to date, but written from a C compiler writer standpoint. A lot of references to why C (and libs) are the way they are.

[1] https://www.amazon.com/Expert-Programming-Peter-van-Linden/d...

Re: Speed of Rust vs. C

#257

Earlier quoted context omitted.

C being barebones does not mean it is faster. Because it has such weak typing and gives a huge amount of programmer freedom, compilers have to do a lot of work to be able to understand a C program well enough to optimise it. Rust, on the other hand, requires the programmer to give the compiler more information about what they're doing. A very simple example: void foobar(struct foo *f) { f->a += 2; foo(); f->a += 2; b…

Lately on another Rust thread somebody pointed out that C programs use a lot of indirection like pointers and vtable dispatches which actually detracts from the supposed mega-speed of the low-level C. I found that to be mind-blowing and felt stupid for not remembering that earlier.

I don't think vtables are often used in C.

Re: Speed of Rust vs. C

#258
post #26

"But the biggest potential is in ability to fearlessly parallelize majority of Rust code, even when the equivalent C code would be too risky to parallelize. In this aspect Rust is a much more mature language than C." Yes. Today, I integrated two parts of a 3D graphics program. One refreshes the screen and lets you move the viewpoint around. The other loads new objects into the scene. Until today, all the objects were…

But Rust works badly with mmapped (memory-mapped) files, as the article notes. So in C you could load (and save!) stuff almost instantly, whereas in Rust you still have to de-serialize the input stream.

In C you can access pointers to memory mapped files effortlessly in ways that are often extremely unsafe against the possible existence of other writers and against the making being unmapped and mapped elsewhere. It’s also traditional to pretend that putting types like int in a mapped file is reasonable, whereas one ought to actually store bytes and convert as needed. Rust at least requires a degree of honesty.

Re: Speed of Rust vs. C

#259
post #122

Earlier quoted context omitted.

Dynamic linking is one thing I miss from Swift - I used dynamic linking for hot code reloading for several applications, which resulted in super fast and useful development loops. Given Rust's sometimes long compile times, this is something which would be welcome.

There are crates for hot reloading in Rust, and they use dynamic linking.

Do you have to stick to a C-FFI like interface, or can they handle rust-native features like closures and traits?

Re: Speed of Rust vs. C

#260

Earlier quoted context omitted.

But Rust works badly with mmapped (memory-mapped) files, as the article notes. So in C you could load (and save!) stuff almost instantly, whereas in Rust you still have to de-serialize the input stream.

is it something deeply ingrained to rust? or is it something rust is working on?

The problem is that compilers are allowed to make some general assumption about how they're allowed to reorder code, always based on the assumption that no other process is modifying the memory. For example, the optimizer may remove redundant reads. That's a problem if the read isn't really redundant -- if the pointer isn't targeting process-owned memory, but a memory mapped file that's modified by someone else. Programs might crash in very "interesting" ways depending on optimization flags.

C has this issue as well, but Rust's compiler/borrow checker is particularly strong at this kind of analysis, so it's potentially bitten even harder.

Post reply on HN