1

最近,我们有一个需求,其中有超过 100,000 个 xml 文件,并且所有这些文件都需要修改 xml 中的特定数据。简单的 perl 命令可以完成这项工作,但 perl 没有安装在文件所在的机器上。因此,我编写了一个小的 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# 版本。在两个版本中运行了几次。事实上,在某些运行期间它与 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";
}
4

3 回答 3

7

似乎您有很多文件完成的工作太少,所以这里的主要瓶颈是磁盘 IO。如果您对每个文件都有一些复杂且消耗 CPU 的任务,您可以更快地获得 C++ 版本,但在小任务上它是无关紧要的,因为 IO 是问题

于 2013-02-20T05:51:23.870 回答
3

尽管有些人认为,只要您不使用某些慢速功能(例如反射),c# 一点也不慢 - 事实上,人们最终编码速度更快,并且有更少的模糊错误,因此有更多时间花在优化上性能和逻辑,而不是错误修复,这意味着它最终会更快......

除了您在 C# 代码中使用更常见的库之外,这些库通常由 MS 开发人员编写和优化 - 与必须在 C++ 代码中滚动您自己的函数相比。

于 2013-02-20T05:50:08.210 回答
0

当您“编译”C# 代码时,“编译器”会生成中间语言代码 (MSIL),然后此代码在运行时由 dotnet 框架的 JIT 编译器编译为本机代码。JIT 编译的代码针对您执行代码的环境进行了高度优化。每个函数只发生一次,一旦函数被编译为本机代码,它将被重用,直到应用程序终止。因此,如果您一遍又一遍地调用一个函数,JIT 生成和优化的代码可能会胜过一般编译的 C++ 代码

于 2013-02-20T06:05:50.050 回答