Skip to content

Switch from 'Option' to 'ManuallyDrop' for blocking guard's inner #1176

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Aandreba
Copy link

This change will remove a panic point and improve performance when accessing a bound godot class

@TitanNano
Copy link
Contributor

This change will remove a panic point

But we are trading it for more unsafe code. It's not a huge deal, but maintenance wise, I don't think having to verify unsafe code is better than verifying possible panics.

and improve performance

can you elaborate how this is improving performance?

@Aandreba
Copy link
Author

can you elaborate how this is improving performance?

Not having to check if the Option is None improves performance slightly, but the biggest improvement comes from the optimizations that the compiler can perform by not having to worry about panicking every time it dereferences the guard. The guard should also be smaller now, since we're not storing the None case.

@Bromeon Bromeon added c: core Core components performance Performance problems and optimizations labels May 30, 2025
@GodotRust
Copy link

API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-1176

@Bromeon Bromeon added this to the 0.3.x milestone May 30, 2025
Copy link
Member

@Bromeon Bromeon left a comment

Choose a reason for hiding this comment

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

Thanks for your contribution! 🙂


Not having to check if the Option is None improves performance slightly, but the biggest improvement comes from the optimizations that the compiler can perform by not having to worry about panicking every time it dereferences the guard.

This is a fair point, also for self-documentation reasons: seeing unwrap() immediately rings alarm bells about potential panics. Not that unsafe code is much better only to drop a field earlier in the destructor, but it's reasonably localized, and with a safety statement it should be clear enough.

I haven't found a well-established idiom for this problem, which is a pity. There seem to be specialized solutions like parking_lot's unlocked(), but nothing that we could use here.

let guard = mutex.lock();
guard.unlocked(|guard| {
    // Mutex is temporarily unlocked here.
    condition.notify_all();
    // When this closure returns, `guard` is re-locked.
});

The guard should also be smaller now, since we're not storing the None case.

From a brief test, it seems to be 32 bytes with both Option and ManuallyDrop. It looks like niche optimizations are at play here.


Could you add the safety statements (see comments) and rebase onto master, while keeping the PR at 1 commit?

Comment on lines +102 to +104
unsafe {
ManuallyDrop::drop(&mut self.inner);
}
Copy link
Member

Choose a reason for hiding this comment

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

Please add a safety statement:

Suggested change
unsafe {
ManuallyDrop::drop(&mut self.inner);
}
// SAFETY: guard is dropped exactly once, here.
unsafe {
ManuallyDrop::drop(&mut self.inner);
}

Comment on lines +53 to +55
unsafe {
ManuallyDrop::drop(&mut self.inner);
}
Copy link
Member

Choose a reason for hiding this comment

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

Also here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: core Core components performance Performance problems and optimizations
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants