Skip to content

Commit 82297bc

Browse files
committed
Auto merge of rust-lang#87777 - the8472:fix-mir-max-rss, r=oli-obk,joshtriplett
Use zeroed allocations in the mir interpreter instead eagerly touching the memory rust-lang#86255 introduced a 30% regression in [page faults](https://perf.rust-lang.org/compare.html?start=64ae15ddd3f3cca7036ab2b2f3a6b130b62af4da&end=39e20f1ae5f13451eb35247808d6a2527cb7d060&stat=faults ) and a 3% regression in [max-rss](https://perf.rust-lang.org/index.html?start=2021-07-01&end=&absolute=false&stat=max-rss) in the ctfe-stress benchmarks. That's most likely happened because it separated allocation from initialization of the vec which defeats the zero-optimization. Currently there's no allocation API that is fallible, zeroing and returns a slice, so this PR introduces one and then uses that to solve the problem. In principle `vec.resize(len, 0)` could be optimized to use `alloc::grow_zeroed` where appropriate but that would require new specializations and new plumbing in `RawVec`.
2 parents d6f93fd + 6eba6fe commit 82297bc

File tree

1 file changed

+65
-1
lines changed

1 file changed

+65
-1
lines changed

alloc/src/boxed.rs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,6 @@ use crate::alloc::{handle_alloc_error, WriteCloneIntoRaw};
157157
use crate::alloc::{AllocError, Allocator, Global, Layout};
158158
#[cfg(not(no_global_oom_handling))]
159159
use crate::borrow::Cow;
160-
#[cfg(not(no_global_oom_handling))]
161160
use crate::raw_vec::RawVec;
162161
#[cfg(not(no_global_oom_handling))]
163162
use crate::str::from_boxed_utf8_unchecked;
@@ -589,6 +588,71 @@ impl<T> Box<[T]> {
589588
pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
590589
unsafe { RawVec::with_capacity_zeroed(len).into_box(len) }
591590
}
591+
592+
/// Constructs a new boxed slice with uninitialized contents. Returns an error if
593+
/// the allocation fails
594+
///
595+
/// # Examples
596+
///
597+
/// ```
598+
/// #![feature(allocator_api, new_uninit)]
599+
///
600+
/// let mut values = Box::<[u32]>::try_new_uninit_slice(3)?;
601+
/// let values = unsafe {
602+
/// // Deferred initialization:
603+
/// values[0].as_mut_ptr().write(1);
604+
/// values[1].as_mut_ptr().write(2);
605+
/// values[2].as_mut_ptr().write(3);
606+
/// values.assume_init()
607+
/// };
608+
///
609+
/// assert_eq!(*values, [1, 2, 3]);
610+
/// # Ok::<(), std::alloc::AllocError>(())
611+
/// ```
612+
#[unstable(feature = "allocator_api", issue = "32838")]
613+
#[inline]
614+
pub fn try_new_uninit_slice(len: usize) -> Result<Box<[mem::MaybeUninit<T>]>, AllocError> {
615+
unsafe {
616+
let layout = match Layout::array::<mem::MaybeUninit<T>>(len) {
617+
Ok(l) => l,
618+
Err(_) => return Err(AllocError),
619+
};
620+
let ptr = Global.allocate(layout)?;
621+
Ok(RawVec::from_raw_parts_in(ptr.as_mut_ptr() as *mut _, len, Global).into_box(len))
622+
}
623+
}
624+
625+
/// Constructs a new boxed slice with uninitialized contents, with the memory
626+
/// being filled with `0` bytes. Returns an error if the allocation fails
627+
///
628+
/// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
629+
/// of this method.
630+
///
631+
/// # Examples
632+
///
633+
/// ```
634+
/// #![feature(allocator_api, new_uninit)]
635+
///
636+
/// let values = Box::<[u32]>::try_new_zeroed_slice(3)?;
637+
/// let values = unsafe { values.assume_init() };
638+
///
639+
/// assert_eq!(*values, [0, 0, 0]);
640+
/// # Ok::<(), std::alloc::AllocError>(())
641+
/// ```
642+
///
643+
/// [zeroed]: mem::MaybeUninit::zeroed
644+
#[unstable(feature = "allocator_api", issue = "32838")]
645+
#[inline]
646+
pub fn try_new_zeroed_slice(len: usize) -> Result<Box<[mem::MaybeUninit<T>]>, AllocError> {
647+
unsafe {
648+
let layout = match Layout::array::<mem::MaybeUninit<T>>(len) {
649+
Ok(l) => l,
650+
Err(_) => return Err(AllocError),
651+
};
652+
let ptr = Global.allocate_zeroed(layout)?;
653+
Ok(RawVec::from_raw_parts_in(ptr.as_mut_ptr() as *mut _, len, Global).into_box(len))
654+
}
655+
}
592656
}
593657

594658
impl<T, A: Allocator> Box<[T], A> {

0 commit comments

Comments
 (0)