Быстрая конкатенация нескольких файлов в Linux

Я использую многопроцессорную обработку Python для создания временного выходного файла для каждого процесса. Их размер может быть несколько ГБ, и я делаю несколько десятков таких. Эти временные файлы должны быть объединены для формирования желаемого результата, и этот шаг оказывается узким местом (и убийцей параллелизма). Существует ли инструмент Linux, который будет создавать объединенный файл, изменяя метаданные файловой системы, а не копировать содержимое? Пока это работает на любой системе Linux, которая была бы приемлема для меня. Но решение для файловой системы не очень поможет.

Я не обучен ОС или CS, но теоретически кажется возможным создать новый инод и скопировать структуру указателя инода из инода файлов, из которых я хочу копировать, и затем отсоединить эти иноды. Есть ли какая-нибудь утилита, которая сделает это? Учитывая избыток хорошо продуманных утилит unix, я полностью ожидал, что это произойдет, но ничего не смог найти. Отсюда мой вопрос по ТАК. Файловая система находится на блочном устройстве, фактически на жестком диске, если эта информация имеет значение. Я не уверен, что смогу написать это самостоятельно, так как я никогда раньше не занимался программированием на системном уровне, поэтому любые указатели (на фрагменты кода C /Python) будут очень полезны.

12 голосов | спросил san 5 Mayam11 2011, 10:30:14

6 ответов


0

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

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

  1. Перед началом многопроцессорной обработки создайте окончательный выходной файл и увеличьте его. это до окончательного размера fseek() ИНГ до конца, это создаст разреженный файл .

  2. Запустите многопроцессорную обработку, передав каждый процесс FD и смещению в его определенный фрагмент файла.

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

ИЗМЕНИТЬ

Если вы не можете предсказать размер отдельных файлов, но потребитель Конечный файл может работать с последовательным (в отличие от произвольного доступа) вводом, вы можете передать cat tmpfile1 .. tmpfileN потребителю либо на стандартный ввод

cat tmpfile1 ... tmpfileN | consumer

или через именованные каналы (используя подстановку процессов в bash):

consumer <(cat tmpfile1 ... tmpfileN)
ответил Marc Mutz - mmutz 5 Mayam11 2011, 10:39:42
0

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

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

FUSE имеет привязки для нескольких языков, включая Python . Если вы посмотрите на некоторые примеры здесь или здесь (это для разных привязок), для этого требуется на удивление мало кода.

ответил NPE 5 Mayam11 2011, 10:47:36
0

Я так не думаю, inode может быть выровнен, поэтому это возможно, только если вы можете оставить несколько нулей (или неизвестных байтов) между нижним колонтитулом одного файла и заголовком другого файла.

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

ИЗМЕНИТЬ

@san: Поскольку вы говорите, что используемый код не поддается контролю, вы можете объединить отдельные файлы на лету, используя именованные каналы:

$ mkfifo /tmp/cat
$ cat file1 file2 ... >/tmp/cat &
$ user_program /tmp/cat
...
$ rm /tmp/cat
ответил Xiè Jìléi 5 Mayam11 2011, 10:42:00
0

Для 4 файлов; xaa, xab, xac, xad быстрая конкатенация в bash (от имени root):

losetup -v -f xaa; losetup -v -f xab; losetup -v -f xac; losetup -v -f xad

(Предположим, что loop0, loop1, loop2, loop3 являются именами файлов новых устройств.)

Вставьте http://pastebin.com/PtEDQH7G в файл сценария join_us. Тогда вы можете использовать это так:

./join_us /dev/loop{0..3}

Затем (если этот большой файл - фильм), вы можете передать его в собственность обычному пользователю (chown itsme /dev /mapper /join), а затем он /она может воспроизвести его через: mplayer /dev /mapper /join

Очистка после них (от имени root):

dmsetup remove joined; losetup -d /dev/loop[0123]
ответил szabozoltan 18 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowWed, 18 Sep 2013 12:52:57 +0400 2013, 12:52:57
0

Нет, такого инструмента или системного вызова нет.

Вы могли бы исследовать, возможно ли для каждого процесса записать непосредственно в окончательный файл. Скажем, процесс 1 записывает байты 0-X, процесс 2 пишет X-2X и т. Д.

ответил janneb 5 Mayam11 2011, 10:40:18
0

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

ответил Ryan Thompson 5 Mayam11 2011, 10:53:25

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132