Live data from Hacker News

Rust Performance Pitfalls

llogiq.github.io

11–20 of 112 posts

Re: Rust Performance Pitfalls

#11
post #10
post #7

> To get rid of the checks, we can either use bytes directly (usually via Vec / &[u8]) or, if we are absolutely sure the input will be valid UTF-8, use str::from_utf8_unchecked(_) (note that this will require unsafe and break your code in surprising ways should the input not be valid UTF-8). I believe this needs a stronger warning. Functions that operate on strings are allowed to assume that their input is valid UTF-…

What sort of language beyond "absolutely sure", "require unsafe", and "break your code in surprising ways" would you recommend to make this warning stronger?

'break your code in surprising ways' is super vague. Saying 'may cause out of bounds memory access/writes should the input not be valid UTF-8' explicitly is probably more scary.

Re: Rust Performance Pitfalls

#12
post #5

I'm not a compiler expert, but it seems like some of these should be unnecessary, especially with Rust's strong knowledge of types and ownership lifespans. Like this example from the article: let nopes : Vec = bleeps.iter().map(boop).collect(); let frungies : Vec = nopes.iter().filter(|x| x > MIN_THRESHOLD).collect(); where he recommends avoiding the first collect(). Can't the optimizer do that for you if you don't d…

There might be side effects from the first call to `collect`, so the compiler can't get rid of it without potentially changing the semantics of the program.

Best example of this (at least in Java):

    List futures = requestList.map(Client::makeRemoteCall).collect(toList);
    
    List responses = futures.map(CompletableFuture::get).collect(toList);
Basically, we need to start all of the futures, then wait for all the futures. Eliminating the first call to `.collect` would force these remote calls to happen one at a time.

Re: Rust Performance Pitfalls

#13
post #10
post #7

> To get rid of the checks, we can either use bytes directly (usually via Vec / &[u8]) or, if we are absolutely sure the input will be valid UTF-8, use str::from_utf8_unchecked(_) (note that this will require unsafe and break your code in surprising ways should the input not be valid UTF-8). I believe this needs a stronger warning. Functions that operate on strings are allowed to assume that their input is valid UTF-…

What sort of language beyond "absolutely sure", "require unsafe", and "break your code in surprising ways" would you recommend to make this warning stronger?

Explain what might happen, as I did in my comment. People are more likely to take heed of a warning if it's concrete.

Re: Rust Performance Pitfalls

#14
post #10

Earlier quoted context omitted.

What sort of language beyond "absolutely sure", "require unsafe", and "break your code in surprising ways" would you recommend to make this warning stronger?

'break your code in surprising ways' is super vague. Saying 'may cause out of bounds memory access/writes should the input not be valid UTF-8' explicitly is probably more scary.

The nature of undefined behavior is in fact super vague; it's not actually possible to say what will happen.

Re: Rust Performance Pitfalls

#15
post #9

Earlier quoted context omitted.

Does current Rust contain a way to mark functions as Pure?

Not in the referentially-transparent sense. Most Rust functions meet almost all of the practical criteria for for purity (i.e. does not mutate global state (or otherwise any state that was not explicitly passed in to the function), does not do I/O), but that's only a comfort for the programmer's ability to reason about the code; this weakened notion of purity-by-default isn't enough to allow the typical optimizations…

but that's only a comfort for the programmer's ability to reason about the code

A way to mark functions as pure for this purpose would be great! Especially if it's not as fraught as const in C++.

Re: Rust Performance Pitfalls

#16
post #9

Earlier quoted context omitted.

Not in the referentially-transparent sense. Most Rust functions meet almost all of the practical criteria for for purity (i.e. does not mutate global state (or otherwise any state that was not explicitly passed in to the function), does not do I/O), but that's only a comfort for the programmer's ability to reason about the code; this weakened notion of purity-by-default isn't enough to allow the typical optimizations…

but that's only a comfort for the programmer's ability to reason about the code A way to mark functions as pure for this purpose would be great! Especially if it's not as fraught as const in C++.

We actually did have this once, but it wasn't really worth it, so it was removed. https://news.ycombinator.com/item?id=6940624 is the HN discussion, but it looks like the link might now be wrong?

It was also a very, very long time ago, and so today's Rust might be different enough that those reasons don't apply any more.

Re: Rust Performance Pitfalls

#17
post #10

Earlier quoted context omitted.

What sort of language beyond "absolutely sure", "require unsafe", and "break your code in surprising ways" would you recommend to make this warning stronger?

'break your code in surprising ways' is super vague. Saying 'may cause out of bounds memory access/writes should the input not be valid UTF-8' explicitly is probably more scary.

That's the kind of vagueness that should sound like a warning to anyone considering that approach.

Re: Rust Performance Pitfalls

#18
post #4

I'm not a compiler expert, but it seems like some of these should be unnecessary, especially with Rust's strong knowledge of types and ownership lifespans. Like this example from the article: let nopes : Vec = bleeps.iter().map(boop).collect(); let frungies : Vec = nopes.iter().filter(|x| x > MIN_THRESHOLD).collect(); where he recommends avoiding the first collect(). Can't the optimizer do that for you if you don't d…

Good question. That would mean chaining two statements together so "nopes" is not allocated as a symbol. But, with "let", the user is explicitly instructing the compiler to allocate a reference for "nopes", so i don't think the compiler would chain the statements. Unless it takes the task to checking that "nopes" is not used elsewhere.

The code is problematic, but not because of the let. Optimizations work basically on the as-if principle: they're free to execute code any way they like, but the results must be as if they followed your explicit instructions. Compilers need not, and usually do not, preserve references just because you gave them a name--if you've ever run gdb on optimized code, you'll note how many variables become "" (although that's often a lie for other reasons).

The real problem is that you're shoving the variable into a Vec, which means that you are doing heap allocation. This means that optimizing it out requires matching the heap allocation to the free, noting that the side effects of these two function calls are only about allocation. There's also issues with respect to inlining, dead-code elimination, and then doing data dependence analysis to prove that the two loops can be fused.

Re: Rust Performance Pitfalls

#19

Earlier quoted context omitted.

'break your code in surprising ways' is super vague. Saying 'may cause out of bounds memory access/writes should the input not be valid UTF-8' explicitly is probably more scary.

That's the kind of vagueness that should sound like a warning to anyone considering that approach.

The nature of warnings means that any time you make assumptions about those that might need the warnings having enough knowledge to correctly assess an ambiguity, you've likely just failed a portion of the people the warning was meant to help.

The correct response when warning people of potential problems is never "oh, they should be able to figure out whether this applies to their case".

Re: Rust Performance Pitfalls

#20
post #19

Earlier quoted context omitted.

That's the kind of vagueness that should sound like a warning to anyone considering that approach.

The nature of warnings means that any time you make assumptions about those that might need the warnings having enough knowledge to correctly assess an ambiguity, you've likely just failed a portion of the people the warning was meant to help. The correct response when warning people of potential problems is never "oh, they should be able to figure out whether this applies to their case".

Right. The correct answer here is to convert external data into UTF-8 once and keep it that way. You're probably not going to become compute-bound, even if you're just reading in text and writing it out again. The UTF-8 check is linear time.
Post reply on HN