【问题标题】:Should I allocate a Vec with bumpalo?我应该用 bumpalo 分配一个 Vec 吗?
【发布时间】:2021-12-23 10:42:53
【问题描述】:

我需要动态分配的数组,所以我需要一个内存池来有效地执行此操作。我找到了https://github.com/fitzgen/bumpalo,但它看起来不支持分配直接数组。我应该像这样分配一个向量:


use bumpalo::{Bump, collections::Vec};
let bump = Bump::new();
let mut v = Vec::new_in(&bump);

每次我需要时都得到它的切片?

问题是我无法强制矢量具有我想要的确切大小。我的数组始终具有固定大小(但大小在运行时确定)。我认为 Vec 适合体积变大的东西。

【问题讨论】:

  • 如果你的数组总是有一个固定的大小,你不能用数组代替向量吗? let v = bump.alloc([ElemType::default(); SIZE])
  • @user4815162342 我的意思是它是不变的意思是我不需要在完成后调整它的大小,但是大小是在运行时确定的,所以这样做是不可能的
  • 您始终可以将Vec 包装在不允许大小更改的自定义结构中。
  • @Lagerbaer 是的,但这不是重点。我想为这些分配使用一个内存池,以便它回收东西
  • 等一下...... “我想为这些分配使用内存池,以便它回收东西” - bumpalo::Bump 名义上是 bump allocator,它由 -设计不能重用释放的内存。 “凹凸分配的缺点是没有通用的方法来释放单个对象或为不再使用的对象回收内存区域。” - bumpalo readme。它似乎不适合回收内存池,至少在没有大量工作和计划​​的情况下并非如此。

标签: memory memory-management rust


【解决方案1】:

我想拥有数据并在需要时获取切片。

bumpalo 目前只提供可增长的集合,但编写一个不可增长的集合应该很简单。例如:

use std::marker::PhantomData;
use bumpalo::Bump;

#[derive(Debug)]
pub struct BumpArray<'bump, T> {
    data: &'bump mut [T],
    _marker: PhantomData<T>, // we're dropping T values
}

impl<'bump, T> BumpArray<'bump, T> {
    // Just an example - you could also provide `new_with()` or similar
    // with different bounds on `T`.
    pub fn new_default(bump: &'bump Bump, size: usize) -> Self
    where
        T: Default,
    {
        BumpArray {
            data: bump.alloc_slice_fill_default(size),
            _marker: PhantomData,
        }
    }

    pub fn as_slice(&self) -> &[T] {
        self.data
    }

    pub fn as_slice_mut(&mut self) -> &mut [T] {
        self.data
    }
}

impl<T> Drop for BumpArray<'_, T> {
    fn drop(&mut self) {
        if std::mem::needs_drop::<T>() {
            for val in self.data.iter_mut() {
                unsafe {
                    std::ptr::drop_in_place(val);
                }
            }
        }
    }
}

需要手动删除,因为 bumpalo 不调用 drop()。在这种情况下,它允许我们利用所有权并在单个元素上执行 drop (对于首先需要 drop 的类型),比整个 arena 被释放要快得多。它确实需要一点不安全,但很容易推理。如果您使用未实现 Drop 的类型,请随意省略 Drop 实现和 _marker 字段。

【讨论】:

  • 为什么我需要释放每个单独的元素?这个数组主要用于整数类型,所以我不会释放每一个。是否可以不释放每一个所以不要使用不安全的?
  • @GuerlandoOCs 如果您要存储数字等副本类型,则无需执行删除操作。这就是最后一句话所指的 - 如果您在数组中存储非Drop 类型,请随意省略整个Drop 实现。
  • @GuerlandoOCs 另一方面,如果您不删除元素,那么这种“拥有”类型与alloc_slice_fill_default() 返回的切片之间几乎没有区别。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-10
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
相关资源
最近更新 更多