Почему острингстрим быстрее, чем офстрим - PullRequest
9 голосов
/ 04 марта 2011

Чтобы записать много данных в файл, у меня есть 2 подхода:

  1. Пишите в ofstream по одному напрямую

    ofstream file("c:\\test.txt");
    for (int i = 0; i < 10000; ++i)
    {
        file << data[i];
    }
    
  2. Сначала пишите в istringstream, а затем сразу пишите в ofstream

    ostringstream strstream;
    for (int i = 0; i < 10000; ++i)
    {
        strstream << data[i];
    }
    ofstream file("c:\\test.txt");
    file << strstream.str();
    

Не удивительно, что второй подход быстрее, фактически, он в 4 раза быстрее, чем первый подход на моей машине HP7800.

Но почему? Я знаю, что ofstream использует filebuf внутри, а ostringstream использует stringbuf - в качестве буфера они все должны находиться в памяти, поэтому не должно иметь разницы.

Какая разница под капотом?

Ответы [ 3 ]

16 голосов
/ 04 марта 2011

Вы используете std::endl много вместо '\n'? std::endl делает две вещи: вставляет '\n' в поток, а затем сбрасывает буфер на диск . Я видел, как код говорит о серьезном падении производительности. (После исправления код работал в 5-10 раз быстрее.)
Сброс в строковый буфер будет намного быстрее, чем сброс на диск, так что это объяснит ваши выводы.

Если это не тот случай, вы можете подумать об увеличении размера буфера:

const std::size_t buf_size = 32768;
char my_buffer[buf_size];
ofstream file("c:\\test.txt");
file.rdbuf()->pubsetbuf(my_buffer, buf_size);

for (int i = 0; i < 10000; ++i)
{
    file << data[i];
}
5 голосов
/ 04 марта 2011

Диск медленный.Многие маленькие записи дороже, чем одна большая.

2 голосов
/ 04 марта 2011

Это может быть проблема реализации с конкретной ОС. Также я предполагаю, что буфер ofstream (buflen) меньше 10000, типичное значение 4095. Поэтому попробуйте запустить с i <4096, и время отклика должно быть таким же! </p>

Причина, по которой он быстрее во втором случае:

В первом случае, когда буфер заполнен (buflen = 4095 байт), он записывается на диск. Так что для меня <10000 это вызвало бы его промывку 3 раза. </p>

В то время как во втором случае все данные сначала подготавливаются в ОЗУ и за один раз сбрасываются на жесткий диск. Таким образом, два сброса были сохранены!

...