我应该通过引用或值传递大数组吗?

时间:2015-02-10 04:37:32

标签: performance pass-by-reference rust pass-by-value

我正在Rust中构建一个Game Boy模拟器。我创建了一个readByteFromMemory()函数,它将8KB数组作为参数,表示Game Boy的内存为8KB。我在考虑两种选择:

fn readByteFromMemory(internalRAM: [u8;0x2000]) -> u8

fn readByteFromMemory(internalRAM: &[u8;0x2000]) -> u8

我唯一可以找到引用此主题的内容是本文:http://words.steveklabnik.com/pointers-in-rust-a-guide,其中指出:

But don’t reach for that pointer until you must! Make sure that the 
struct is large enough by performing some tests before you add in the 
complexity of pointers.

我对这两个选项进行了基准测试,似乎无论优化器是打开还是关闭,指针1的传递都要快得多(正如预期的那样)。

虽然有趣的是,如果关闭优化器,传递值会略快一些:

➜  rustTest$  rustc --test -O passByTest.rs
➜  rustTest$  ./passByTest --bench         

running 2 tests
test ptrBench   ... bench:         1 ns/iter (+/- 0)
test valueBench ... bench:       221 ns/iter (+/- 2)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured

➜  rustTest$  rustc --test  passByTest.rs 
➜  rustTest$  ./passByTest --bench       

running 2 tests
test ptrBench   ... bench:        13 ns/iter (+/- 3)
test valueBench ... bench:       152 ns/iter (+/- 1)

我的问题是:什么似乎是以字节为单位的阈值,通过引用传递对传递值有意义?

1 个答案:

答案 0 :(得分:1)

我无法直接回答你的问题,因为正如许多其他事情一样,它取决于代码的位置,它周围的代码在做什么,访问模式是什么,等等,等等,等等。如果您对性能感到担心,您必须对进行分析。

那说......

  • "大"在Rust中通过值传递的值实际通过引用传递为优化。通过" large",我相信它比任何指针更重要。同样,这是一个优化,所以你依靠编译器在这里做出合理的选择。在大多数情况下,它应该正确选择。

    另请注意,您无法按价值逻辑传递,实际上是通过参考" (这是编译器正在做的事情)你自己;这意味着使用&move引用,但该语言尚不存在。

    我相信史蒂夫的评论应该更加自由地解释为:"不要自己覆盖编译器除非分析告诉你。&#34

  • 两者之间有什么区别吗?是!如果您传递[u8; 0x2000],则调用者必须在传递值之前制作值的副本,假设您希望以后能够再次使用它。这可能是绩效差异的来源。

    请注意,如果要将值移动到函数中,编译器不会复制。这包括所有不可复制的类型(例如BoxStringVec),而 应包含编译器知道您不可复制的可复制类型再次使用。

适当的选择是&[u8; 0x2000]因为:

  • 您只需要从值读取,如果您想要修改它,您需要&mut [u8; 0x2000]
  • 您不想拥有该值的所有权(在这种情况下,您会通过值传递)。

再次强调:不要开始玩#34;这是一个很大的价值,因此我将使用传递参考"因为编译器已经这样做了,而且你很难手动完成它。