Skip to content

Commit 3960f56

Browse files
bmbergerjoshlf
andcommitted
Optimize Ref<_, T> methods when T: Sized (#2752)
With optimization: test r#ref::tests::bench_from_bytes_sized ... bench: 4.86 ns/iter (+/- 0.33) test r#ref::tests::bench_into_ref_sized ... bench: 0.88 ns/iter (+/- 0.05) Without optimization: test r#ref::tests::bench_from_bytes_sized ... bench: 5.03 ns/iter (+/- 0.60) test r#ref::tests::bench_into_ref_sized ... bench: 0.89 ns/iter (+/- 0.12) Closes #2752 Co-authored-by: Joshua Liebow-Feeser <[email protected]>
1 parent 2d1d2b2 commit 3960f56

File tree

1 file changed

+21
-22
lines changed

1 file changed

+21
-22
lines changed

src/ref.rs

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ mod def {
192192

193193
#[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain.
194194
pub use def::Ref;
195+
use crate::pointer::invariant::{
196+
Aligned, Initialized, Shared, Valid, Unaligned,
197+
};
195198

196199
impl<B, T> Ref<B, T>
197200
where
@@ -620,30 +623,21 @@ where
620623

621624
if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info {
622625
let ptr = Ptr::from_ref(b);
623-
// SAFETY: `T::raw_from_ptr_len` promises to preserve address and provenance in the referent
624-
let ptr: Ptr<'_, T, _> = unsafe {
625-
ptr.transmute_unchecked(|ptr| {
626+
let ptr: Ptr<'_, [u8], (Shared, Unaligned, Initialized)> = ptr.transmute::<_, _, (_, (_, _))>();
627+
// SAFETY: `T::raw_from_ptr_len` promises to preserve address and provenance in the referent.
628+
let ptr: Ptr<'_, T, (Shared, Unaligned, Initialized)> = unsafe {
629+
ptr.cast_unsized(|ptr| {
626630
let ptr = T::raw_from_ptr_len(
627631
ptr.as_non_null().cast(),
628632
<T::PointerMetadata as crate::PointerMetadata>::from_elem_count(0),
629633
);
630-
// SAFETY: The safety invariants of `Ptr::new` (see definition) are
631-
// satisfied:
632-
// 0. If `ptr`'s referent is not zero sized, then `ptr` has valid
633-
// provenance for its referent, because it derived from `self`
634-
// using a series of provenance-preserving operations, and
635-
// because `self` has valid provenance for its referent. By the
636-
// same argument, `ptr`'s referent is entirely contained within
637-
// the same allocated object as `self`'s referent.
638-
// 1. If `ptr`'s referent is not zero sized, then the allocation of
639-
// `ptr` is guaranteed to live for at least `'a`, because `ptr`
640-
// is entirely contained in `self`, which lives for at least `'a`
641-
// by invariant on `Ptr`.
642634
unsafe { crate::pointer::PtrInner::new(ptr) }
643635
})
644636
};
645-
// SAFETY: By invariant on `r`, we know that size and alignment are valid.
646-
let ptr = unsafe { ptr.assume_alignment() };
637+
638+
// SAFETY: By invariant on `r`, we know that alignment is valid.
639+
let ptr = unsafe { ptr.assume_alignment::<Aligned>() };
640+
let ptr = ptr.recall_validity::<Valid, _>();
647641
return ptr.as_ref();
648642
}
649643

@@ -1005,39 +999,44 @@ mod tests {
1005999
fn bench_from_bytes_sized(b: &mut Bencher) {
10061000
let buf = Align::<[u8; 8], AU64>::default();
10071001
// `buf.t` should be aligned to 8, so this should always succeed.
1008-
b.iter(|| test::black_box(Ref::<_, AU64>::from_bytes(&buf.t[..]).unwrap()));
1002+
let bytes = &buf.t[..];
1003+
b.iter(|| test::black_box(Ref::<_, AU64>::from_bytes(test::black_box(bytes)).unwrap()));
10091004
}
10101005

10111006
#[bench]
10121007
fn bench_into_ref_sized(b: &mut Bencher) {
10131008
let buf = Align::<[u8; 8], AU64>::default();
1009+
let bytes = &buf.t[..];
10141010
b.iter(|| {
1015-
let r = Ref::<_, AU64>::from_bytes(&buf.t[..]).unwrap();
1011+
let r = Ref::<_, AU64>::from_bytes(test::black_box(bytes)).unwrap();
10161012
test::black_box(Ref::into_ref(r))
10171013
});
10181014
}
10191015

10201016
#[bench]
10211017
fn bench_into_mut_sized(b: &mut Bencher) {
10221018
let mut buf = Align::<[u8; 8], AU64>::default();
1019+
// TODO change these
10231020
b.iter(|| {
1024-
let r = Ref::<_, AU64>::from_bytes(&mut buf.t[..]).unwrap();
1021+
let r = Ref::<_, AU64>::from_bytes(test::black_box(&mut buf.t[..])).unwrap();
10251022
test::black_box(Ref::into_mut(r));
10261023
});
10271024
}
10281025

10291026
#[bench]
10301027
fn bench_deref_sized(b: &mut Bencher) {
10311028
let buf = Align::<[u8; 8], AU64>::default();
1032-
let r = Ref::<_, AU64>::from_bytes(&buf.t[..]).unwrap();
1029+
let bytes = &buf.t[..];
1030+
let r = Ref::<_, AU64>::from_bytes(test::black_box(bytes)).unwrap();
10331031
b.iter(|| test::black_box(r.deref()));
10341032
}
10351033

10361034
#[bench]
10371035
fn bench_deref_mut_sized(b: &mut Bencher) {
10381036
let mut buf = Align::<[u8; 8], AU64>::default();
1037+
// TODO change these
10391038
b.iter(|| {
1040-
let mut r = Ref::<_, AU64>::from_bytes(&mut buf.t[..]).unwrap();
1039+
let mut r = Ref::<_, AU64>::from_bytes(test::black_box(&mut buf.t[..])).unwrap();
10411040
test::black_box(r.deref_mut());
10421041
});
10431042
}

0 commit comments

Comments
 (0)