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

Optimize miri engine performance for sanity checks of arrays #53845

Closed
oli-obk opened this issue Aug 31, 2018 · 3 comments
Closed

Optimize miri engine performance for sanity checks of arrays #53845

oli-obk opened this issue Aug 31, 2018 · 3 comments
Labels
A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate.

Comments

@oli-obk
Copy link
Contributor

oli-obk commented Aug 31, 2018

The knowledge about all the elements in an array can be used to run a single check instead of running the checks on each element one at a time (suggested in #53671 (comment)).

This is currently only done for strings, but could just as well be done for arrays of various types with Scalar layout.

The E-easy part of this issue is to check for arrays/slices of the builtin integer types and simply verify that there are no relocations in the entire array and that the entire array has no undefined bytes. Should be possible by simply calling

pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> {
and checking whether it returned Ok. No need to actually check the value.

The E-medium part is to refactor

fn validate_scalar(
to take a bunch of closures which do the final checks. Instead of doing the check for a single memory location, run it for the entire array at once. This means the function won't have
value: ScalarMaybeUndef,
as an argument anymore, but instead the closures pass around some generic value. E.g
let value = match value {
ScalarMaybeUndef::Scalar(scalar) => scalar,
ScalarMaybeUndef::Undef => return validation_failure!("undefined bytes", path),
};
would be replaced by a closure call, and its result would be fed into the next closure e.g. in
let in_range = |bound: RangeInclusive<u128>| bound.contains(&bits);
. Note that #53826 should be done before this, otherwise you'll go crazy while attempting to fiddle this refactoring into the current code

@oli-obk oli-obk added E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. WG-compiler-const A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) labels Aug 31, 2018
@RalfJung
Copy link
Member

take a bunch of closures which do the final checks

I have no idea what you are suggesting here. The array field operand iteration is already quite optimized, so for which cases do you expect performance gains here? For non-integer scalars, we still have to actually check every single element for being valid.

Also we have again the question of when to look for the layout vs. the type.

@oli-obk
Copy link
Contributor Author

oli-obk commented Aug 31, 2018

E.g. for [&i32] it seems faster to do a single call to Memory::relocations than one for each field. I don't expect the iteration to be faster, I expect it to be faster to check N elements via an optimized operation instead of reading a Scalar at each index and then checking that.

For non-integer scalars, we still have to actually check every single element for being valid.

Even scalars with a valid range less than the full range require doing the access checks (defined, not pointer, aligned) on the memory, when one could just get the entire byte memory of the array at once and then just read integers out of it.

@RalfJung
Copy link
Member

Even scalars with a valid range less than the full range require doing the access checks

Oh, I thought you'd only do this for "full-range scalars".

For anything else, the perf win will be smaller, and I am afraid we'll have to start tearing down those beautiful abstractions and make the code ugly. :/

bors added a commit that referenced this issue Sep 8, 2018
Optimize miri checking of integer array/slices

This pull request implements the optimization described in #53845 (the  `E-easy` part of that issue, not the refactoring). Instead of checking every element of an integral array, we can check the whole memory range at once.

r? @RalfJung
@oli-obk oli-obk closed this as completed Jan 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate.
Projects
None yet
Development

No branches or pull requests

2 participants