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#コードでより一般的なライブラリを使用しています。これは、C++コードで独自の関数をロールする必要があるのと比較して、一般的にMS開発者によって適切に記述および最適化されています..

于 2013-02-20T05:50:08.210 に答える
0

'C#コードをコンパイルすると、'コンパイラ'は中間言語コード(MSIL)を生成し、このコードは実行時にdotnetフレームワークのJITコンパイラによってネイティブコードにコンパイルされます。JITでコンパイルされたコードは、コードを実行する環境に合わせて高度に最適化されています。これは、関数ごとに1回だけ発生し、関数がネイティブコードにコンパイルされると、アプリケーションが終了するまで再利用されます。したがって、1つの関数が何度も呼び出される場合、JITで生成および最適化されたコードは、一般的にコンパイルされたC++コードよりもパフォーマンスが優れている可能性があります。

于 2013-02-20T06:05:50.050 に答える