最近在做三維掃描相關項目。利用Sick的三維掃描儀掃描隧道輪廓,並保存成文件。
項目中需要做點雲顯示和切片。在讀取文件時發現性能不高,代碼如下:
QFile file("20170930092902.txt"); if (!file.open(QFile::ReadOnly | QIODevice::Text)) return; QTextStream in(&file); int cnt = 0; while (!in.atEnd()) { QString line = in.readLine(); QStringList list = line.split(" "); point[cnt][0] = list.at(0).toFloat(); point[cnt][1] = list.at(1).toFloat(); point[cnt][2] = list.at(2).toFloat(); cnt++; }
該文本文件總共295723行,8.3M。執行完本段代碼用時2.43523 ss。
加上顯示和切片等耗時,感覺這代碼性能好低,於是准備開始優化。
方法一:將readLine改成readAll方法。()
QFile file("20170930092902.txt"); if (!file.open(QFile::ReadOnly | QIODevice::Text)) return; QTextStream in(&file); QString ramData = in.readAll(); QStringList list = ramData.split("\n"); QStringList list1; int cnt = 0; for(int i=0; i<list.count()-1; i++) { list1 = list.at(i).split(" "); point[cnt][0] = list1.at(0).toFloat(); point[cnt][1] = list1.at(1).toFloat(); point[cnt][2] = list1.at(2).toFloat(); cnt++; }
優化完以后,本段代碼執行時間為2.20287 s。
有改進,但優化不大。后來單獨測試了readAll()和readLine的方法。讀取整個文件readAll()耗時0.217646 s;readLine()耗時0.482322 s。確實優化力度不大。
而且整個性能的瓶頸應該不在讀取文件,而在於字符串分割和字符串轉Float。於是開始想着使用C庫函數strtok和atof。於是修改代碼如下:
QFile file("20170930092902.txt"); if (!file.open(QFile::ReadOnly | QIODevice::Text)) return; uchar* fpr = file.map(0, file.size()); int cnt = 0; int subcnt = 0; char *substr; char *s = strdup((char*)fpr); while(substr= strsep(&s, "\n")) { char *lineSubStr; subcnt = 0; while(subcnt < 3) { lineSubStr = strsep(&substr, " "); point[cnt][subcnt] = atof(lineSubStr); subcnt++; } cnt++; }
測試用時0.36724 s(其中map函數用時0.000997 s)。優化成功。(代碼中使用strsep而非strtok函數,是因為strtok不支持嵌套使用。有時間的話會在下篇隨筆中詳細解釋)