Подтвердить что ты не робот

С++ намного быстрее, чем Bash script запись в текстовый файл

Я хотел протестировать производительность записи в файл в bash script по сравнению с программой на С++.

Вот bash script:

#!/bin/bash

while true; do
        echo "something" >> bash.txt
done

Это добавило около 2-3 КБ к текстовому файлу в секунду.

Вот код С++:

#include <iostream>
#include <fstream>

using namespace std;

int main() {
    ofstream myfile;
    myfile.open("cpp.txt");

    while (true) {
        myfile << "Writing this to a file Writing this to a file \n";
    }

    myfile.close();
}

Это создало текстовый файл размером ~ 6 ГБ менее чем за 10 секунд.

Что делает этот код С++ намного быстрее и/или этот bash script настолько медленнее?

4b9b3361

Ответ 1

Есть несколько причин.

Во-первых, интерпретируемые среды исполнения (например, bash, perl наряду с не-JITed lua и python и т.д.) обычно намного медленнее, чем даже плохо написанные скомпилированные программы (C, C++ и т.д.).

Во-вторых, обратите внимание, как фрагментирован ваш код bash - он просто записывает строку в файл, затем записывает еще одну и так далее. Ваша программа на С++, с другой стороны, выполняет буферизированную запись - даже без ваших прямых усилий. Вы можете увидеть, как будет работать медленнее, если вы замените

myfile << "Writing this to a file Writing this to a file \n";

с

myfile << "Writing this to a file Writing this to a file" << endl;

для получения дополнительной информации о том, как потоки реализованы на С++, и почему \n отличается от endl, см. любую справочную документацию на С++.

В-третьих, как показывают комментарии, ваш bash script выполняет открытие/закрытие целевого файла для каждой строки. Это подразумевает значительную служебную нагрузку - представьте myfile.open и myfile.close, перемещенные внутри вашего тела цикла!

Ответ 2

Как уже отмечалось, это происходит потому, что вы открываете и закрываете файл каждой строкой, которую вы пишете в своем script (и интерпретаторы оболочки интерпретируются при компиляции С++). Вы можете выполнять пакетную запись и писать один раз, например

MSG="something"
logfile="test.txt"
(
for i in {1..10000}; do
        echo $MSG
done
) >> $logfile

Что будет писать сообщение 10k раз, но только один раз открыть журнал.