2014-01-04 4 views
4

По какой-то причине я решил сделать очень простое приложение, которое отображает все цифры от 1 до 1 000 000. Я заметил, что для отображения результатов требуется больше времени, чем для их хранения. Я предположил, что для сохранения всех значений потребуется больше времени, чем для их отображения. Я также помню, что читал, если правильно помню, что нет никакой разницы между пользовательским вводом и чтением из текстового файла в консольном приложении, поэтому я предположил, что отображение и хранение одинаковы. Может кто-нибудь объяснить, почему это? Согласно книге, которую я читаю, поток очень похож на cout, поэтому я не понимаю, почему это занимает больше времени.Из потока быстрее, чем cout? || Хранение быстрее, чем визуальный вывод

Почему это медленнее для отображения результатов с использованием cout, чем для хранения результатов в текстовом файле с использованием ofstream?

COUT = 169.168 секунд

ofstream = 3.473 секунды

метод ofstream

#include <iostream> 
#include <fstream> 
#include <string> 
#include <sstream> 

namespace patch //used to patch some C++11 functions not included in mingw 4.7 // to_string 
{ 
    template < typename T > std::string to_string(const T& n) 
    { 
     std::ostringstream stm ; 
     stm << n ; 
     return stm.str() ; 
    } 
} 
using namespace patch; 
using namespace std; 

int main() 
{ 
    int minimumRange = 1; //sets minimum number in range 
    int maximumRange = 1000000; // sets maximum number in range 
    string strRanges = to_string(minimumRange) + "-" + to_string(maximumRange); //appends string names 
    ofstream myRange; 
    myRange.open(strRanges + ".txt"); 

    for (int i = minimumRange; i<=maximumRange; ++i) 
    { 
     myRange << to_string(i) << "\n"; 
    } 
    myRange.close(); 
    return 0; 
} 

метод соиЬ

#include <iostream> 
using namespace std; 

int main() 
{ 
    int minimumRange = 1; 
    int maximumRange = 1000000; 
    for (int i = minimumRange; i<=maximumRange; ++i) 
    { 
     cout << i << "\n"; //using "/n" instead of endl; for speed purposes 
    } 
    return 0; 
} 
+4

Сама консольная/терминальная программа работает медленно. –

+0

Возможно, система кэширует файл для вас и записывает данные несинхронно на диск? Это будет простой доступ к памяти для вашей версии файла. Запись на консоль связана скоростью консоли (что может быть довольно медленным) – user1781290

+0

D: ... почему вы используете '' stringstream'' для печати ints. T_T мой мозг болит прямо сейчас. – quasiverse

ответ

4

Во многих системах cout является всего лишь экземпляром ostream, отображающим файл CON.

Дело в том, что ostream ничего не пишет.

Его цель состоит в том, чтобы преобразовать любой поддерживаемый тип (maninly: const char*, std::string, int, long ... double ...) в «последовательность символов», который будет помещен в буфер (см std::streambuf).

В этом смысле сохранение или набрав делает то же самое.

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

Когда ОС передает основную массу данных в файл диска, в нем используется драйвер, который может внутренне использовать кеширование, которое ведет переговоры с внешним устройством, используя протокол связи (в основном SATA, SCSI, NFS ...), который ведет к контроллер (микрокомпьютер на диске) также имеет свое кэширование, которое впоследствии управляет магнитным хранилищем.

Ваша программа говорит «пишут», ОС говорит «написано», но данные все еще разрабатываются контроллерами устройств вне операционной системы. «Медленная» часть происходит с вашей точки зрения.

Когда вы должны писать на консоль, большинство из этого «кеширования» не могут быть выполнены: как только вы ждете ввода, cout сбрасывается (вы хотите прочитать то, что вы написали, если это вопрос, который вы должны ответ).

По этой причине драйвер консоли должен дождаться, пока консольная программа завершит свою запись, прежде чем продолжить.Но это письмо на самом деле является «живописью»: символы должны быть преобразованы в пиксели с помощью шрифтов, а рисование должно быть синхронизировано с сканированием дисплея (иначе изображение будет «нарушено»).

Этот процесс медленнее (чем длиннее), чем «запись на диск», что на самом деле означает «переместить большую часть памяти из процесса в порт ввода-вывода» (и где аппаратное обеспечение действительно может сделать это путем замены два регистра указателя)

Кроме того, консольная программа оптимизирована для просмотра данных (и не имеет смысла делать это быстрее, чем глаза), в то время как драйвер диска оптимизирован для передачи данных. Это нормально для того, чтобы быть быстрее.

+0

Это действительно имеет смысл для меня, и мне уже 3 часа. Я не думал о том, что консоль практически нарисовала результаты, или тот факт, что он оптимизирован для просмотра данных, не показывает 1-1 миллион на скорости, которую пользователь не может понять. Возможно ли создать оптимизированную консоль или графический интерфейс, способный отображать эти результаты более своевременно? «Я просто говорю гипотетически, если только что-то вроде QT или wxWidgets не выполняется быстрее, хотя я предполагаю, что полностью раздутый G Пользовательский интерфейс будет медленнее. – Crysis

+0

Ну, если я знаю, что принимающее устройство работает медленно, и единственное, что есть последнее отправленное сообщение, и я могу как-то предсказать, когда произойдет «последние данные», я могу избежать печати вообще, что никогда не будет видно ... Это может выглядеть странно, но ... Полностью раздутый gui может быть в курсе этого проще, чем простой консольный драйвер (который должен работать даже в ситуации восстановления ... поэтому я не должен быть слишком сложным). В зависимости от того, как оптимизирован графический интерфейс, может случиться, что он будет еще быстрее. ... Но это слишком специфично для реализации, и больше не может обсуждаться в общем виде. –