最近的專案用到了QT 5.5,專案在執行過程中出現了一段時間CPU佔用率持續25%,並頻繁斷網的情況,遂決定對專案效能進行優化。
優化工具也是VS2010自帶的效能分析工具,具體的使用方法參見:http://www.cnblogs.com/smark/archive/2011/10/12/2208039.html
其中可以選擇“just my code”過濾出自己編寫的程式碼。
1.優化字串格式化方法。
專案中有將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左右,效能提升了幾十倍。
2.優化介面重新整理
在介面功能中有一處表格顯示的功能,顯示接收到的資料,在原始的程式碼中,當接收到一條資料,填充到表格上時,就呼叫一次表格scrollTo方法,當1s接收到2,3百條資料時,就會呼叫2,3此scrollTo方法,直接導致了介面頻繁更新。
優化的方法是,考慮到人眼的觀察能力,將重新整理頻率即scrollTo的函式呼叫固定為1s一次,減少了2,3百此的介面重繪,降低了CUP負載。
3.優化更新時戳功能
專案中有一處更新時戳的功能,記錄某些狀態是否已經超時,原始程式碼中通過QDateTime記錄時戳,當資料到來時會呼叫QDateTime::currentDateTime更新時戳,當有大量資料到來時會頻繁更新時戳,通過效能分析發現此處呼叫總CPU使用率的7%。考慮該時戳只需要統計時間間隔,遂優化後改用time.h中的clock函式打時戳,該函式返回至程式啟動的毫秒數。再次進行效能分析顯示此處呼叫降到CPU使用率的0.23%,效能提升明顯。
4.優化資料庫操作
專案中有一處資料庫記錄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的時間。
5.其他
其他優化還包括資料結構的調整,包括將2,3百條資料的陣列改成map結構儲存等。
總結
當然對軟體的優化還是用遵循相應的原則,比如不要過早優化,在專案的初期以程式碼的穩定性,可讀性,可擴充套件性為主要目標,只有當程式碼的效能不能滿足需求時再進行適當的優化。因為往往對程式碼的優化會犧牲以上三個特效,所以在軟體開發過程中,經常需要平衡這些特性。