Производительность fwrite и размера записи
Я пишу большой двумерный массив размером в двоичный файл (конечный размер ~ 75 МБ).
Я делаю это в Linux-системе. Во-первых, есть ли лучший способ или syscall, кроме fwrite, для записи файла как можно быстрее?
Во-вторых, если я должен использовать fwrite, то должен ли я просто написать весь файл как 1 непрерывную строку?
fwrite( buf, sizeof(float), 6700*6700, fp );
или записать его в виде серии кусков
fwrite( buf, sizeof(float), 8192, fp );
fwrite( *(buf+8192), sizeof(float), 8192, fp );
....
Если я должен записать текст, насколько большой должен быть каждый кусок?
Ответы
Ответ 1
Просто используйте fwrite (не нужно переходить на системные вызовы нижнего уровня) и делайте это как один кусок. В системных вызовах нижнего уровня вы узнаете, как лучше буферировать и разделить эту команду записи. Я никогда не мог победить в работе над такими вещами - большими последовательными записями.
Ответ 2
Я согласен с miked и Jerome по большей части, но... только для современной ОС. Если вы работаете в встроенной флэш файловой системе, есть некоторые основные исключения. В этой среде, если вы подозреваете fwrite(), инвестируйте в быстрый тест, используя write() с большими блоками.
Сегодня я нашел улучшение скорости на 4 раза, переходящее в write(). Это произошло из-за слоя posix во встроенной ОС, который транскрибировал fwrite() s в fputc() s... в этом случае базовый файл флэш файла SYNC просто разбивается. write() была реализована с помощью подпрограмм, гораздо более близких к ОС (Nucleus), в которых запись блоков не была разбита на байты.
просто говоря... если вы сомневаетесь в двух вариантах, вероятно, лучше всего просто попробовать.
Ответ 3
Вероятнее всего, вы получите более высокие показатели, используя nmap(), создав пространство для своего массива (виртуальное адресное пространство) и THEN, чтобы записать в "память", а не на диск.
Пусть система сделает это за вас: она, скорее всего, выделит как можно меньше страниц, что не произойдет с буфером 75 МБ, сбрасываемым fwrite().
В мире ограниченных кэшей CPU, игра с огромными буферами - это не-go (почему malloc() использует nmap() для больших распределений). Присоединив буфер к файлу при настройке nmap() - и перед заполнением буфера вы сохраните много работы в системе.
Ответ 4
Один кусок быстрее. Для этого есть несколько причин:
1) запись на HDD означает также сохранение "обновленной" всех дополнительных сведений в файловой системе (временная метка, размер файла, используемый кластер, блокировки и т.д.), поэтому есть некоторые накладные расходы, связанные с каждым доступом к файлу (особенно доступ для записи).
2) Диск ввода/вывода работает медленно, и поэтому ОС обычно пытается реализовать некоторое кэширование на своей стороне. Это означает, что каждый раз, когда вы используете ввод/вывод файлов, будут выполняться дополнительные проверки, если он кэшируется, если он должен быть кэширован и т.д.
Ответ 5
Вы можете найти источник fwrite в
http://sourceware.org/git/?p=glibc.git;a=blob;f=libio/iofwrite.c;hb=HEAD
Как вы можете видеть, это, в свою очередь, вызывает IO_sputn, который в конечном итоге заканчивается на
http://sourceware.org/git/?p=glibc.git;a=blob;f=libio/fileops.c;hb=HEAD
(в частности, _IO_new_file_xsputn). Как вы можете видеть, это всегда проходит через буфер stdio.
Поэтому я бы посоветовал не использовать stdio; запись с использованием write (2) будет обходить эту дополнительную копию.