Skip to content

Question: Optimisation effects of catch_unwind? #4

@clintonmead

Description

@clintonmead

In the readme to this package you state:

It's very akin to take_mut, though uses Drop instead of std::panic::catch_unwind() to react to unwinding, which avoids the optimisation barrier of calling the extern "C" __rust_maybe_catch_panic(). As such it's up to ∞x faster.

I was wondering if you could go into detail here, in particular whether catch_unwind() causes any optimisation barriers in the case where there is no panic (it seems like it does due to the "maybe").

I've also written the following function, which does an inplace replacement of a vector. It doesn't require Default or Clone. The behaviour on failure is to take the last element of the vector and move it in the vector in the spot where the function panicked, and then simply slice the last element from the vector (as it is now moved and doesn't need to be dropped). My implementation seems to work but uses catch_unwind. I was wondering whether there was a better approach here that avoids the catch_unwind() call, particularly if it inhibits optimisation as you suggest (feel free to include any of this in your library as well).

    fn inplace_vec_map<T>(f: impl Fn(T) -> T, mut x: Vec<T>) -> Vec<T> {
        let mut ptr_and_error: Option<(*mut T, _)> = None;

        for item_ref in &mut x {
            unsafe {
                let y1: T = std::ptr::read(item_ref);
                let y2 = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(y1)));
                match y2 {
                    Ok(result) => std::ptr::write(item_ref, result),
                    Err(error) => {
                        ptr_and_error = Some((item_ref, error));
                        break;
                    }
                }
            }
        }

        if let Some((item_ptr, error)) = ptr_and_error {
            let last_index = x.len() - 1;
            unsafe {
                std::ptr::write(item_ptr, std::ptr::read(x.get_unchecked(last_index)));
                x.set_len(last_index);
                std::panic::resume_unwind(error);
            }
        }
        x
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions