最近的項目用到了QT 5.5,項目在運行過程當中出現了一段時間CPU佔用率持續25%,並頻繁斷網的狀況,遂決定對項目性能進行優化。html
優化工具也是VS2010自帶的性能分析工具,具體的使用方法參見:http://www.cnblogs.com/smark/archive/2011/10/12/2208039.html數據庫
其中能夠選擇「just my code」過濾出本身編寫的代碼。數組
項目中有將QByteArray中的二進制數如」123」格式化成」31, 32, 33」的功能,使用的代碼以下:性能優化
1 QByteArray msg = xxx 2 3 QString str; 4 5 foreach (quint8 b, msg) 6 7 { 8 9 str.append(QString().sprintf(「%02X」, b)); 10 11 }
當msg中包含6,7w個字符時,在lz酷睿2代i5的機器上,這段代碼須要執行4到5s,由於其中的QString會調用new函數6,7w此,對性能影響極大。優化後的代碼以下:數據結構
1 QString buildString(const QByteArray& ba) 2 3 { 4 5 static const char ascii[] = {‘0’, ‘1’, ‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘9’,‘A’,‘B’,‘C’,‘D’,‘E’,‘F’}; 6 7 QString buf; 8 9 buf.resize(ba.length() * 3); 10 11 int i = 0; 12 13 foreach (quint8 b, ba) 14 15 { 16 17 buf[i] = ascii[b >> 4]; 18 19 buf[i + 1] =ascii[b & 0xF]; 20 21 buf[i + 2] = ‘, ’; 22 23 24 25 i += 3; 26 27 } 28 29 if (i > 0) 30 31 i –= 3; 32 33 buf[i] = ‘\0’; 34 35 return buf; 36 37 }
從新運行後,CPU耗時120ms左右,性能提高了幾十倍。app
在界面功能中有一處表格顯示的功能,顯示接收到的數據,在原始的代碼中,當接收到一條數據,填充到表格上時,就調用一次表格scrollTo方法,當1s接收到2,3百條數據時,就會調用2,3此scrollTo方法,直接致使了界面頻繁更新。ide
優化的方法是,考慮到人眼的觀察能力,將刷新頻率即scrollTo的函數調用固定爲1s一次,減小了2,3百此的界面重繪,下降了CUP負載。函數
項目中有一處更新時戳的功能,記錄某些狀態是否已經超時,原始代碼中經過QDateTime記錄時戳,當數據到來時會調用QDateTime::currentDateTime更新時戳,當有大量數據到來時會頻繁更新時戳,經過性能分析發現此處調用總CPU使用率的7%。考慮該時戳只須要統計時間間隔,遂優化後改用time.h中的clock函數打時戳,該函數返回至程序啓動的毫秒數。再次進行性能分析顯示此處調用降到CPU使用率的0.23%,性能提高明顯。工具
項目中有一處數據庫記錄update操做,將QByteArray更新到數據庫中,程序中使用了QT中的儲存過程API,將QByteArray變量綁定到QSqlQuery對象上,參考代碼以下:性能
1 QSqlQuery query(db); 2 3 QByteArray data; 4 5 query.prepare(「update table set data = ? where id = ?」); 6 7 query.bindValue(0, data); 8 9 query.bindValue(1, id);
其中data中包含6,7w個數據,其中發現程序在query.bindValue(data)上耗時最多,打印日誌發現該data中的內容一定爲可顯示的ascii,遂將代碼改成
1 query.bindValue(0, QString(data));
減小了QByteArray轉換成QString的時間。
其餘優化還包括數據結構的調整,包括將2,3百條數據的數組改爲map結構儲存等。
固然對軟件的優化仍是用遵循相應的原則,好比不要過早優化,在項目的初期以代碼的穩定性,可讀性,可擴展性爲主要目標,只有當代碼的性能不能知足需求時再進行適當的優化。由於每每對代碼的優化會犧牲以上三個特效,因此在軟件開發過程當中,常常須要平衡這些特性。