2013-02-20 4 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#. В run обе версии sevaral times.In факт, это так же быстро, как и версия 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

Почему вы ожидаете, что они будут отличаться? –

+0

Как вы скомпилировали код на C++? – jogojapan

+0

@jogojapan, Release build. – Jagannath

ответ

3

, несмотря на некоторое восприятие народов, C# не замедлит вообще до тех пор, пока вы не используете определенные медленные функции, такие как отражение - на самом деле, люди в конечном итоге кодирования быстрее и с меньшим количеством непонятных ошибок, так имеют больше времени, чтобы провести оптимизацию производительности и логики, а не исправление ошибок, а это значит, что она заканчивается быстрее ...

кроме того, что вы используете более распространенные библиотеки в коде C#, которые обычно хорошо написаны и оптимизированы MS devs - по сравнению с необходимостью сворачивать ваши собственные функции в код C++.

+2

У C# есть некоторые накладные расходы, которые не присутствуют на C++ или других языках, которые изначально скомпилированы, поскольку в целом есть такие вещи, как JIT происходит преобразование IL в собственный код и различные вещи, которые могут замедлить вас, как бокс и так далее. Аргумент производительности в значительной степени не имеет значения ... люди лучше всего кодируют то, что им известно, поэтому программирование на C++ на C# менее продуктивно, чем программирование на C++ на C++. Это все относительно. Хороший код в C# может бить плохой код на C++ и наоборот. – Corey

+1

Это слишком общий и не совсем правильный ответ на вопрос. Производительность не имеет ничего общего с вопросом, который был задан, а именно, почему один фрагмент кода работает быстрее, чем другой. –

7

Похоже, что у вас много файлов со слишком маленькой работой сделанные на них, поэтому основным узким местом является диск IO здесь. Если у вас была какая-то сложная и потребляющая процессор задача для каждого файла, вы могли бы иметь C++-версию быстрее, но при небольших задачах это не имеет значения, так как проблема IO является проблемой

0

Когда вы компилируете код C#, компилятор генерирует промежуточный язык кода (MSIL), этот код затем компилируется во время выполнения JIT-компилятором структуры dotnet для собственного кода. Скомпилированный код JIT высоко оптимизирован для среды, в которой выполняется код. Это происходит только один раз для каждой функции, и как только функция скомпилирована в собственный код, она будет использоваться повторно до тех пор, пока приложение не будет завершено. Поэтому, если у вас есть одна функция, называемая снова и снова, JIT-генерация и оптимизированный код могут превосходить обычно скомпилированный код на C++

 Смежные вопросы

  • Нет связанных вопросов^_^