軟件工程第2次作業—效能分析

 

作業要求的博客鏈接:https://edu.cnblogs.com/campus/nenu/2016CS/homework/2139

git倉庫地址:https://git.coding.net/isak_even/wfAnalysis.git

第一次作業—詞頻統計v1.0:https://www.cnblogs.com/kongwy/p/9662364.html

 

一、項目概要:

  本次項目實現的是詞頻統計的效能優化,v1.1主要改進功能三,目前測試《戰爭與和平》結果的最優時間爲0.385。

二、效能分析

1.以war_and_peace.txt作爲測試文件,連續三次運行,給出每次消耗時間。

原始代碼沒有使用命令行參數,經過改進後測試截圖如下:

2.猜測瓶頸

 (1)第一個瓶頸應該就是讀文件,將文本處理成字符串。這次處理的是3.14MB的文本文件,讀文件一定是耗時最長的單元,這個地方應該優化一下。估計優化後時間會縮短一半。

/* ----實現讀取指定文件的功能-----*/
void readtxt(string filename)
{
    ifstream file;
    file.open(filename.c_str());//注意一定要轉化爲 char *
    string s;        //每次讀取一行txt文件返回的字符串
    while(getline(file, s))//按行讀取
    {
        str=s+' '+str;//加空格確保分割開行尾和行首的兩個單詞
    }
    transform(str.begin(), str.end(), str.begin(), ::tolower);//將大寫轉化爲小寫
    file.close();    //關閉文件
}

 (2)第二個是分割字符串,並且統計合法單詞的詞頻。理由同上,測試數據過大所以耗時長,優化後時間會縮短。

for (long i=0;i<str.length();i++)
    {
        while(str[i]>='0'&&str[i]<='9'||str[i]>='a'&&str[i]<='z')
        {
            temp=true;
            b+=str[i];
            i++;
        }
        if(temp)
        {
            word=b;
            if(word[0]>'9'||word[0]<'0') //判斷第一個字符是不是數字
            {
                ++word_count[word];
                vec.push_back(word);
            }

            b="";
            word="";
            temp=false;
        }
    }

3.利用profile找出瓶頸並優化

 第一次profile的截圖如下:

 (1)可以看出getline(file,s)和字符串的合併是耗時最長的。分析後決定把讀文件和分割出合法字符串合在一起,讀完一行就進行處理,就可以省略str = s+' '+str。

 (2)調試後發現transform函數也比較耗時,便將處理大小寫轉變爲判斷字符,確定是大寫字母再轉化爲小寫字母。

 (3) 將for (long i = 0; i<str.length(); i++) 轉變爲 long a = str.length();  for (long i = 0; i<a; i++),這樣不需要每次循環都調用length()函數。

優化後第二次profile截圖如下

 

 (1)再次測試後此時耗時最長的是b=b+str[i]。參考博客:http://www.cnblogs.com/chuncn/archive/2009/02/13/1390176.html 我改爲:b.append(1,str[i]);

 (2)++word_count[word]耗時也長。map函數是自動排序的,這樣效率會低一點,所以我換成unordered_map<string, long> word_count;

參考博客:http://www.cnblogs.com/me115/archive/2013/06/05/3117967.html

(3)最後將功能一和二共同改進一下。

4.優化後的profile截圖

5.優化後時間

三、自我評估

個人基本情況見第零次作業 博客地址:https://www.cnblogs.com/kongwy/p/9611339.html

這次作業主要是優化代碼,提高效率,也是解決自己上次遺留的問題。

(1)在初步測試的時候其實不太好用,通過參考其他人的博客,發現沒有使用命令行參數,就是int main(int argc, char* argv[]),更改之後代碼也簡單了不少。

(2)用ptime測試時發現電腦配置對代碼的運行效率影響較大,所以在室友的筆記本和學院的機房都進行了多次測試。

(3)安裝VS,並且啓用性能分析,通過閱讀《構建之法》第二章基本瞭解到抽樣和代碼注入的區別。這次採用的主要還是抽樣。

(4)發現VS要求比較嚴格,代碼不能用頭文件#include<bits/stdc++.h>以及需要將 sscanf改爲sscanf_s。

(5)優化代碼之後大概減少了四十行,速度提高了十倍左右。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章