2013-02-20 115 views
1

最近,我們有一個要求,即有超過100,000個xml文件,並且所有這些文件都需要修改xml中的特定數據。簡單的perl命令可以完成這項工作,但perl並未安裝在文件所在的機器上。因此我寫了一個小小的C#代碼來完成這項工作。爲什麼這個C++代碼與C#版本相比較慢

private static void ModifyXML(string[] args) 
{ 
     Stopwatch sw = new Stopwatch(); 
     sw.Start(); 
     string path = @args[0]; 
     string opath = @args[1]; 
     string token = "value_date=\"20121130\""; 
     string target = "value_date=\"20121019\""; 

     Parallel.ForEach(Directory.EnumerateFiles(path), (file) => 
     { 
      StringBuilder sb = new StringBuilder(File.ReadAllText(file)); 
      sb.Remove(0, 55); 
      sb.Replace(token, target); 
      var filename = file.Split(new char[] { '\\' }).Last();     
      File.WriteAllText(string.Format("{0}\\{1}", opath, filename), sb.ToString()); 
     }); 
     TimeSpan ts = sw.Elapsed; 
     Console.WriteLine("Took {0} secs", ts.TotalSeconds); 
} 

我決定實施C++版本。事實證明,C++版本並沒有比C#版本快得多。在兩個版本中都運行了sevaral times。事實上,在一些運行期間,它和C#版本一樣快。

對於C#我使用.NET 4.0和C++它是VC10。

void FileHandling(std::string src, std::string dest) 
{ 
    namespace fs = boost::filesystem; 
    auto start = boost::chrono::system_clock::now(); 
    string token = "value_date=\"20121130\""; 
    string target = "value_date=\"20121019\""; 
    fs::directory_iterator end_iter; 
    fs::directory_iterator dir_itr(src); 
    vector<fs::path> files; 
    files.insert(files.end(), dir_itr, end_iter); 
    string dest_path = dest + "\\"; 
    parallel_for_each(files.begin(), files.end(), [=](const fs::path& filepath) 
    { 
     ifstream inpfile (filepath.generic_string()); 
     string line; 
     line.insert(line.end(), istreambuf_iterator<char>(inpfile), istreambuf_iterator<char>()); 
     line.erase(0, 55); 
     auto index = line.find(token, 0); 
     if (index != string::npos) 
     { 
      line.replace(index, token.size(), target); 
     } 
     ofstream outfile(dest_path + filepath.filename().generic_string()); 
     outfile << line; 
    }); 

    boost::chrono::duration<double> finish = boost::chrono::system_clock::now() - start; 
    std::cout << "Took " << finish.count() << " secs\n"; 
} 
+5

爲什麼你會期望它們有所不同? – 2013-02-20 05:43:02

+0

你是如何編譯C++代碼的? – jogojapan 2013-02-20 05:43:19

+0

@jogojapan,發佈版本。 – Jagannath 2013-02-20 05:46:33

回答

3

儘管一些民族的感知,C#不慢都只要你不使用某些緩慢的功能,如反射 - 事實上,人們結束了編碼速度更快,用更少的不明顯的錯誤等等有更多的時間去花費優化性能和邏輯,而不是bug修復,這意味着它變得更快......

除了您在C#代碼中使用更常見的庫,它們通常是通過編寫和優化MS開發人員 - 相比,必須在C++代碼中推出自己的功能..

+2

C#確實有一些開銷不會出現在本地編譯的C++或其他語言中,因爲一般情況下都有JIT發生將IL轉換爲本地代碼,以及各種事情,可以放慢你像拳擊等。生產力的論點在很大程度上是不相關的......人們在他們最熟悉的方面編碼最好,所以用C#編寫的C++程序員的生產力比編寫C++的C++程序員的生產力低。這都是相對的。 C#中的好代碼可以擊敗C++中的錯誤代碼,反之亦然。 – Corey 2013-02-20 05:56:33

+1

這太籠統了,對於這個問題並不是真正的答案。生產力與被問到的問題無關,這就是爲什麼一段代碼運行得比另一段快。 – 2013-02-20 06:18:11

7

好像你有很多文件工作太少完成它們,所以主要的瓶頸是磁盤IO在這裏。如果您對每個文件都有一些複雜且耗費CPU的任務,那麼您可以更快地使用C++版本,但對於小任務而言,這是無關緊要的,因爲IO是問題

0

當編譯C#代碼時,代碼(MSIL),此代碼將在運行時由dotnet框架的JIT編譯器編譯爲本地代碼。 JIT編譯代碼針對執行代碼的環境進行了高度優化。每個函數只發生一次,一旦函數被編譯爲本地代碼,它將被重用直到應用程序終止。所以,如果你有一個函數被重複調用,JIT生成和優化的代碼可能會勝過一般編譯的C++代碼

相關問題