Live data from Hacker News

Performance of Rust Language [pdf]

github.com

71–80 of 146 posts

Re: Performance of Rust Language [pdf]

#71
post #5

There's a discussion of "delayed bounds checking", but not "hoisted bounds checking", where bounds checking is done early. Consider let mut tab: [usize;100] = [0;100]; ... for i in 0..101 { tab[i] = i; } This must panic at i=100. Panic becomes inevitable at entry to the loop. Is the compiler entitled to generate a check that will panic at loop entry? The slides suggest that Rust does not hoist such checks, and, so, w…

On https://godbolt.org/ select Ada and compiler option "-O2"

    function Square(num : Integer) return Integer is
        tab : array (0..100) of integer;
    begin
        for i in 0..101 loop 
            tab(i):=i; 
        end loop;
        return tab(100);
    end Square;
The assembly code generated is :

    sub     rsp, 8    #,
    mov     esi, 11   #,
    mov     edi, OFFSET FLAT:.LC0     #,
    call    "__gnat_rcheck_CE_Index_Check"  #
Loop is not run and exeption handler is called directly.

Link : https://godbolt.org/z/qT4TsKPxz

Re: Performance of Rust Language [pdf]

#72

Earlier quoted context omitted.

Nim also has top notch meta programming, probably more so than Zig. You can easily do loop unrolling, specialization, etc. For example Constantine, which is a constant time crypto library that outperforms C, etc. To me programming Rust feels so limiting due to lack of good compile time meta programming with types . That’s the key.

How can you create constant-time code with Nim when none of its backends support it (e.g. LLVM may turn an apparently-constant-time code into non-constant-time assembly)?

You can see all the details at: https://github.com/mratsim/constantine , but to answer your "how" question briefly here, something Nim shares with most (all?) "systems programming languages" is "easy" integration with assembly languages -- whatever the backend for "most" compiled code is (whatever that "most" even is - weighted by any number of measures of static source size or dynamic instruction counts). Of course, hand-rolled assembly can cost you a lot in portability/effort to port to new platforms/etc.

The entire concept of the "performance of a PLang" in terms of the run-time of programs written "mostly in it" is rather seriously under-specified, TBH. This is (or should be) uncontentious in spite of the slew of articles with titles like the one for this thread.

Re: Performance of Rust Language [pdf]

#73
post #72

Earlier quoted context omitted.

How can you create constant-time code with Nim when none of its backends support it (e.g. LLVM may turn an apparently-constant-time code into non-constant-time assembly)?

You can see all the details at: https://github.com/mratsim/constantine , but to answer your "how" question briefly here, something Nim shares with most (all?) "systems programming languages" is "easy" integration with assembly languages -- whatever the backend for "most" compiled code is (whatever that "most" even is - weighted by any number of measures of static source size or dynamic instruction counts). Of course,…

Exactly, Constantine generates assembly output and links that into normal Nim objects (e.g. C). That can then used in Nim or in Rust, Go, etc.

From its "Why Nim" in the readme:

- Assembly support either inline or a simple {.compile: "myasm.S".} away

- No GC if no GC-ed types are used (automatic memory management is set at the type level and optimized for latency/soft-realtime by default and can be totally deactivated).

- Procedural macros working directly on AST to create generic curve configuration, derive constants write a size-independent inline assembly code generator

Re: Performance of Rust Language [pdf]

#74
post #11

Earlier quoted context omitted.

C++ you get templated generic algorithms that in practice no one really does with C because macros suck too much. So in C typically you'd have a runtime generic routine that doesn't inline. A classic example here is qsort() vs std::sort().

Rust also has these advantages of course

Right. I'm mostly addressing GP's first question about C and C++.

Re: Performance of Rust Language [pdf]

#75
I find the real issue with Rust is the compiler performance. I decided to use it for a project, and frankly I have huge regrets now that it's grown big enough. It literally takes over a minute to compile on my M1 laptop.

I just don't understand how people find this sort of thing normal. If you implement a feature, and then you want to see it in action, the feedback loop for that is insanely slow. It's incredibly jarring coming from Clojure where you have a live development experience.

