本文講述在編寫C程序代碼的常用優化辦法,分為I/O篇,內存篇,算法篇,MMX匯編篇。
一.I/O篇
如果有文件讀寫的話,那么對文件的訪問將是影響程序運行速度的一大因素。提高文件訪問速度的主要辦法有兩個:一是采用內存映射文件,二是使用內存緩沖。下面是一組測試數據(見《UNIX環境高級編程》3.9節),顯示了用18種不同的緩存長度,讀1 468 802字節文件所得到的結果。
緩沖大小 | 用戶CPU(秒) | 系統CPU(秒) | 時鐘時間(秒) | 循環次數(秒) |
1 | 23.8 | 397.9 | 423.4 | 1 468 802 |
2 | 12.3 | 202.0 | 215.2 | 734 401 |
4 | 6.1 | 100.6 | 107.2 | 367 201 |
8 | 3.0 | 50.7 | 54.0 | 183 601 |
16 | 1.5 | 25.3 | 27.0 | 91 801 |
32 | 0.7 | 12.8 | 13.7 | 45 901 |
64 | 0.3 | 6.6 | 7.0 | 22 951 |
128 | 0.2 | 3.3 | 3.6 | 11 476 |
256 | 0.1 | 1.8 | 1.9 | 5 738 |
512 | 0.0 | 1.0 | 1.1 | 2 869 |
1 024 | 0.0 | 0.6 | 0.6 | 1 435 |
2 048 | 0.0 | 0.4 | 0.4 | 718 |
4 096 | 0.0 | 0.4 | 0.4 | 359 |
8 192 | 0.0 | 0.3 | 0.3 | 180 |
16 384 | 0.0 | 0.3 | 0.3 | 90 |
32 768 | 0.0 | 0.3 | 0.3 | 45 |
65 536 | 0.0 | 0.3 | 0.3 | 23 |
131 072 | 0.0 | 0.3 | 0.3 | 12 |
可見,一般的當內存緩沖區大小為8192的時候,性能就已經是最佳的了,這也就是為什么在H.263等圖像編碼程序中,緩沖區大小為8192的原因(有的時候也取2048大小)。使用內存緩沖區方法的好處主要是便于移植,占用內存少,便于硬件實現等。下面是讀取文件的C偽碼:
int Len;
BYTE buffer[8192];
ASSERT(buffer==NULL);
If buffer is empty{
Len=read(File,buffer,8192);
If(len==0) No data and exit;
}
但是如果內存比較大的時候,采用內存映射文件可以達到更佳性能,并且編程實現簡單。內存映射的具體使用說明見msdn October 2001中的Platform SDK
Documentation—Base Services—File Storage—File Mapping。下面是一點建議:
① 內存映射文件不能超過虛擬內存的大小,最好也不要太大,如果內存映射文件接近虛擬內存大小的時候,反而會大大降低程序的速度(其實是因為虛擬內存不足導致系統運行效率降低),這個時候,可以考慮分塊映射,但是我覺得如果這樣,還不如直接使用內存緩沖來得直接一些。
② 可以將兩種方法統一使用,如我在編大圖像文件數據處理的時候(因為是Unix工作站,內存很大GB單位)使用了內存映射文件,但是為了最佳性能,也使用了一行圖像緩存,這樣在讀取文件中數據的時候,就保證了僅僅是順序讀寫(內存映射文件中,對順序讀寫有專門的優化)。
③ 在寫文件的時候使用內存映射文件要有一點小技巧:應該先創建足夠大的文件,然后將這個文件映射,在處理完這個文件的時候,用函數SetFilePointer和SetEndOfFile來對文件進行截尾。
④ 對內存映射文件進行操作與對內存進行操作類似(使用起來就象數組一樣),那么如果有大塊數據讀寫的時候,切記使用memcpy()函數(或者CopyMemory()函數)
總之,如果要使用內存映射文件,必須:1.處理的文件比較的小,2.處理的文件很大,但是運行環境內存也很大,并且一般在運行該程序的時候不運行其他消耗內存大的程序,同時用戶對速度有特別的要求,而且對內存占用沒有什么要求。如果以上兩個條件不滿足的時候,建議使用內存緩沖區的辦法。