Live data from Hacker News

Making Rust as Fast as Go

christianfscott.com

121–130 of 211 posts

Re: Making Rust as Fast as Go

#121

Earlier quoted context omitted.

> Both versions will not work with complex Unicode input unless you perform both segmentation by Grapheme Cluster [1] and utilize a consistent Normalization [2] when comparing clusters Doing this is quite easy from Rust.

There's no standard library API in Rust for either grapheme cluster segmentation or for normalization. You'd need a third-party crate, at which point it's less "easy in Rust" and more "someone did the hard work for you" because, its really not easy anywhere haha.

No, and there probably never be a libstd implementation of it, but there is a single crate that everybody uses: unicode-segmentation [0]

> You'd need a third-party crate, at which point it's less "easy in Rust" and more "someone did the hard work for you"

"Someone did the work for you" is true of all code that you did not write yourself, independently of whether that code is easy or hard to write, or whether it is in the standard library or not.

unicode-segmentation is pretty much the only library of its kind in Rust, is super easy to discover (google "Rust grapheme cluster", "Rust unicode segmentation", etc.), and using it is as easy as just typing "cargo add unicode-segmentation".

The library is maintained by a Rust core team member, a Rust standard library team member, is used by servo and firefox, and is the only unicode segmentation library that people use.

Since many programs don't need to do any kind of unicode segmentation, making it part of the standard library sounds like a bad idea. In particular, given that unicode is a moving standard, it would mean that people stuck on old Rust toolchains (e.g. LTS linux distros) cannot create binaries that do proper unicode segmentation, which does not make sense.

The underlying problem is that many programmers do not know that they need to do unicode segmentation in the first place. Moving this into the standard library does not fix that problem either.

[0]: https://crates.io/crates/unicode-segmentation

Re: Making Rust as Fast as Go

#122

Hey all, as some keen-eyed commenters have pointed out, it looks like the rust program is not actually equivalent to the go program. The go program parses the string once, while the rust program parses it repeatedly inside every loop. It's quite late in Sydney as I write this so I'm not up for a fix right now, but this post is probably Fake News. The perf gains from jemalloc are real, but it's probably not the alloca…

> this post is probably Fake News It's not Fake News. Fake News is the publication of intentionally false stories. This is just erroneous. There's a yawning chasm between the two.

Says who?

When news organizations take other news organizations word for it and the story is false, that's fake news. We called it something different back then, but fake news led to the invasion of Iraq. Negligence is sufficient for fake news, malice not required.

Re: Making Rust as Fast as Go

#123
post #105

Earlier quoted context omitted.

Levenstein (edit) distance is fundamentally an information-theoretical concept defined on bitstreams, as insertions/deletions/swaps of individual bits within a stream. It has a lot in common with error-correcting codes, fountain codes, and compression, which all also operate on bitstreams. Any higher-level abstract mention of Levenstein distances (e.g. of Unicode codepoints) is properly supposed to be taken to refer…

Can you point to a source that defines Levenstein distance as only referring to bitstreams? A translation of the original article [1] that introduced the concept notes in a footnote that "the definitions given below are also meaningful if the code is taken to mean an arbitrary set of words (possibly of different lengths) in some alphabet containing r letters (r >= 2)". And if you wish to strictly stick to how it was…

And Unicode is the biggest alphabet haha.

Re: Making Rust as Fast as Go

#124

Earlier quoted context omitted.

> this post is probably Fake News It's not Fake News. Fake News is the publication of intentionally false stories. This is just erroneous. There's a yawning chasm between the two.

"fake news" is an attempt at permanently damaging the American public's faith in the fifth estate. Nobody should ever use that term in the current political climate, ever.

[deleted]

Re: Making Rust as Fast as Go

#126
post #24

Earlier quoted context omitted.

> But I’ve also come to the conclusion that Rust relies on libc way too much. 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 link…

That’s true. But going the no_std route is very hard (the ecosystem isn’t big, and relying cargo and crates.io you’re almost guaranteed to link in the std or liballoc by accident at some point). Even when using the std intentionally, I really wouldn’t have expected that basic std functions like println require the libc.

Well, writing to standard output requires interacting with an operating system, so it's not surprising that it requires `std`. You cannot write to standard output without knowing what operating system you are compiling for.

Worth noting however that `writeln` only needs `core`, and as long you can provide an implementation of writing to standard output (pretty much create a struct and implement `core::fmt::Write` trait for it), creating `println` macro is trivial.

Re: Making Rust as Fast as Go

#128
post #68

Earlier quoted context omitted.

No, most #![no_std] libraries do not link libc in the way you describe (having a direct FFI dependency on malloc) - they link liballoc, which has a pluggable allocator interface. On some platforms and some configurations (including most normal userspace platforms), the default allocator used by liballoc uses malloc. It's actually hard to go out of your way and call malloc directly, because FFI calls are unsafe. It's…

> and they do work. Maybe you are just using different no_std libraries that I am using, but pretty much all of the no_std libraries that I use have `libc` as a direct dependency. Not only for malloc, many of them just needs to write something to stdout or a file, generate random numbers, ..., and that's hard to do without libc. Why they advertise themselves as no_std escapes my comprehension.

Huh, the libc crate itself claims #![no_std] support. I agree that's confusing and counterintuitive... I see what it means in terms of semantics but I don't understand why that's useful.

Re: Making Rust as Fast as Go

#129
post #33
post #32

Earlier quoted context omitted.

AFAIK on Windows, the hierarchy is: C library => kernel32.dll => ntdll.dll => system calls You don’t have to go via the C library - calling kernel32 directly is fine (I believe this is what Go does). However, it’s very rare to call ntdll or to make system calls directly.

Basically yes. ntdll is an implementation detail that shouldn’t be relied upon. kernel32/user32 and friends are considered the “proper” interface to the system and have been stable for decades.

There are some ntdll calls that are officially documented and ok to use. Of course there are also a lot of calls you shouldn't use.

When necessary, it's fine to use even undocumented ones to support Windows 7 and older. It's not like those are going to change anymore.

Re: Making Rust as Fast as Go

#130
post #128

Earlier quoted context omitted.

> and they do work. Maybe you are just using different no_std libraries that I am using, but pretty much all of the no_std libraries that I use have `libc` as a direct dependency. Not only for malloc, many of them just needs to write something to stdout or a file, generate random numbers, ..., and that's hard to do without libc. Why they advertise themselves as no_std escapes my comprehension.

Huh, the libc crate itself claims #![no_std] support. I agree that's confusing and counterintuitive... I see what it means in terms of semantics but I don't understand why that's useful.

The libc crate does correctly claim #![no_std] support, because #![no_std] means "Does not require the Rust standard library", and libc does not require it.

The two main issues I see with #![no_std] are:

* its a flag for "doesn't link the standard library" but the standard library is often too high-level for bare metal apps that want to be in precise control about everything that gets linked

* it isn't a contract of any kind, so you can't rely on it for anything. In fact, this code is correct and works as intended:

    #![no_std]
    extern crate std;
This is problematic, because many #![no_std] libraries end up linking libstd "by accident", even though that's probably not their intent.

So I agree with you that #![no_std] isn't a silver bullet. I think it is still useful in that it lets you avoid linking the standard library by default, which is necessary condition for embedded development. It is not a sufficient condition, in that in practice you actually want to forbid the standard library and other libraries from being linked, and not just "don't link them by default, but do so by accident".

Post reply on HN