C ++ против Python против производительности Ruby в рекурсивном списке всех каталогов - PullRequest
0 голосов
/ 02 ноября 2018

Я только что написал код на C ++ для рекурсивного перечисления всех каталогов в папке. Я использую Boost Filesystem и я статически собираю следующий код:

#include <iostream>
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
using namespace std;

int main(int argc, char* argv[]) {
    const path current_file_path(current_path());

    try {
        std::vector<path> directories_vector;
        for (auto&& x : recursive_directory_iterator(current_file_path))
            if (is_directory(x.path()))
                directories_vector.push_back(x.path());
        /* GETTING UP TO HERE TAKES MORE TIME THAN PYTHON OR RUBY*/

        for (auto&& x : directories_vector) {
            cout << x << '\n';
        }
    }
    catch (const filesystem_error& ex) {
        cout << ex.what() << '\n';
    }

    cin.get();
    return 0;
}

Я хотел посмотреть, как быстро этот код будет работать с Python и Ruby. Я знаю, что связанные с вводом / выводом вещи не годятся для оценки производительности кода, но когда я запускаю исполняемый файл C ++, для 15+ рекурсивных папок требуется почти 3 секунды, в то время как следующие коды Python и Ruby запускаются практически мгновенно:

Ruby:

Dir.glob("**/*/")

Python:

[x[0] for x in os.walk(directory)]

Все коды работают на SSD. Я использую Visual Studio 2017, Python 3.5.2 и Ruby 2.4 для Windows. Код C ++ использует режим Release / x64, а для параметра Оптимизация установлено значение Максимальная оптимизация (скорость фаворита) (/O2).

Почему код C ++ медленнее, когда сталкивается с большим количеством рекурсивных папок?

1 Ответ

0 голосов
/ 02 ноября 2018

Запустив и версию C ++, и версию Ruby с strace, мы можем получить некоторые подсказки, почему версия C ++ медленнее.

Использование исходного кода Linux для тестирования (65000 файлов):

strace -o '|wc' cpp_recursion
  86417  518501 9463879

strace -o '|wc' ruby -e 'Dir.glob("**/*")' 
  30563  180115 1827588

Мы видим, что версия C ++ выполняет почти в 3 раза больше операций, чем Ruby.

При более внимательном рассмотрении вывода strace вы обнаружите, что обе программы используют getdents для извлечения записей каталога, но версия C ++ запускает lstat для каждого отдельного файла, а версия Ruby - нет.

Я могу только заключить, что версия C ++ не реализована так эффективно (или, возможно, служит другой цели), как версия Ruby. Разница в скорости - это не проблема языка, а проблема реализации.

N.B. Версия C ++ с оптимизацией -O выполняется за 0,347 с, а версия Ruby - за 0,304 с. По крайней мере, в Linux lstat, похоже, не слишком много накладных расходов. Возможно, в Windows ситуация иная.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...