Rust程式語言內建的String結構體,可以用來儲存可變動的字串。在串接字串的時候,經常會使用到String結構實體的「push_str」方法,將其它字串複製進該String結構實體現有的字串資料之後,其背後是使用Vec結構實體的「extend_from_slice」方法來處理的,效能雖然還算不錯,但如果要串接的字串還沒產生出來呢?我們只能先把要串接的字串產生出來之後,再把它複製進另一個String結構實體中嗎?何不在現有String結構實體中的字串資料之後,直接產生新的字串呢?



我們先來看看以下程式碼:

let number: f64 = 45.48;
let mut s = String::new();
s.push_str(&format!("Hello! {}.", number));

以上程式,在串接字串之前,程式會先產生出「Hello! 45.48」這個暫時的String結構實體,然後再將其參考傳給「s」這個String結構實體的「push_str」方法,來將參考到的字串給複製進「s」這個String結構實體。也就是說,使用這個方式,免不了會發生字串複製。然而,記憶體中資料的複製我們應該要儘可能地避免,因為它會影響到程式效能。

我們可以使用String結構體已經實作的Rust標準函式庫「std::fmt」模組中的「Write」特性,將該特性用「use」關鍵字引用到目前程式範圍之下,就可以使用能接受「format_args」巨集的回傳值的「write_fmt」方法了。以上程式可以改寫如下:

use std::fmt::Write;

let number: f64 = 45.48;
let mut s = String::new();
s.write_fmt(format_args!("Hello! {}.", number)).unwrap();

所以String結構實體的「push_str」和「write_fmt」方法到底哪個更快?顯然我們可以猜測是不需複製字串的「write_fmt」方法會比「push_str」方法還快。

實測看看?

為了驗證我們的猜測,就要實際寫一段程式來測試運算效能啦!這段程式可以在GitHub上取得:

根據測試結果我們可以發現,「write_fmt」方法加上「format_args」巨集確實會比「push_str」方法加上「format」巨集還要快!