2016-06-17 1 views
4

У меня есть файл, который очень большой (> 500 ГБ), который я хочу добавить с относительно небольшим заголовком (< 20KB). Выполнение таких команд, как:Подготовка к очень большому файлу в фиксированное время или очень быстро

cat header bigfile > tmp 
mv tmp bigfile 

или аналогичные команды (например, с sed) очень медленные.

Что такое быстрый способ записи заголовка в начало существующего большого файла? Я ищу решение, которое может работать под CentOS 7.2. Это нормально устанавливать пакеты из CentOS install или обновлять репо, EPEL или RPMForge.

Было бы здорово, если бы существовал какой-либо метод, который не предполагает переноса или копирования большого количества данных в файле bigfile. То есть я надеюсь на решение, которое может работать в фиксированное время для заданного файла заголовка независимо от размера файла bigfile. Если это слишком много, чтобы просить, я просто прошу о самом быстром методе.

Компиляция вспомогательного инструмента (как на C/C++) или с использованием языка сценариев вполне приемлема.

+0

Стандартные файловые системы обрабатывают файлы как связанные списки (блоков) байтов, что означает, что кроме добавления к файлу, для редактирования требуется переписывание всего объекта. – chepner

+0

Возможно, вы сможете сделать это быстрее на C++, где вы можете настроить размеры буфера. Тем не менее, вы не можете обойтись без копирования. – molbdnilo

+0

http://stackoverflow.com/questions/2503254/unix-prepending-a-file-without-a-dummy-file – xxfelixxx

ответ

6

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

Если вам нужно сделать это только один раз, тогда ваш лучший вариант - просто принять, что была допущена ошибка, и принять последствия ретро-исправления. Пока вы делаете диск назначения отличным от исходного диска, вы сможете исправить файл размером 500 ГБ в течение примерно двух часов. Таким образом, после недели периодических процессов, запущенных после нескольких часов, вы могли бы обновить, возможно, тридцать или сорок файлов.

Если это стандартное требование для всех таких файлов, и вы считаете, что можете применить изменения только после завершения файла - возможно, какая-то сводная информация - тогда вы должны зарезервировать место в начале каждого файла и оставить его пустым. Тогда это просто вопрос поиска в области заголовка и перезапись его реальными данными после его доставки.

Как было объяснено, стандартным файловым системам требуется скопировать весь файл, чтобы добавить что-то в начале

Если файл 500GB на стандартный жесткий диск, который позволит данных для чтения около 100Мб в секунду, а затем читает весь файл займет 5120 секунд, или примерно 1 час 30 минут

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

5

Если вы не были привязаны к CentOS 7.2, ваша проблема может быть решена (с некоторыми оговорками) по fallocate, что обеспечивает необходимую функциональность для файловой системы ext4, начиная с Linux 4.2 и для файловой системы XFS с Linux 4.1:

INT fallocate (INTFD, INTрежим, off_tсмещения, off_tLen);

Это неподдерживаемый системный вызов для Linux. Для портативного POSIX.1-указанного метода обеспечения того, что пространство выделено для файла , см. posix_fallocate(3).

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

Параметр определяет операцию, которая должна выполняться в указанном диапазоне . Подробная информация о поддерживаемых операциях приведена в подразделах .

...

Увеличение файлового пространства

Указания FALLOC_FL_INSERT_RANGE флага (доступен с Linux 4.1) в режим увеличивает файловое пространство, вставив отверстие в размер файла без перезаписи существующих данных. Отверстие начнется по номеру offset и продолжится для len байт. При вставке отверстия в файл содержимое файла, начинающегося с , смещение будет сдвинуто на вверх (т. Е. На более высокое смещение файла) на len байт. Вставка отверстия внутри файла увеличивает размер файла на len байт.

...

FALLOC_FL_INSERT_RANGE требуется поддержка файловой системы. Файловые системы, которые поддерживают эту операцию, включают XFS (начиная с Linux 4.1) и ext4 (с Linux 4.2).


fallocate позволяет предваряя данные в файл только кратного размера блока файловой системы. Таким образом, он решит вашу проблему, только если вам будет удобно заполнять лишнее пространство пробелами, комментариями и т. Д.


Без поддержки fallocate() + FALLOC_FL_INSERT_RANGE лучшее, что вы можете сделать, это

  1. Увеличение файла (так что он имеет свой окончательный размер);
  2. mmap() файл;
  3. memmove() данные;
  4. Заполните данные заголовка в начале.
+0

Независимо от того, как вы читаете и записываете файл, его все еще нужно полностью прочитать в памяти и записать; не имеет значения, используете ли вы «memcopy» и «memmove» или «readline» и «print». На самом деле этот способ будет намного медленнее, потому что вы будете читать и записывать на один и тот же диск, тогда как 'print' может быть направлен на другое аппаратное устройство. Даже использование 'fallocate' с' FALLOC_FL_INSERT_RANGE' займет пару часов, чтобы выделить несколько сотен байт в начале файла 500 ГБ, потому что данные все равно должны быть перемещены каким-то образом. – Borodin

+1

@Borodin Файловые системы, такие как ext4, используют древовидные структуры с указателями на выделение файлов (это, конечно, большое упрощение). Можно вставлять блоки спереди, не перемещая все последующие блоки. – Kaz

+0

Пожалуйста, объясните, почему вы предлагаете 'mmap' и' memmove', и почему вы думаете, что это лучшее решение, чем 'readline' и' print' в Perl – Borodin