小夕说,不了解动态空间增长的程序喵都是假喵(下)
小夕在本系列前兩篇文章中為大家介紹了各類數(shù)據(jù)結(jié)構(gòu)的擴(kuò)容策略,且在上篇文末,小夕提到了加倍式擴(kuò)容中,倍率采用2并不是最優(yōu)的,為什么呢?有沒有最優(yōu)倍率呢?
?
內(nèi)存復(fù)用
如果倍率采用2甚至更大的數(shù),那么被開辟過的舊空間永遠(yuǎn)都不會被新開辟的空間利用。小夕舉個栗子。
?
if(倍率≥2){
那么以下是小夕為大家畫的三次擴(kuò)容后的內(nèi)存塊的占用情況(小夕用PPT畫的,好麻煩的喵,讀者喵有好用的輕量級畫矢量圖的軟件記得推薦給小夕哦~)
?
?
上圖中,內(nèi)存塊一共有15個字節(jié)。粉色實(shí)心框是數(shù)據(jù)結(jié)構(gòu)占用的內(nèi)存塊,空心框是空閑的內(nèi)存。
?
假如一開始數(shù)據(jù)結(jié)構(gòu)的大小是1字節(jié),占用了0xFF00這個字節(jié),如圖中第一列。然后第一次擴(kuò)容后數(shù)據(jù)結(jié)構(gòu)大小變成2字節(jié),無法利用之前的舊內(nèi)存空間。
同樣,第二次擴(kuò)容,第三次擴(kuò)容后,數(shù)據(jù)結(jié)構(gòu)的大小總是要比之前累計占用的舊內(nèi)存空間之和還要大,總是大1個字節(jié),所以永遠(yuǎn)都無法重新利用之前的舊內(nèi)存空間。
?
那么無法復(fù)用舊內(nèi)存空間,對應(yīng)有程序與操作系統(tǒng)各有什么影響呢?小夕還沒有探索出嚴(yán)謹(jǐn)?shù)慕Y(jié)論,讀者有思路可以跟小夕一起討論哦~
?
如果倍率改為比2大的數(shù),結(jié)果是一樣的。有興趣的喵喵可以自行畫畫圖~當(dāng)然,數(shù)學(xué)好的喵喵不用畫圖也能證明出來的~(利用幾何級數(shù)的性質(zhì))
}
?
if(倍率<2&&倍率>1){
比如倍率采用1.5。小夕再畫一下圖~
?
可以看到,第三次擴(kuò)容后的新數(shù)據(jù)結(jié)構(gòu)大小約為338B!而舊空間的大小是250+225=475>338,也就是說新的哈希表可以挪到舊的內(nèi)存空間了!內(nèi)存得到了復(fù)用!
?
好咯,說到這里,讀者應(yīng)該懂了,對于加倍式擴(kuò)容,倍率必須小于2才能復(fù)用內(nèi)存。那么為什么默認(rèn)值取1.5,而不是1.6,1.7呢?小夕查了很多資料,發(fā)現(xiàn)這是一個啟發(fā)式策略(啟發(fā)式策略就是拍腦袋想出來的看似合理而沒有嚴(yán)謹(jǐn)理論依據(jù)的方法)。
?
一個疑問
?
那么既然看似倍率用1.5要優(yōu)于2,為什么Java中的哈希表系列以及C++中的Vector卻采用2呢?
?
這就是理論與工程的不同之處。在工程中不僅要考慮內(nèi)存復(fù)用這一個問題,還要考慮到浮點(diǎn)數(shù)運(yùn)算問題和大量數(shù)據(jù)場景下的擴(kuò)容速度的問題。
?
具體來說,若采用1.5倍,那么假設(shè)數(shù)據(jù)結(jié)構(gòu)初始大小為10,則以后的數(shù)據(jù)結(jié)構(gòu)大小會依次計算為:
15,
22.5,
33.75,
50.625,
75.9375
...
?
可以看到浮點(diǎn)運(yùn)算的代價會越來越高。
?
擴(kuò)容速度也很好理解。大量數(shù)據(jù)時,2倍擴(kuò)容速度會比1.5倍擴(kuò)容速度少很多次擴(kuò)容次數(shù),因此效率會比1.5倍高很多。那么當(dāng)程序不怎么看重內(nèi)存復(fù)用,卻有大量數(shù)據(jù)待填入數(shù)據(jù)結(jié)構(gòu)時,2倍是更合理的。
?
So
雖然很多數(shù)據(jù)結(jié)構(gòu)都是基于靜態(tài)數(shù)組實(shí)現(xiàn)的動態(tài)空間增長,但是有的是上述提到的2倍的擴(kuò)容倍率,有的像Java中的ArrayList則為1.5倍的擴(kuò)容倍率。
?
看來如何決定倍率,要在設(shè)計數(shù)據(jù)結(jié)構(gòu)的時候好好考慮這個數(shù)據(jù)結(jié)構(gòu)將來的業(yè)務(wù)場景呢。
PS:
沒有發(fā)現(xiàn)小夕在上面的一個if語句中漏了一半括號的C/C++/Java等程序員請自覺面壁思過。
?
最后,不知道您對小夕的文章是否滿意呢(?????????)
小夕已委托維權(quán)騎士對小夕發(fā)布文章的版權(quán)行為進(jìn)行追究與維權(quán)。歡迎大家轉(zhuǎn)發(fā)分享~如需轉(zhuǎn)載,請聯(lián)系微信xiyaomengmengda。?
總結(jié)
以上是生活随笔為你收集整理的小夕说,不了解动态空间增长的程序喵都是假喵(下)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android自定义Lint实践
- 下一篇: 基本功 | Litho的使用及原理剖析