Revisiting Loop Recognition in C++... in Rust

11 points by camblomquist


kornel

If a straight translation from the C++ were made while trying to stay in Safe Rust, most of the pointers would be replaced with references

Oh no, that assumption gets people stuck fighting the borrow checker.

Rust’s references are not general-purpose pointers. They have a much more specialized role of giving only a temporary access to objects, and by definition are incapable of storing data.

Rust has other ways of referring to objects and storing data “by reference”. What each pointer translates to is “it depends”, and unfortunately the details are very important. It may be a Box, or may require Rc or Arc (even where C++ wouldn’t use shared_ptr), or could even be non-pointer and store and pass an object by value.

masklinn

Rust is not garbage collected, opting for compile-time verification of memory lifetime through the borrow checker.

The two clauses are largely unrelated. Rust is not garbage collected, memory management is automated via RAII. For this specific context the borrow checker “just” verifies that a reference does not outlive the referent (that there are no dangling pointers).

Rust has pointers but deferefencing these pointers is limited to unsafe contexts.

Rust has pointers and dereferencing those pointers is just fine: references, box, rc, … are all pointers. Raw pointers are unsafe to dereference.

Rust requires statements be terminated with ;.

Not quite:

An expression that consists of only a block expression or control flow expression, if used in a context where a statement is permitted, can omit the trailing semicolon.

Lines not terminated with ; are considered expressions, returning their value.

Expressions are expressions, and thus have a value. An expression followed by a semicolon is an expression statement. I’m unsure there’s anything in rust which cares about lines.

dataangel

The Rust Release build handily beats the C++ in both execution time and memory footprint.

Having done a fair number of these comparisons my two most likely explanations for why are:

There are no significant sources of overhead at the language level in C++ compared to Rust other than C++ coroutines requiring heap allocation (shouldn’t be used for a graph algorithm benchmark), the theoretical Rust advantage from having better aliasing due to mut being like restrict rarely shows up, and Rust has several idioms that add overhead that would not be in the C++ version (RefCell, extra clone and Rc calls to please borrow checker).