过度工程:在 Rust 中的 HashMap 键上使用引用借用?

问题描述

我正在制作一个搜索算法 (BFS/DFS) 来搜索游戏状态树。 我已经用 C 语言完成了这个东西,但我想知道 Rust 是否会更快,因为我一直想学习 Rust,所以我想我会试一试。

我正在尝试将这件事优化到过度工程的地步(我喜欢它,让我来吧),我用 C 语言做了一个我认为很酷的优化,但我不知道如何(/如果可能的话)在 Rust 中。

我的算法大纲是这样的:

Add the start state to a queue,and make a hashmap [State -> PrevIoUs State,Action]
// I use this hashmap to find the way back later,and to check if I have been in a state before.

Take a state S0 from the queue:
   for all possible actions,calculate next state S1:
      if S1 is already a key in the hashmap,continue
      and add [ S1 -> S0,action taken ] to the hashmap
      add S1 to the queue,...
   // some other stuff here to check when to stop

我在 C 中所做的优化之一是:我没有将状态结构数据复制到队列中,而是将指向哈希图中相同数据的指针(因为我只是将其添加到哈希图中)复制到队列中,这样我就不必复制状态数据,但队列只是由指向哈希图中相同数据的指针组成。

这在 C 中很容易运行,因为我有自己的 hashmap 实现,所以很容易制作一个函数来返回指向 hashmap 中正确数据的指针。

在 Rust 中,我现在有了这个:

// Add all possible moves to be searched through later
for m in possible_moves.iter() {
    if let Some(new_state) = popped.do_move(m) { // popped is S0 from my algorithm outline
        if backmap.contains_key(&new_state) { continue; }
        queue.push_back(new_state);
        backmap.insert(new_state,Wayback {
        prev_state: popped,did_move: m });
    }
}

但这意味着new_state数据被复制到队列和hashmap中。 我想知道是否有一种方法可以不在 Rust 中复制这些数据,比如我的 C 版本(或其他方式)。

我喜欢这个优化,因为我只是喜欢它的优化感觉,但在 Rust 的情况下也是因为现在这个副本意味着我有 #[derive(Clone,copy)] 高于我的所有结构,这不是很好的 imo,如果没有办法进行我过度设计的优化,但有一种方法不必派生来复制和克隆我仍然想知道的特征。

非常感谢您的帮助!

附言我知道这不是您的常规代码问题,从我的解释中可能不太清楚,所以如果对我的意思有任何疑问,我会尽快回答。

解决方法

我喜欢这种优化,因为我只是喜欢它的优化感觉,但在 Rust 的情况下也是因为现在这个副本意味着我在所有结构之上都有 #[derive(Clone,Copy)],这不是不错的我

取决于结构的大小……这真的很重要吗? Copy 只是一个 memcpy

如果没有办法进行我过度设计的优化,但有一种方法不必派生来复制和克隆特征,我仍然想知道。

这里的问题是 Rust 想要每个数据都有一个明确的静态所有者,但这在您的算法中并不存在:状态由地图和队列“拥有”。 “共享”不清楚所有权的方法是使用 Rc,但这会转化为堆分配(当它不是原子时,引用计数流量并不重要),如果 {{1 }}