【问题标题】:Owned arena data structure [duplicate]拥有的竞技场数据结构[重复]
【发布时间】:2016-06-14 13:02:48
【问题描述】:

我想为一个非常大(节点数)的图建模,该图由许多非常大(内存方面)的节点组成。由于节点如此之大,我只想将它们存储一次并将借用传递给它们,所以从概念上讲是这样的:

struct Graph<'a> {
    nodes: Vec<Node<'a>>,
}

struct Node<'a> {
    edges: HashMap<String, &'a Node>,
    // ...lots of other data...
}

当然没有办法像这样构造Graph,因为(a)Vec 不允许我在元素借用时添加新节点,并且(b)我不能告诉 rustc nodes 向量将终生存在 'a。我也不能使用像Rc 这样的东西,因为图表有循环。

我想表达的是一个竞技场,它让我可以分配很多Nodes,只要竞技场存在,就可以对它们进行不可变的借用,并使用生命周期检查来确保我取消分配竞技场时,没有剩余的Node 引用。比如:

struct Graph<'a> {
    nodes: Arena<'a, Node<'a>>,
}

struct Node<'a> {
    edges: HashMap<String, &'a Node>,
}

impl<'a, A> Arena<'a, A> {
    fn own(&self, a: A) -> &'a A {
        // magic
    }
}

impl<'a, A> Drop for Arena<'a, A> {
    fn drop(&'a mut self) {
        // magic
    }
}

这在语义上可以用 Rust 表达吗?

【问题讨论】:

  • crates.io 上搜索“arena”提供了许多结果。一个这样的箱子是typed-arena
  • 我也不能使用像Rc 这样的东西,因为图表有循环。 — 不完全正确;当您有周期性数据时,您可以引入Weak 引用。 module-level documentation 有一个例子。
  • @Shepmaster typed-arena 实现让我可以借用,但这些借用绑定到 &amp;mut 生命周期,我无法连接到竞技场的生命周期。不过,我会尝试使用弱引用。

标签: graph rust lifetime ownership


【解决方案1】:

一个简单的解决方案是使用typed-arena crate。它包含一个Arena 类型和一个fn alloc(&amp;self, T) -&gt; &amp;mut T 方法。

另一个简单的解决方案是使用索引而不是引用(并且永远不要从Vec 中删除,因为这会使索引无效)。在 64 位平台上,使用 32 位索引可以减少一些字节。

然而,这两种解决方案都无法删除节点。您可能会停止引用它们,但它们仍将存在于内存中,因此将它们用于动态图(节点来去处)需要更多的工作。在这种情况下,我的建议是定期从一个新的竞技场创建一个新的图克隆(不复制未使用的节点),这类似于使用移动垃圾收集器,如果不那么自动化的话。

【讨论】:

  • 在 64 位平台上,使用 32 位索引可以减少一些字节。 — 这是否需要在 u32usize 之间进行多次转换?
  • @Shepmaster:嗯,在硬件层面,当然需要强制转换;然而,在软件级别,如果向量被正确封装,访问函数采用u32,那么您应该只获得一两个as usize
  • @MatthieuM。您能否演示一下typed-arena 如何让我以一种可以让我将该图封装在struct 中的方式构建一个图表?
  • @MatthieuM。 (我之前使用过typed-arena,但我只让它在单个堆栈框架中工作)
  • @dflemstr:我建议typed-arena,因为你说的是​​竞技场,但是由竞技场创建的项目借用了竞技场(因为在竞技场死后你不能引用该项目)和兄弟Rust 中不允许借用关系,因此确实竞技场本身不会成为图表的一部分。我认为这不是什么大问题(只要你有一个生命周期的上限)。如果有必要成为图表的一部分,那么Vec + 索引解决方案更容易。
猜你喜欢
  • 1970-01-01
  • 2012-03-01
  • 2015-08-29
  • 1970-01-01
  • 2012-06-07
  • 2017-01-28
  • 2019-03-20
  • 2018-01-16
  • 2022-01-15
相关资源
最近更新 更多