почему этот код C ++ медленнее по сравнению с вариантом C #

Недавно у нас появилось требование, когда существует более 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";
}

1

Решение

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

7

Другие решения

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

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

3

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

0
По вопросам рекламы [email protected]