本系列文章是Jon Gjengset發布的CRust of Rust系列視頻的學習筆記,CRust of Rust是一系列持續更新的Rust中級教程。
在這篇文章中,我們將接著上一篇文章對avec!宏做性能優化。
先看一下已經寫好的代碼:
1#[macro_export] 2macro_rules!avec{ 3...... 4($element:expr;$count:expr)=>{{ 5letmutvs=Vec::new(); 6letx=$element; 7for_in0..$count{ 8vs.push(x.clone()); 9} 10vs 11}}; 12}
在第5行,我們創建了一個空的Vector,然后在第8行進行了一堆的push操作。
假設我們有1024個元素要放入到Vector中,那就進行了1024次push操作,就會導致在堆內存上對Vector進行多次重新分配。這是因為在 vector 增加新元素時,如果沒有足夠的空間就會要求分配大小是原內存2倍的新內存,并將老的元素拷貝到新的空間中,再銷毀舊內存中的數據。
第一個需要改進的地方是:將創建空Vector的語法Vec::new()改成Vec::with_capacity(count),根據count大小預先分配內存空間,這樣就避免了一堆的內存重新分配操作。
1#[macro_export] 2macro_rules!avec{ 3...... 4($element:expr;$count:expr)=>{{ 5letcount=$count; 6letmutvs=Vec::with_capacity(count); 7letx=$element; 8for_in0..count{ 9vs.push(x.clone()); 10} 11vs 12}}; 13}第二個需要改進的地方是push,盡管已經預先分配了內存空間,但是每次執行push操作后,指向元素的指針地址都會增長,都會進行邊界檢查,這是不需要的。修改如下:
1#[macro_export] 2macro_rules!avec{ 3...... 4($element:expr;$count:expr)=>{{ 5letcount=$count; 6letmutvs=Vec::with_capacity(count); 7vs.extend(std::repeat($element).take(count)); 8vs 9}}; 10}
我們使用Vector的extend方法,參數需要一個iterator,我們使用了標準庫的std::repeat函數,它會把element元素進行clone。使用extend方法的好處是只會對iterator的范圍進行一次邊界檢查,這樣就更加高效。
我們也可以使用Vector的resize方法:
1#[macro_export] 2macro_rules!avec{ 3...... 4($element:expr;$count:expr)=>{{ 5//letcount=$count; 6//letmutvs=Vec::with_capacity(count); 7//vs.extend(std::repeat($element).take(count)); 8letmutvs=Vec::new(); 9vs.resize($count,$element); 10vs 11}}; 12}至此,關于Rust的聲明宏就學習完了。
審核編輯:湯梓紅
-
內存
+關注
關注
8文章
2767瀏覽量
72779 -
代碼
+關注
關注
30文章
4557瀏覽量
66826 -
Rust
+關注
關注
1文章
223瀏覽量
6388
原文標題:CRust學習筆記:聲明宏-3
文章出處:【微信號:Rust語言中文社區,微信公眾號:Rust語言中文社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論