I've used Go before, and while you still have to wait for compiling, at least the compiler is actually fast.

I get the problem Rust aims to solve, but the ergonomics are just not there in my opinion.

Re: Performance of Rust Language [pdf]

#76

Earlier quoted context omitted.

LTO cannot change the layout of structs. For something like a hash map implementation, it matters whether inner nodes store a pointer to the key and value, or whether it stores a pointer to each. To achieve this in C, you have no other options than emulating templates using macros.

The question is whether a hash-map implementation that works on a general `[key, index]` item and where index references at separate array of values isn't actually better for some access patterns ;) And of course the other alternative to macros is code-generation (but macros are actually often fine). But this also only matters for actually reusable generic code. If I'd implement a super-hot-path hashmap in C, I would…

Sure, but now you're actually moving the goal posts. We're talking about the practicalities - you can always achieve the same by doing more work, but it makes a difference that Rust gives you `HashMap` in the standard library that you can just use and get best-in-class performance, every time, with zero work, zero maintenance. The only choice you have to make is which hash function you want to plug into it, and since it is generic, that gets optimized and inlined as well (even with LTO disabled).

Re: Performance of Rust Language [pdf]

#77
post #75

I find the real issue with Rust is the compiler performance. I decided to use it for a project, and frankly I have huge regrets now that it's grown big enough. It literally takes over a minute to compile on my M1 laptop. I just don't understand how people find this sort of thing normal. If you implement a feature, and then you want to see it in action, the feedback loop for that is insanely slow. It's incredibly jarr…

Yeah rust has issues. Have you tried splitting your project into multiple crates if possible?

Re: Performance of Rust Language [pdf]

#78

I would summarize it thusly: Rust is roughly as performant as C. This matches my experience and Rust is more ergonomic than C in many regards. The caveat is that modern C++ is notably more performant than C and by implication Rust. This also matches my experience for both C and Rust. I think most of this is attributable to the ergonomics of compile-time expressiveness. C++ can effortlessly do things that require moun…

Is C++ more performant than C? I find this hard to believe. C++ does not have any construct that cannot be replicated, or is not common, in C. The only candidate is using virtualization and void* pointers instead of monomorphized generics which some C code does for the lack of better options, but that's not a problem in Rust as well. If anything, Rust has the potential to be more performant than C due to its aliasing…

[deleted]

Re: Performance of Rust Language [pdf]

#79
post #71
post #5

There's a discussion of "delayed bounds checking", but not "hoisted bounds checking", where bounds checking is done early. Consider let mut tab: [usize;100] = [0;100]; ... for i in 0..101 { tab[i] = i; } This must panic at i=100. Panic becomes inevitable at entry to the loop. Is the compiler entitled to generate a check that will panic at loop entry? The slides suggest that Rust does not hoist such checks, and, so, w…

On https://godbolt.org/ select Ada and compiler option "-O2" function Square(num : Integer) return Integer is tab : array (0..100) of integer; begin for i in 0..101 loop tab(i):=i; end loop; return tab(100); end Square; The assembly code generated is : sub rsp, 8 #, mov esi, 11 #, mov edi, OFFSET FLAT:.LC0 #, call "__gnat_rcheck_CE_Index_Check" # Loop is not run and exeption handler is called directly. Link : https:/…

Right, that's the extreme case, where the problem is detected at compile time. Unfortunately, it's not a user-visible error message at compile time.

Need to try an example where the size isn't known until run time.

Re: Performance of Rust Language [pdf]

#80
post #58

Earlier quoted context omitted.

Julia is another contender. Julia code can be as performant as C++ code, but Julia code may be even more elegant than C++. Even without accounting for Julia's metaprogramming features, the compile-time expressiveness is top-notch. It shares some of the same drawbacks as C++, though. The language is extremely powerful, so while it is easy to write performant code, it is also easy for non experts to write very suboptim…

Julia is not a systems language. Also its design (GC, dynamic typing) does not allow it to reach exactly the same level as C++.

you are right one has to be careful to avoid the GC and dynamic dispatch, but if you do it can for sure reach the same level as C++. with tightly optimized Julia code there is little to no overhead over any other low-level language.
Post reply on HN