2016-06-28 61 views
2
struct Vec { 
    data: [f32; 3], 
} 

impl Vec { 
    fn dot(&self, other: &Vec) -> f32 { 
     .. 
    } 
    // vs 
    fn dot(self, other: Vec) -> f32 { 
     .. 
    } 
} 

我目前正在寫矢量數學庫,我想知道是否應該借用或複製我的矢量類型。我應該借用還是複製我的小數據類型?

目前我執行CopyVec這使得API更好一些,因爲您不必一直編寫&

但它需要更復雜的約束,因爲現在我所有的約束條件也需要滿足Copy

哪一個可能產生更好的性能,爲什麼?

哪一個可能產生更好的人體工程學,爲什麼?

編輯:

我創建了一個小microbenchmark

test bref_f32 ... bench: 2,736,055 ns/iter (+/- 364,885) 
test bref_f64 ... bench: 4,872,076 ns/iter (+/- 436,928) 
test copy_f32 ... bench: 2,708,568 ns/iter (+/- 31,162) 
test copy_f64 ... bench: 4,890,014 ns/iter (+/- 553,050) 

似乎有這個例子在性能方面refcopy之間沒有什麼區別。

Copy似乎爲圖書館用戶提供了更好的人體工程學設計。

+2

你確定你想問一下「慣用」而不是「表演」或「簡化界限」嗎?因爲成語非常*主觀*,我恐怕可以推薦兩種選擇,並且不存在明確的客觀答案......在這種情況下,您的問題已經準備好關閉(主要基於意見)。 –

+0

@MatthieuM。我認爲有一些關於習慣Rust代碼應該是什麼樣的指南,我重新提出了這個問題並添加了一個例子。 –

回答

1

鏽不是一個純粹的學術語言與崇高的美學目標和單一目的。 Rust是一種系統編程語言,這意味着實用主義。

一般的經驗法則是,你的界面應該正確記錄所有權

  • 路過當你放棄所有權
  • 通過引用傳遞(可能可變)值,當你暫時放棄所有權

然而,Copy特質是實用主義的完美典範。它認識到通過引用可能會很麻煩(是否有人想輸入(&1 + &x) * &y?),因此爲不需要仿射的類型(即對破壞沒有特別的操作)創建一個逃生艙口。

其結果是,在語義上,如果你的類型可以是保證成爲並保持Copy,然後將其標記爲這樣爲用戶提供了其使用可提高工效一些餘地。我鼓勵你對它進行標記,然後,儘管提醒以後刪除Copy特性將是一個落後的不兼容變化。

一旦類型爲Copy,我會毫不猶豫地利用這一事實並將其傳遞給客戶。畢竟,如果這個類型永遠不會被數值傳遞,那麼首先就沒有必要使它成爲Copy


唯一要注意的是性能的原因。

Copy確實不是強制一個副本,它只是允許它。這意味着優化器具有使用副本的全部自由度。

對於小型企業來說,無論發生什麼事情,績效都不會有太大的不同;對於更大的類型,如果性能很重要,我會鼓勵對各種接口進行基準測試Vec僅爲64位體系結構指針/引用大小的1.5倍,因此它確實處於灰色區域。有時候複製會比較慢(較大的複製),但有時使用本地副本的好處將使優化不會被指針觸發。

但是,這樣的基準測試充滿了危險,尤其是因爲它極大地依賴於函數是否內聯(給定或多或少的移除副本的餘地)。

4

我建議在這種情況下借款,因爲它似乎並不像所有權是一個問題。所以,我想你的代碼看起來像

struct Vec { 
    data: [f32; 3], 
} 

impl Vec { 
    fn dot(&self, other: &Vec) -> f32 {..} 
} 
+1

你能解釋一下爲什麼你會推薦這個嗎? –

+0

我推薦它,因爲它使用更多的內存來創建一個全新的矢量,這是複製矢量時發生的情況。如果你不需要創建一個新的矢量,不要。 –

+1

*這是當你複製一個向量時會發生什麼* - 如果它決定它可以被簡化,它可以達到優化編譯器的奇思妙想。 – Shepmaster

相關問題