-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Arc: remove unused allocation from Weak::new() #50357
Conversation
In order to not lose the |
@jonas-schievink I suppose it could be, would such trickery be worth it though? The only thing you do with |
This comment has been minimized.
This comment has been minimized.
I think what matters most is how |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
It seems potentially common to have |
So, I could change it back to holding a |
I think |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
weak: atomic::AtomicUsize::new(1), | ||
data: uninitialized(), | ||
}), | ||
ptr: NonNull::new_unchecked(WEAK_EMPTY as *mut _), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😕 Just use NonNull::dangling()
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That picks a value based on the alignment size of T
. While RawVec
can check cap
if its pointer is actually null, Weak
doesn't have that. So, to check, dangling
would need to be called each time.
It's also not clear to me what having a never-used pointer to 8
, or 16
, etc would provide.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think calling dangling
every time is a problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It shouldn't be a problem, the value is constant for the input type.
It may avoid memory access errors in debuggers, or avoid tripping unaligned access warnings in tools like Valgrind (if that's a thing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In #41064 we changed all dangling pointers to be aligned rather than 1. There is no reason for this case to be different.
dangling()
optimizes to a constant, there is not issue with calling it many times.
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
Ping from triage, @seanmonstar and @kennytm ! What's the status here? |
@shepmaster looks like the CI failure is spurious. It's tagged waiting on review, is that correct, or is that blocked on me? |
@shepmaster @seanmonstar This is blocked by the lack of a reviewer 😐 |
haha, I thought you were the reviewer! random says... r? @KodrAus |
I can resolve the conflicts. I no longer have the benchmark code setup, is it needed to see |
Thanks for your patience with this @seanmonstar. I figured since we had the little bit of extra logic in #![feature(test)]
extern crate test;
use std::sync::{Arc, Weak};
#[bench]
fn weak_new(b: &mut test::Bencher) {
b.iter(|| test::black_box(Weak::<()>::new()));
}
#[bench]
fn weak_upgrade_none(b: &mut test::Bencher) {
let w = Weak::<i32>::new();
b.iter(|| test::black_box(w.upgrade()));
}
#[bench]
fn weak_upgrade_some(b: &mut test::Bencher) {
let a = Arc::new(42);
let w = Arc::downgrade(&a);
b.iter(|| test::black_box(w.upgrade()));
} On my machine I get:
The difference looks negligible to me. I'm happy to r+ again after we resolve the conflicts. |
df72c4c
to
24ce259
Compare
It looks like we're get the benefits of not allocating @bors r+ |
📌 Commit 24ce259 has been approved by |
Arc: remove unused allocation from Weak::new() It seems non-obvious that calling `Weak::new()` actually allocates space for the entire size of `T`, even though you can **never** access that data from such a constructed weak pointer. Besides that, if someone were to create many `Weak:new()`s, they could be unknowingly wasting a bunch of memory. This change makes it so that `Weak::new()` allocates no memory at all. Instead, it is created with a null pointer. The only things done with a `Weak` are trying to upgrade, cloning, and dropping, meaning there are very few places that the code actually needs to check if the pointer is null.
☀️ Test successful - status-appveyor, status-travis |
Why do this for |
Same for Rc: #51901 |
…hton Rc: remove unused allocation and fix segfault in Weak::new() Same as rust-lang#50357 did for `Arc`. Fixes rust-lang#48493
Correct outdated documentation for rc::Weak This was overlooked in ~~rust-lang#50357~~ rust-lang#51901
It seems non-obvious that calling
Weak::new()
actually allocates space for the entire size ofT
, even though you can never access that data from such a constructed weak pointer. Besides that, if someone were to create manyWeak:new()
s, they could be unknowingly wasting a bunch of memory.This change makes it so that
Weak::new()
allocates no memory at all. Instead, it is created with a null pointer. The only things done with aWeak
are trying to upgrade, cloning, and dropping, meaning there are very few places that the code actually needs to check if the pointer is null.