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

Improve shootout-reverse-complement.rs using unsafe code #18056

Merged

Conversation

TeXitoi
Copy link
Contributor

@TeXitoi TeXitoi commented Oct 15, 2014

This is some improvement as asked and discused here: http://www.reddit.com/r/rust/comments/2j2ij3/benchmark_improvement_reverse_compliment/

Before:

real    0m0.396s
user    0m0.280s
sys     0m0.112s

after:

real    0m0.293s
user    0m0.216s
sys     0m0.076s

best C version:

real    0m0.135s
user    0m0.132s
sys     0m0.060s

Another possibility will be to add a DoubleEndedIterator::next_two_side() with a deffault implementation, and specialising it for slices, and use it here (MutableSlice::reverse() can then become safe). This benchmark will then be safe.

What do you think?

@rust-highfive
Copy link
Collaborator

warning Warning warning

  • These commits modify unsafe code. Please review it carefully!

if self.cur >= self.nb { return None; }
let res = unsafe {
(std::mem::transmute(self.slice.unsafe_mut(self.cur)),
std::mem::transmute(self.slice.unsafe_mut(self.last - self.cur)))
Copy link
Member

Choose a reason for hiding this comment

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

This is probably faster storing raw pointers (and is somewhat simpler):

struct TwoSidedIterator<'a, T: 'a> {
    start: *mut T,
    end: *mut T,
    _marker: marker::ContravariantLifetime<'a>
}

fn new(x: &'a mut [T]) -> TwoSideIterator<'a, T> {
    let start = x.as_mut_ptr();
    let end = if x.len() == 0 {
        start
    } else {
        unsafe {start.offset(x.len() - 1)}
    };

    TwoSideIterator {
        start: start,
        end: end,
        _marker: marker::ContravariantLifetime
    }
}

fn next(&mut self) -> Option<(&'a mut T, &'a mut T)> {
    if self.start < self.end {
        let ret = unsafe { (&mut *self.start, &mut *self.end) };
        self.start = self.start.offset(1);
        self.end = self.end.offset(-1);
        ret
    } else {
        None
    }
}

If not that, decrementing self.last instead of doing this subtraction would be better (would avoid the need to store nb too).

@TeXitoi
Copy link
Contributor Author

TeXitoi commented Oct 15, 2014

After using pointers in TwoSideIter as suggested by @huon, I have

real    0m0.264s
user    0m0.184s
sys     0m0.076s

so better :)

On the other hand, the code is trickier:

  • as we don't take the slice, markers are needed, which is error prone (@huon forgot NoCopy for example)
  • if std::mem::size_of::<T>() == 0 I don't know what append.

Finally, such a modification may be interesting to do in MutableSlice::reverse().

bors added a commit that referenced this pull request Oct 17, 2014
…vement, r=alexcrichton

This is some improvement as asked and discused here: http://www.reddit.com/r/rust/comments/2j2ij3/benchmark_improvement_reverse_compliment/

Before:
```
real    0m0.396s
user    0m0.280s
sys     0m0.112s
```
after:
```
real    0m0.293s
user    0m0.216s
sys     0m0.076s
```
best C version:
```
real    0m0.135s
user    0m0.132s
sys     0m0.060s
```

Another possibility will be to add a `DoubleEndedIterator::next_two_side()` with a deffault implementation, and specialising it for slices, and use it here (`MutableSlice::reverse()` can then become safe). This benchmark will then be safe.

What do you think?
@bors bors closed this Oct 17, 2014
@bors bors merged commit 1a6f1eb into rust-lang:master Oct 17, 2014
lnicola pushed a commit to lnicola/rust that referenced this pull request Sep 25, 2024
…r=Veykril

Use more correct handling of lint attributes

The previous analysis was top-down, and worked on a single file (expanding macros). The new analysis is bottom-up, starting from the diagnostics and climbing up the syntax and module tree.

While this is more efficient (and in fact, efficiency was the motivating reason to work on this), unfortunately the code was already fast enough. But luckily, it also fixes a correctness problem: outline parent modules' attributes were not respected for the previous analysis. Case lints specifically did their own analysis to accommodate that, but it was limited to only them. The new analysis works on all kinds of lints, present and future.

It was basically impossible to fix the old analysis without rewriting it because navigating the module hierarchy must come bottom-up, and if we already have a bottom-up analysis (including syntax analysis because modules can be nested in other syntax elements, including macros), it makes sense to use only this kind of analysis.

Few other bugs (not fundamental to the previous analysis) are also fixed, e.g. overwriting of lint levels (i.e. `#[allow(lint)] mod foo { #[warn(lint)] mod bar; }`.

After this PR is merged I intend to work on an editor command that does workspace-wide diagnostics analysis (that is, `rust-analyzer diagnostics` but from your editor and without having to spawn a new process, which will have to analyze the workspace from scratch). This can be useful to users who do not want to enable check on save because of its overhead, but want to see workspace wide diagnostics from r-a (or to maintainers of rust-analyzer).

Closes rust-lang#18086.
Closes rust-lang#18081.
Fixes rust-lang#18056.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants