Вопрос по file-io, file, c++ – Использует ли C ++ ofstream для записи файлов буфер?

26

Ниже приведены две программы, которые записывают 50 000 000 байтов в файл.

Первая программа, написанная на C, использует буфер, который однажды заполняется до произвольного значения, записывает на диск и затем повторяет этот процесс до тех пор, пока не будут записаны все 50 000 000 байтов. Я заметил, что когда я увеличил размер буфера, программе потребовалось меньше времени для запуска. Например, при BUFFER_SIZE = 1 программе потребовалось ~ 88,0463 секунды, тогда как при BUFFER_SIZE = 1024 программе потребовалось всего ~ 1,7773 секунды. Лучшее время, которое я записал, было, когда BUFFER_SIZE = 131072. Когда BUFFER_SIZE увеличился выше, я заметил, что на самом деле это заняло немного больше времени.

Вторая программа, написанная на C ++, использует ofstream для записи по одному байту за раз. К моему удивлению, запуск программы занял всего ~ 1,87 секунды. Я ожидал, что это займет минуту или около того, как программа C с BUFFER_SIZE = 1. Очевидно, что C ++ ofstream обрабатывает запись файла иначе, чем я думал. По моим данным, он работает примерно так же, как файл C с BUFFER_SIZE = 512. Использует ли он какой-то закулисный буфер?

Вот программа на C:

<code>const int NVALUES = 50000000; //#values written to the file
const char FILENAME[] = "/tmp/myfile";
const int BUFFER_SIZE = 8192; //# bytes to fill in buffer before writing

main()
{
    int fd;  //File descriptor associated with output file
    int i;
    char writeval = '\0';
    char buffer[BUFFER_SIZE];

    //Open file for writing and associate it with the file descriptor
    //Create file if it does not exist; if it does exist truncate its size to 0
    fd = open(FILENAME, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);

    for(i=0;i<NVALUES;i++)
    {
        //Package bytes into BUFFER_SIZE chunks 
                //and write a chunk once it is filled
        buffer[i%BUFFER_SIZE] = writeval;
        if((i%BUFFER_SIZE == BUFFER_SIZE-1 || i == NVALUES-1))
            write(fd, buffer, i%BUFFER_SIZE+1);

    }

    fsync(fd);

    close(fd);
}
</code>

Вот программа на C ++:

<code>int main()
{
    ofstream ofs("/tmp/iofile2");
    int i;

    for(i=0; i<50000000; i++)
        ofs << '\0';

    ofs.flush();
    ofs.close();

    return 0;
}
</code>

Спасибо за ваше время.

Да, это скрыто за кулисами, так какofs.flush(); указывает на то. Anders Lindahl
Я всегда слышал, что 4096 (размер страницы ОС) или 8192 (двойной размер страницы ОС) - лучшее число, к которому можно стремиться. Размеры больше, чем те, которые могут быть быстрее, но увеличение скорости не стоило увеличения памяти. Mooing Duck
Ой! Мне очень нравится, когда «новички» задайте такой вопрос: экспериментальные данные, разумная гипотеза, сэр, приятно иметь вас на борту! Matthieu M.

Ваш Ответ

3   ответа
2

этот, ofstream имеет нутреннийfilebuf указатель, можно прочитать черезrdbuf функция, которая указыает наstreambuf объект, который это:

streambuf objects are usually associated with one specific character sequence, from which they read and write data through an internal memory buffer. The buffer is an array in memory which is expected to be synchronized when needed with the physical content of the associated character sequence.

Я ыделил ажные биты, кажется, что он использует буфер, но я не знаю или не ыяснил, что это за буфер.

Спасибо @BenjaminLindley за это разъяснение. TimeBomb006
@ TimeBomb006: Это не справочная страница C ++. Это & APOS; sa C ++, и если вы ищете точный ответ, он ненадежен.
Спасибо вам за это, я, должно быть, пропустил это, когда просматривал справочную страницу C ++. TimeBomb006
11

все потоковые операции буферизируются, хотя по умолчанию стандартный ввод, вывод и вывод ошибок не являются такими, чтобы взаимодействия с C IO были менее удивительными.

Как уже упоминалось, есть базовый классstreambuf это используется за кулисами. Он снабжен собственным буфером, размер которого является деталью реализации.

Вы можете проверить (экспериментально), сколько этот буфер, используяstreambuf::in_avail, предполагая, что входной файловый поток и выходной файловый поток настроены с одинаковым размером буфера ...

Здесь вы можете сделать еще две операции, которые могут вас заинтересовать:

you can change the streambuf object used by a stream, to switch to a custom version you can change the buffer used by the streambuf object

оба должны быть сделаны сразу после создания потока или послеflushЧтобы некоторые данные не были потеряны ...

Чтобы проиллюстрировать изменение буфера, посмотритеstreambuf::putsetbuf:

#include <fstream>
#include <vector>

int main () {
  std::vector<char> vec(512);

  std::fstream fs;
  fs.rdbuf()->pubsetbuf(&vec.front(), vec.size());

  // operations with file stream here.
  fs << "Hello, World!\n";

  // the stream is automatically closed when the scope ends, so fs.close() is optional
  // the stream is automatically flushed when it is closed, so fs.flush() is optional

  return 0;
}

Теперь вы можете повторить эксперименты, которые вы проделали в C, чтобы найти лучшее место :)

@ Сэм: Я полагаю, вы имеете в видуThe problem is that when printing to the console (instead of, say, being redirected to a file), neither our C nor C++ I/O are buffered by default. (в противном случае, пожалуйста, уточните). Я хотел бы отметить, что мое первое предложение заканчиваетсяthough by default the standard input, output and error output are not so that interactions with the C IO is less surprising что точно так же.
Это не правда, что все потоковые операции буферизируются -connect.microsoft.com/VisualStudio/feedback/details/642876/…
9

ostreams использует потоковый буфер, некоторый подкласс экземпляра шаблона basic_streambuf. Интерфейс basic_streambuf разработан так, что реализация может выполнять буферизацию, если в этом есть преимущество.

Однако это вопрос качества реализации. Реализации не обязаны делать это, но любая компетентная реализация будет.

Вы можете прочитать все об этом в главе 27 стандарта ISO, хотя, возможно, более читаемый источникThe C++ Standard Library: A Tutorial and Reference (поиск Гугл).

Похожие вопросы