2011-11-14 53 views
0

我在我的項目中有一個方法,當它放到它自己的程序中時只需要幾秒鐘的時間運行,當它在它所屬的項目中運行需要5分鐘。我不知道爲什麼。我已經嘗試過分析,不再需要改變這個和那個。我很難過。奇怪的緩慢的方法

它填充要由另一個類使用的整數矢量,但該類當前未被實例化。我儘可能多地檢查了一下,看起來確實沒有別的事情發生,但是這個方法在一個項目中奇蹟般地花費更長的時間,而不是另一個項目。

該方法在啓動時運行,大約需要5分鐘,如果自己運行則需要大約3秒。什麼可能導致這個?奇怪的項目設置?多線程的東西,我不知道? (據我所知,除非它自動完成,否則我的項目中沒有任何項目)。

有一個鏈接到項目here。如果有人能爲我解決這個問題,我會很感激,只要我能夠爲此開始一個獎勵。

該方法被稱爲PopulatePathVectors並在Level.cpp中運行。註釋掉對方法的調用(在關卡構造函數中)意味着程序在數秒內啓動。唯一使用它生成的列表的其他類是Agent,但目前沒有被實例化。

編輯 - 根據要求,這裏是代碼。雖然請記住,我的問題不是'爲什麼代碼很慢?'但'爲什麼它在一個地方速度快,我的項目速度慢?'

//parses the text path vector into the engine 
void Level::PopulatePathVectors(string pathTable) 
{ 
    // Read the file line by line. 
    ifstream myFile(pathTable); 

     for (unsigned int i = 0; i < nodes.size(); i++) 
     { 
      pathLookupVectors.push_back(vector<vector<int>>()); 

      for (unsigned int j = 0; j < nodes.size(); j++) 
      { 
       string line; 

       if (getline(myFile, line)) //enter if a line is read successfully 
       { 
        stringstream ss(line); 
        istream_iterator<int> begin(ss), end; 
        pathLookupVectors[i].push_back(vector<int>(begin, end)); 
       } 
      } 
     } 
} 

編輯 - 我知道代碼不是最好的,但這不是重點。它自己運行很快 - 大約3秒鐘,這對我來說很好。我想要解決的問題是爲什麼在項目內部需要更長的時間。

編輯 - 我評論了除主遊戲循環以外的所有遊戲代碼。我將該方法放入代碼的初始化部分,該代碼在啓動時運行一次。除了一些設置窗口的方法外,它現在幾乎與只使用該方法的程序相同,只是它仍然需要大約5分鐘的時間才能運行。現在我知道它與pathLookupVectors上的依賴關係無關。另外,我知道這不是計算機開始寫入硬盤驅動器的記憶事物,因爲在慢速程序運行該方法時,我可以打開另一個VS實例並同時運行單個方法程序,該程序完成後秒。我意識到這個問題可能是一些基本的設置,但我沒有經歷過如此的道歉,如果這確實令人失望,最終成爲原因。我仍然不知道爲什麼它需要更長的時間。

如果在調試模式下不需要這麼長時間,這將會很棒,因爲這意味着每次進行更改時都需要等待5分鐘。這裏必須有一個原因,這是如此緩慢。這些都在削減項目的其他包括頭:

#include <d3d10.h> 
#include <d3dx10.h> 
#include "direct3D.h" 
#include "game.h" 
#include "Mesh.h" 
#include "Camera.h" 
#include "Level.h" 

#include <vector> 

using namespace std; 

編輯 - this是唯一的代碼,其中的問題仍然發生一點點小得多自包含的項目。

this也是一個非常小的項目,其代碼運行速度非常快。

+0

您是否比較過在項目中生成和未生成的程序集? – Rup

+0

可能是項目設置或內存豬(是否比你擁有的內存佔用更多​​的內存?) – CharlesB

+10

請告訴我們相關的代碼在這裏。你真的不希望人們從互聯網上下載未知文件,然後瀏覽你的整個項目的代碼,只是爲了能夠幫助你 – jalf

回答

6

我在MSVC10(您使用的編譯器相同)中運行此代碼,並將結果與​​您提供的項目重複。但是,由於使用快速版本,我無法使用此編譯器進行配置文件。

我在MSVC9編譯器中運行了這段代碼,運行速度提高了5倍!我也異形它,並得到了這些結果:

Initialize (97.43%) 
    std::vector::_Assign (29.82%) 
     std::vector::erase (12.86%) 
      std::vector::_Make_iter (3.71%) 
      std::_Vector_const_iterator (3.14%) 
     std::_Iterator_base (3.71%) 
     std::~_Ranit (3.64%) 
    std::getline (27.74%) 
     std::basic_string::append (12.16%) 
      std::basic_string::_Grow (3.66%) 
      std::basic_string::_Eos (3.43%) 
     std::basic_streambuf::snextc (5.61%) 
    std::operator<<(std::string) (13.04%) 
     std::basic_streambuf::sputc(5.84%) 
    std::vector::push_back (11.84%) 
     std::_Uninit_move::?? (3.32%) 
    std::basic_istream::operator>>(int) (7.77%) 
     std::num_get::get (4.6%) 
      std::num_get::do_get (4.55%) 

