Skip to content

Instantly share code, notes, and snippets.

@Dousir9
Created September 30, 2023 05:32
Show Gist options
  • Save Dousir9/aa3b338606441b49c661e84e1dceb436 to your computer and use it in GitHub Desktop.
Save Dousir9/aa3b338606441b49c661e84e1dceb436 to your computer and use it in GitHub Desktop.
Vec Bench
use std::time::Instant;
/// # Safety
///
/// * `ptr` must be [valid] for writes.
/// * `ptr` must be properly aligned.
#[inline(always)]
pub unsafe fn store_advance_aligned<T>(val: T, ptr: &mut *mut T) {
unsafe {
std::ptr::write(*ptr, val);
*ptr = ptr.add(1)
}
}
#[inline(always)]
pub unsafe fn store_advance<T>(val: &T, ptr: &mut *mut T) {
unsafe {
std::ptr::copy_nonoverlapping(val as *const T, *ptr, 1);
*ptr = ptr.add(1)
}
}
/// # Safety
///
/// * `(ptr as usize - vec.as_ptr() as usize) / std::mem::size_of::<T>()` must be
/// less than or equal to the capacity of Vec.
#[inline(always)]
pub unsafe fn set_vec_len_by_ptr<T>(vec: &mut Vec<T>, ptr: *const T) {
unsafe {
vec.set_len((ptr as usize - vec.as_ptr() as usize) / std::mem::size_of::<T>());
}
}
const N: usize = 1000;
const BATCH_SIZE: usize = 65536;
fn test_pointer_write() {
let mut offsets: Vec<u64> = Vec::with_capacity(BATCH_SIZE);
let mut offsets_ptr = offsets.as_mut_ptr();
unsafe {
for i in 0..BATCH_SIZE {
store_advance_aligned::<u64>(i as u64, &mut offsets_ptr);
}
set_vec_len_by_ptr(&mut offsets, offsets_ptr);
}
assert_eq!(offsets[10], 10);
}
fn test_pointer_write_without_fn() {
let mut offsets: Vec<u64> = Vec::with_capacity(BATCH_SIZE);
let mut offsets_ptr = offsets.as_mut_ptr();
unsafe {
for i in 0..BATCH_SIZE {
std::ptr::write(offsets_ptr, i as u64);
offsets_ptr = offsets_ptr.add(1)
}
set_vec_len_by_ptr(&mut offsets, offsets_ptr);
}
assert_eq!(offsets[10], 10);
}
fn test_slice_get_unchecked() {
let mut offsets: Vec<u64> = Vec::with_capacity(BATCH_SIZE);
unsafe {
let offsets = offsets.as_mut_slice();
for i in 0..BATCH_SIZE {
*offsets.get_unchecked_mut(i) = i as u64;
}
}
unsafe {
offsets.set_len(BATCH_SIZE);
}
assert_eq!(offsets[10], 10);
}
fn test_vec_get_unchecked() {
let mut offsets: Vec<u64> = Vec::with_capacity(BATCH_SIZE);
unsafe {
// let offsets = offsets.as_mut_slice();
for i in 0..BATCH_SIZE {
*offsets.get_unchecked_mut(i) = i as u64;
}
offsets.set_len(BATCH_SIZE);
}
assert_eq!(offsets[10], 10);
}
fn test_push() {
let mut offsets: Vec<u64> = Vec::with_capacity(BATCH_SIZE);
for i in 0..BATCH_SIZE {
offsets.push(i as u64);
}
assert_eq!(offsets[10], 10);
}
fn test_pointer_copy() {
let mut offsets: Vec<u64> = Vec::with_capacity(BATCH_SIZE);
let mut offsets_ptr = offsets.as_mut_ptr();
unsafe {
for i in 0..BATCH_SIZE {
store_advance::<u64>(&(i as u64), &mut offsets_ptr);
}
set_vec_len_by_ptr(&mut offsets, offsets_ptr);
}
assert_eq!(offsets[10], 10);
}
fn test_extend_from_into_iter() {
let mut offsets: Vec<u64> = Vec::with_capacity(BATCH_SIZE);
offsets.extend((0..BATCH_SIZE).into_iter().map(|x| x as u64));
assert_eq!(offsets[10], 10);
}
fn test_extend_from_iter() {
let mut offsets: Vec<u64> = Vec::with_capacity(BATCH_SIZE);
offsets.extend((0..BATCH_SIZE).map(|x| x as u64));
assert_eq!(offsets[10], 10);
}
// test_pointer_write: 317ms
// test_pointer_write_without_fn: 317ms
// test_slice_get_unchecked: 353ms
// test_vec_get_unchecked: 413ms
// test_push: 433ms
// test_pointer_copy: 438ms
// test_extend_from_into_iter: 454ms
// test_extend_from_iter: 475ms
fn main() {
// let instant = Instant::now();
// for _ in 0..N {
// test_pointer_write()
// }
// println!("test_pointer_write: {:?}", instant.elapsed());
// let instant = Instant::now();
// for _ in 0..N {
// test_pointer_write_without_fn()
// }
// println!("test_pointer_write_without_fn: {:?}", instant.elapsed());
// let instant = Instant::now();
// for _ in 0..N {
// test_slice_get_unchecked()
// }
// println!("test_slice_get_unchecked: {:?}", instant.elapsed());
// let instant = Instant::now();
// for _ in 0..N {
// test_vec_get_unchecked()
// }
// println!("test_vec_get_unchecked: {:?}", instant.elapsed());
// let instant = Instant::now();
// for _ in 0..N {
// test_push()
// }
// println!("test_push: {:?}", instant.elapsed());
// let instant = Instant::now();
// for _ in 0..N {
// test_pointer_copy()
// }
// println!("test_pointer_copy: {:?}", instant.elapsed());
// let instant = Instant::now();
// for _ in 0..N {
// test_extend_from_into_iter()
// }
// println!("test_extend_from_into_iter: {:?}", instant.elapsed());
// let instant = Instant::now();
// for _ in 0..N {
// test_extend_from_iter()
// }
// println!("test_extend_from_iter: {:?}", instant.elapsed());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment