Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement TrustedRandomAccess for slice::{Chunks, ChunksMut, Windows} #47142

Merged
merged 4 commits into from
Jan 5, 2018

Conversation

sdroege
Copy link
Contributor

@sdroege sdroege commented Jan 2, 2018

As suggested by @bluss in #47115 (comment)

@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @kennytm (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@kennytm
Copy link
Member

kennytm commented Jan 3, 2018

Thanks!

@bors r+

@bors
Copy link
Contributor

bors commented Jan 3, 2018

📌 Commit 43291c6 has been approved by kennytm

@kennytm kennytm added the S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. label Jan 3, 2018
@sdroege
Copy link
Contributor Author

sdroege commented Jan 3, 2018

Thanks for the fast review!

This is going to fail because of #47113
I'll update it in a bit

@kennytm kennytm added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Jan 3, 2018
@kennytm
Copy link
Member

kennytm commented Jan 3, 2018

Okay. @bors r-

@kennytm kennytm added S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jan 3, 2018
@sdroege
Copy link
Contributor Author

sdroege commented Jan 3, 2018

For good measure, I'll also add unit tests for zipping the 3 iterators. It seems like this is not covered by any of the existing unit tests yet

@sdroege
Copy link
Contributor Author

sdroege commented Jan 3, 2018

This will now fail until #47113 is merged for real

@bors
Copy link
Contributor

bors commented Jan 3, 2018

☔ The latest upstream changes (presumably #47151) made this pull request unmergeable. Please resolve the merge conflicts.

@sdroege sdroege force-pushed the trusted-random-access-chunks branch from bbb27f4 to 3f29e2b Compare January 3, 2018 13:05
@sdroege
Copy link
Contributor Author

sdroege commented Jan 3, 2018

Rebased on top of latest master

@kennytm kennytm added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. labels Jan 3, 2018
unsafe impl<'a, T> TrustedRandomAccess for Chunks<'a, T> {
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
let start = i * self.chunk_size;
let end = cmp::min(start + self.chunk_size, self.v.len());
Copy link
Member

@bluss bluss Jan 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a potential wraparound here isn't there? i is in bounds but start + size can still wrap around. In particular for [(); !0].chunks((!0)/2 +1) I think.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turns out Rust ICES on that array. For those that don't like my mobile-friendly syntax, !0 is the same as usize::max_value().

However Rust accepts a vec of this length, and we can demo (playground link)

fn main() {
    let v = vec![(); !0];
    let iter = v.chunks((!0)/2 +1);
    for elt in iter {
        println!("Found chunk of len {}", elt.len());
    }
}

Which has output:

Found chunk of len 9223372036854775808
Found chunk of len 9223372036854775807

@sdroege
Copy link
Contributor Author

sdroege commented Jan 3, 2018

Good point, thanks. This should probably use checked_add and if it overflows then just use the length.

Will fix in a few hours, thanks for spotting this

@sdroege
Copy link
Contributor Author

sdroege commented Jan 4, 2018

I fixed that now , but also see the discussion at #47126 (comment) and the following 3 comments. It might make sense to reconsider the whole TrustedRandomAccess iterator or at least the zip implementation based on it.

Actually this all seems to have been investigated back then already, so it should all be fine. See top of #47126 (comment)

@sdroege
Copy link
Contributor Author

sdroege commented Jan 4, 2018

I think we're good to go actually

@sdroege
Copy link
Contributor Author

sdroege commented Jan 4, 2018

Some benchmark results, based on the code from #47115 (comment) . Just running a 1920*1080*4 byte array through the normal chunks version.

Something like 1.5% difference (the new version is faster), but consistently. So even for things that llvm can't auto-vectorize it seems to be slightly faster.

Before

$ cargo +local bench
running 1 test
    Finished release [optimized] target(s) in 0.0 secs
     Running target/release/deps/testing-611256b07a3291e9

test tests::test_bgrx_to_grey ... bench:   5,858,100 ns/iter (+/- 160,940)

test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out

$ cargo +local bench
    Finished release [optimized] target(s) in 0.0 secs
     Running target/release/deps/testing-611256b07a3291e9

running 1 test
test tests::test_bgrx_to_grey ... bench:   5,842,103 ns/iter (+/- 143,723)

test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out

$ cargo +local bench
    Finished release [optimized] target(s) in 0.0 secs
     Running target/release/deps/testing-611256b07a3291e9

running 1 test
test tests::test_bgrx_to_grey ... bench:   5,858,885 ns/iter (+/- 193,095)

test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out

$ cargo +local bench
    Finished release [optimized] target(s) in 0.0 secs
     Running target/release/deps/testing-611256b07a3291e9

running 1 test
test tests::test_bgrx_to_grey ... bench:   5,853,836 ns/iter (+/- 184,774)

test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out

After

$ cargo +local bench
    Finished release [optimized] target(s) in 0.0 secs
     Running target/release/deps/testing-611256b07a3291e9

running 1 test
test tests::test_bgrx_to_grey ... bench:   5,764,354 ns/iter (+/- 237,465)

test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out

$ cargo +local bench
    Finished release [optimized] target(s) in 0.0 secs
     Running target/release/deps/testing-611256b07a3291e9

running 1 test
test tests::test_bgrx_to_grey ... bench:   5,764,800 ns/iter (+/- 298,007)

test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out

$ cargo +local bench
    Finished release [optimized] target(s) in 0.0 secs
     Running target/release/deps/testing-611256b07a3291e9

running 1 test
test tests::test_bgrx_to_grey ... bench:   5,780,834 ns/iter (+/- 234,143)

test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out

$ cargo +local bench
    Finished release [optimized] target(s) in 0.0 secs
     Running target/release/deps/testing-611256b07a3291e9

running 1 test
test tests::test_bgrx_to_grey ... bench:   5,783,144 ns/iter (+/- 242,745)

test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out

@kennytm
Copy link
Member

kennytm commented Jan 4, 2018

Thanks again! Just wanna confirm, will the expression i * self.chunk_size overflow?

@sdroege
Copy link
Contributor Author

sdroege commented Jan 4, 2018

Thanks again! Just wanna confirm, will the expression i * self.chunk_size overflow?

Yes, but only if you call it with an i that is not in range for the slice. AFAIU this is fine, that's what the "unchecked" / unsafe part of the trait is about: you need to ensure beforehand that the item you want to access does actually exist.

@kennytm
Copy link
Member

kennytm commented Jan 4, 2018

@bors r+

@bors
Copy link
Contributor

bors commented Jan 4, 2018

📌 Commit b69c124 has been approved by kennytm

@kennytm kennytm added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 4, 2018
@sdroege
Copy link
Contributor Author

sdroege commented Jan 4, 2018

Thanks a lot @kennytm and @bluss :)

kennytm added a commit to kennytm/rust that referenced this pull request Jan 4, 2018
…s, r=kennytm

Implement TrustedRandomAccess for slice::{Chunks, ChunksMut, Windows}

As suggested by @bluss in rust-lang#47115 (comment)
@bors
Copy link
Contributor

bors commented Jan 5, 2018

⌛ Testing commit b69c124 with merge b98fd52...

bors added a commit that referenced this pull request Jan 5, 2018
Implement TrustedRandomAccess for slice::{Chunks, ChunksMut, Windows}

As suggested by @bluss in #47115 (comment)
@bors
Copy link
Contributor

bors commented Jan 5, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: kennytm
Pushing b98fd52 to master...

@bors bors merged commit b69c124 into rust-lang:master Jan 5, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants