Assuming this was run on a 64bit system, the Rust version seems to be allocating and zeroing twice as much memory as the Go version. edit: this has been pointed out as incorrect, Go ints are 8 bytes on 64bit systems -- thanks for the correction! let mut cache: Vec = (0..=target.chars().count()).collect(); which can be simplified as let mut cache: Vec = vec![0; target.len()]; vs cache := make([]int, len(target)+1) for…
Go int is 8 bytes
Making Rust as Fast as Go
11–20 of 211 posts
Re: Making Rust as Fast as Go
#12Assuming this was run on a 64bit system, the Rust version seems to be allocating and zeroing twice as much memory as the Go version. edit: this has been pointed out as incorrect, Go ints are 8 bytes on 64bit systems -- thanks for the correction! let mut cache: Vec = (0..=target.chars().count()).collect(); which can be simplified as let mut cache: Vec = vec![0; target.len()]; vs cache := make([]int, len(target)+1) for…
Re: Making Rust as Fast as Go
#13Rust does this
next_dist = std::cmp::min(
dist_if_substitute,
std::cmp::min(dist_if_insert, dist_if_delete),
);
Go does this nextDist = min(
distIfDelete,
min(distIfInsert, distIfSubstitute)
)
The order of minimums is important for this dynamic programming loop. If I change Rust version to take minimums in the same order (swapping substitute and delete), runtime drops from 1.878696288 to 1.579639363.I haven't investigated this, but I would guess that this is the same effect I've observed in
* https://matklad.github.io/2017/03/12/min-of-three.html
* https://matklad.github.io/2017/03/18/min-of-three-part-2.htm...
(reposting my comment from reddit, as it's a rather unexpected observation)
Re: Making Rust as Fast as Go
#14The Rust version uses `target.chars().count()` to initialise the cache, while the Go version counts up to `len(target)`. These are not equivalent: the Rust version counts Unicode code points, the Go version counts bytes. I am confused by the implementations, although I have not spent any time testing them. Both versions contain a mix of code that counts bytes (`.len()` and `len(...)`) and Unicode code points (`chars(…
cache := make([]int, len(targetChars)+1)
for i := 0; i
AFAIK this makes them equivalent (fingers crossed). It seems to not have made much of a difference (-0.03s)Re: Making Rust as Fast as Go
#15The Rust version uses `target.chars().count()` to initialise the cache, while the Go version counts up to `len(target)`. These are not equivalent: the Rust version counts Unicode code points, the Go version counts bytes. I am confused by the implementations, although I have not spent any time testing them. Both versions contain a mix of code that counts bytes (`.len()` and `len(...)`) and Unicode code points (`chars(…
Re: Making Rust as Fast as Go
#16Missed chance to shorten title to "Making Rust Go Fast" :-)
Re: Making Rust as Fast as Go
#17I recently did some experiments with creating small static Rust binaries, custom linking, no_std et cetera. A lot of stuff around that kind of thing is unstable or unfinished, which might be somewhat expected. But I’ve also come to the conclusion that Rust relies on libc way too much. That might be fine on Linux, where GNU’s libc is well-maintained, is a bit questionable on MacOS (as seen in this article) and is a a…
How did you come to this conclusion?
People using Rust rely on libc a lot.
For example, #![no_std] means "no standard-library", but it doesn't mean "no libc, no libunwind, etc.".
So a lot of people like to advertise their crates as "#![no_std]" compatible, because they compile with #![no_std], but then the first thing the crate does is linking against libc, against liballoc, against libm, .... or even the standard library itself...
So... if you are trying to build a binary that does not depend on libc or libstd, then there is no language feature to help you there.
#[no_std] binaries are not only unstable, but also probably not what you want, since that won't prevent you from linking any library that links libc, or the standard library, etc.
If you want to avoid libc, you have to enforce that, e.g., by checking in your build system that your binary doesn't contain any libc, libstd, etc. symbols (I just use nm for this). #![no_std] helps a bit here, but making sure you don't link any library that violates this is up to you.
Re: Making Rust as Fast as Go
#18The Rust version uses `target.chars().count()` to initialise the cache, while the Go version counts up to `len(target)`. These are not equivalent: the Rust version counts Unicode code points, the Go version counts bytes. I am confused by the implementations, although I have not spent any time testing them. Both versions contain a mix of code that counts bytes (`.len()` and `len(...)`) and Unicode code points (`chars(…
Nice catch, thanks for pointing this out. I've updated the cache initialization to use `len(targetChars)` rather than `len(target)`: cache := make([]int, len(targetChars)+1) for i := 0; i AFAIK this makes them equivalent (fingers crossed). It seems to not have made much of a difference (-0.03s)
Re: Making Rust as Fast as Go
#19I recently did some experiments with creating small static Rust binaries, custom linking, no_std et cetera. A lot of stuff around that kind of thing is unstable or unfinished, which might be somewhat expected. But I’ve also come to the conclusion that Rust relies on libc way too much. That might be fine on Linux, where GNU’s libc is well-maintained, is a bit questionable on MacOS (as seen in this article) and is a a…
Linux guarantees syscalls are stable. And on Linux, you have the option of telling Rust to cross-compile using a statically-linked musl-libc. (If you also need to statically link OpenSSL or a few other common libraries, I maintain https://github.com/emk/rust-musl-builder, and there's at least one similar image out there.)