「快」的版本得到以下結果:(縮放,以匹配其他時間):

Initialize (97.42%) 
    std::_Uninit_copy (31.72%) 
     std::_Construct (18.58%) 
     std::_Vector_const_iterator::operator++ (6.34%) 
     std::_Vector_const_iterator::operator!= (3.62%) 
    std::getline (25.37%) 
     std::getline (13.14%) 
     std::basic_ios::widen (12.23%) 
    std::_Construct (18.58%) 
     std::vector::vector (14.05%) 
    std::_Destroy (14.95%) 
     std::vector::~vector (11.33%) 
    std::vector::_Tidy (23.46%) 
     std::_Destroy (19.89%) 
      std::vector::~vector (12.23%) 
     [ntdll.dll] (3.62%) 

研究這些結果,並考慮到邁克爾價格的意見後,很多時候,我想到確保輸入文件的大小相同。當我意識到這一點時,我意識到「快」版本的配置文件,不是顯示std::operator<<(std::string)std::vector::push_back,這似乎是可疑的。我檢查了MethodTest項目,發現它沒有WepTestLevelPathTable.txt,導致getline失敗,並且除了分配一堆空向量外,整個函數幾乎什麼也不做。當我將WepTestLevelPathTable.txt複製到MethodTest項目時,速度與「慢速」版本完全相同。案件解決。使用較小的文件進行調試構建。

+1

出色的工作!你應得的賞金! –

+1

做得好+1 - 我仍然希望人們在發佈問題之前調試他們的代碼。這是一個簡單的錯誤找到作爲代碼的作者... – Walter

+0

啊,好吧非常感謝你。賞金是你的! – SirYakalot

0

它包含一個帶循環的循環,每個內循環讀取超過30MB數據文件的每一行。當然這會很慢。我會說這是設計緩慢。

+0

相同的代碼在一個地方運行得非常快,在另一個地方運行得很慢。 – SirYakalot

+0

和相同的代碼是在C#中快速# – SirYakalot

+0

@SirYakalot - 好的,如果它是相同的代碼,它不是在C#中 - 根據定義,C++代碼不能與C#代碼相同。 –

2

我這裏還有一些方法,我相信會減慢啓動過程:

  1. 級別:: GenerateGridNodes():

    void Level::GenerateGridNodes() 
    { 
        int gridHeight = gridSize; 
        int gridWidth = gridSize; 
    
        // ADD THIS STATEMENT: 
        nodes.reserve(gridHeight*gridWidth); 
    
        for (int h = 2; h <= gridHeight; h++) 
        { 
         for (int w = 2; w <= gridWidth; w++) 
         { 
          nodes.push_back(Node(D3DXVECTOR3((float)w, (float)h, 0))); 
         } 
        } 
    }//end GenerateGridNodes() 
    
  2. 級別:: CullInvalidNodes() :對於std :: vectors,使用remove-erase idiom可以更快地擦除元素。你還需要重新考慮這個函數應該如何工作,因爲它似乎有大量的刪除和刪除節點。代碼中的代碼是否有意義,而不是刪除,您可以簡單地將刪除後立即將您的push_back()值分配給您正在擦除的值?因此,而不是v.erase(itr)其次是v.push_back(new_element),你可以簡單地做*itr = new_element;免責聲明:我沒有看到實際的功能。老實說,我沒有時間。我只是把你指向一個可能性。

  3. 在級別:: LinkNodes():

    void Level::LinkNodes() 
    { 
        //generates a vector for every node 
        // ADD THIS BEFORE THE FOR LOOP 
        nodeAdjacencyVectors.reserve(nodes.size()); 
        for (unsigned int i = 0; ....) 
        //... Rest of the code 
    }//end LinkNodes() 
    

總之,你還是有餘地很大的改進。我相信主要的職業是Level級別的職能。你應該再看看它,並可能重新思考應該如何實現每個功能。特別是在Level類的構造函數中調用的那些。

+0

我會做這些事情,是的,我有很多事情要改進。然而這並不能解釋爲什麼它會在我的項目中慢慢運行,但在其他地方速度很快。 – SirYakalot

+0

@SirYakalot:這很可能是因爲Visual Studio在從VS運行應用程序時會附加它的「調試器」。您應該:(a)自行運行應用程序(b)以「發佈」模式編譯應用程序以查看其實際性能。 這是因爲在'調試'模式下,代碼會得到額外的驗證檢查,並且不會進行優化以幫助您在發現錯誤時調試應用程序。在'釋放'模式下,這些檢查和額外的代碼被取消。除此之外,您的代碼將得到優化,以儘可能快的速度運行。 –

+0

感謝您的信息。這是否解釋了爲什麼它會在另一個項目中跑得更快?或者這是否適用於兩者? – SirYakalot