Skip to content

Add optimize_for_size variants for stable and unstable sort as well as select_nth_unstable #129587

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

Merged
merged 9 commits into from
Sep 24, 2024
Prev Previous commit
Next Next commit
Select tiny sorts for 16-bit platforms
Also skips stack alloc in stable sort if 16-bit target platform.
  • Loading branch information
Voultapher committed Sep 4, 2024
commit a0e4303ba2ed087a85e0218a4049d8cc73d7f404
31 changes: 19 additions & 12 deletions library/core/src/slice/sort/stable/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,27 @@ pub fn sort<T, F: FnMut(&T, &T) -> bool, BufT: BufGuard<T>>(v: &mut [T], is_less
}

cfg_if! {
if #[cfg(feature = "optimize_for_size")] {
if #[cfg(any(feature = "optimize_for_size", target_pointer_width = "16"))] {
let alloc_len = len / 2;

// For small inputs 4KiB of stack storage suffices, which allows us to avoid
// calling the (de-)allocator. Benchmarks showed this was quite beneficial.
let mut stack_buf = AlignedStorage::<T, 4096>::new();
let stack_scratch = stack_buf.as_uninit_slice_mut();
let mut heap_buf;
let scratch = if stack_scratch.len() >= alloc_len {
stack_scratch
} else {
heap_buf = BufT::with_capacity(alloc_len);
heap_buf.as_uninit_slice_mut()
};
cfg_if! {
if #[cfg(target_pointer_width = "16")] {
let heap_buf = BufT::with_capacity(alloc_len);
let scratch = heap_buf.as_uninit_slice_mut();
} else {
// For small inputs 4KiB of stack storage suffices, which allows us to avoid
// calling the (de-)allocator. Benchmarks showed this was quite beneficial.
let mut stack_buf = AlignedStorage::<T, 4096>::new();
let stack_scratch = stack_buf.as_uninit_slice_mut();
let mut heap_buf;
let scratch = if stack_scratch.len() >= alloc_len {
stack_scratch
} else {
heap_buf = BufT::with_capacity(alloc_len);
heap_buf.as_uninit_slice_mut()
};
}
}

tiny::mergesort(v, scratch, is_less);
} else {
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/slice/sort/unstable/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub fn sort<T, F: FnMut(&T, &T) -> bool>(v: &mut [T], is_less: &mut F) {
}

cfg_if! {
if #[cfg(feature = "optimize_for_size")] {
if #[cfg(any(feature = "optimize_for_size", target_pointer_width = "16"))] {
heapsort::heapsort(v, is_less);
} else {
// More advanced sorting methods than insertion sort are faster if called in
Expand Down