第41期:文件的性能分析
我們以前講過硬盤的性能特征,主要是針對硬件層面進行分析的,現(xiàn)在我們來考慮軟件層面的差異。
理論上講,軟件可以穿過操作系統(tǒng)直接進行磁盤扇區(qū)的訪問,但實在太過于麻煩而幾乎不會實踐機會,這里就不考慮了,我們只討論操作系統(tǒng)下的存儲形式,而文件就是其中重要的存儲形式。
文件一般有兩種:文本文件和二進制文件,我們分別來討論。
文本文件
文本是很常見的數(shù)據(jù)存儲形式,它具有通用性易讀性等優(yōu)點而被廣泛使用。但是,文本的性能卻非常差!
文本字符不能直接運算,需要轉(zhuǎn)換成整數(shù)、實數(shù)、日期、字符串等內(nèi)存數(shù)據(jù)類型才可以進一步處理,而文本的解析是個非常復(fù)雜的任務(wù)。
舉個例子,設(shè)想一下把文本“12345"轉(zhuǎn)成內(nèi)存二進制整數(shù)12345的過程:
- 先設(shè)結(jié)果的初始值為0
- 拆出字符“1”,解析出數(shù)值1,將初值0乘以10加上這個1得到數(shù)值1
- 再拆出字符“2”,解析出數(shù)值2,把剛才的1乘以10和這個2相加得到數(shù)值12
- 再拆出字符“3”,解析出數(shù)值3,把剛才的12再乘以10加上這個3得到數(shù)值123
- ...
有些C程序員知道用函數(shù)atoi()可以實現(xiàn)字串到整數(shù)的轉(zhuǎn)換,僅僅一句代碼,看似非常簡單,但其實背后的步驟非常多,CPU要干很多事才能完成這個動作,耗時并不短。實際過程中還要判斷可能出現(xiàn)的非法字符(比如不是數(shù)字的字符),比上面描述的步驟還要更復(fù)雜得多。
整數(shù)還是最簡單的數(shù)據(jù)類型,如果是實數(shù)還要處理小數(shù)點,字符串解析時要考慮轉(zhuǎn)義字符和引號匹配,日期的解析更是要麻煩得多,因為格式種類太多,2018/1/10和10-1-2018都是常見的合法日期格式,甚至還有Jan-10 2018這種,要正確解析,就得嘗試用多種格式去匹配,CPU耗時很嚴重。
一般來講,外存數(shù)據(jù)訪問的主要時間是在硬盤本身的讀取上,而文本文本的性能瓶頸卻經(jīng)常發(fā)生在CPU環(huán)節(jié)。因為解析的復(fù)雜性,CPU耗時很可能超過硬盤耗時(特別是采用高性能固態(tài)硬盤時)。文本是非常慢的,需要高性能處理大數(shù)據(jù)時不要使用文本!
但是,有些原始數(shù)據(jù)(如日志)只有文本形式,解析文本就是不可避免的任務(wù)。這時候,一方面可以采用并行技術(shù),利用多CPU并行度更高的特性,由多個線程同時解析文本,這樣即使仍然串行訪問硬盤也能獲得更高的文本處理性能;另一方面,這些數(shù)據(jù)如果需要反復(fù)使用,那么***是轉(zhuǎn)換成二進制格式存儲,第二次使用不要再次解析。
二進制文件
二進制文件中,我們會將各種數(shù)據(jù)類型對應(yīng)的內(nèi)存字節(jié)直接寫出到文件中,再讀取時也只要直接取出重新裝載成內(nèi)存數(shù)據(jù),沒有復(fù)雜的解析過程,也不需要判斷和識別非法情況,這時性能就會好很多。
不過,用二進制數(shù)據(jù)存儲時需要考慮好壓縮手段,否則在某些極端情況下會比文本的存儲空間更大,雖然解析時間縮短,但硬盤訪問時間會變長。
比如整數(shù)1,用文本存儲時只要占一個字節(jié),即使加上分隔符也就兩個字節(jié)。而如果要把所有整數(shù)都按32位整數(shù)處理(當前計算機的整數(shù)數(shù)據(jù)類型大多數(shù)是這個位長),就需要用4個字節(jié)來存儲,比文本大了一倍,有時可能還要加上數(shù)據(jù)類型本身的信息,就會更長。
對于這種情況,合理的做法是根據(jù)數(shù)的大小決定位長,比如小整數(shù)只存儲一個字節(jié)或兩個字節(jié),大整數(shù)才存儲更多的字節(jié),因為小整數(shù)較常見,結(jié)果會使得總體存儲空間降低,從而獲得性能優(yōu)勢。
但是,壓縮率并不是越高越好,解壓縮需要消耗CPU時間。象上面說的,把整數(shù)分大小存儲能夠減少空間,但在解析時就要多一重判斷,又降低一點性能。***采用的壓縮方案,要在硬盤空間的減少和CPU的消耗中取得某種平衡。如果一味地追求壓縮率(比如使用zip壓縮算法),空間是降低得更多,但CPU時間將會超過硬盤時間,整體性能反而下降。
不過,無論如何,二進制文件仍然是最快的存儲格式。采用簡單壓縮方案的二進制文件,即使同樣采用行式存儲,一般也能達到比文本高4-5倍的性能。使用二進制格式,還有可能使用前面文章中提到過的分段并行技術(shù)和列存技術(shù),從而獲得更高的性能。



























