2013-02-20 120 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++代码

相关问题