我需要Rust中的快速堆栈。每秒需要创建/销毁数百万个这样的内容,每个内容只需要一个固定的深度。我在尽可能加快速度。我想出了以下方法(基本上是教科书式的堆栈实现):
const L: usize = 1024;
pub struct Stack {
xs: [(u64, u64, u64, u64); L],
sz: usize
}
impl Stack {
pub fn new() -> Self {
Self { xs: [(0, 0 ,0, 0); L], sz: 0 }
}
pub fn push(&mut self, item: (u64, u64, u64, u64)) -> bool {
if (self.sz + 1) <= L {
self.xs[self.sz] = item;
self.sz += 1;
true
} else {
false
}
}
pub fn pop(&mut self) -> Option<(u64, u64, u64, u64)> {
(self.sz > 0).then(|| {
self.sz -= 1;
self.xs[self.sz]
})
}
}
问题是memset
,不需要。所以我试着删掉它:
pub fn new2() -> Self {
let xs = std::array::from_fn(|_| unsafe { MaybeUninit::uninit().assume_init() });
Self { xs, sz: 0 }
}
这去掉了memset
,但是现在我有一个警告:
|
18 | let xs = std::array::from_fn(|_| unsafe { MaybeUninit::uninit().assume_init() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
= note: integers must not be uninitialized
= note: `#[warn(invalid_value)]` on by default
如果未初始化的整数导致未定义的行为,是否有可能创建这种堆栈,其中堆栈的逻辑保证正确的行为,并避免不必要的内存操作?
你需要一直使用MaybeUninit
。将数组更改为MaybeUninit
s数组:
use std::mem::MaybeUninit;
const L: usize = 1024;
pub struct Stack {
xs: [MaybeUninit<(u64, u64, u64, u64)>; L],
sz: usize
}
// From standard library
// https://doc.rust-lang.org/stable/src/core/mem/maybe_uninit.rs.html#350-353
#[must_use]
#[inline(always)]
pub const fn uninit_array<const N: usize, T>() -> [MaybeUninit<T>; N] {
// SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid.
unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() }
}
impl Stack {
pub fn new() -> Self {
Self { xs: uninit_array(), sz: 0 }
}
pub fn push(&mut self, item: (u64, u64, u64, u64)) -> bool {
if (self.sz + 1) <= L {
self.xs[self.sz].write(item);
self.sz += 1;
true
} else {
false
}
}
pub fn pop(&mut self) -> Option<(u64, u64, u64, u64)> {
(self.sz > 0).then(|| {
self.sz -= 1;
// Safety: The value has been initialized
unsafe {
self.xs[self.sz].assume_init()
}
})
}
}