Буферизация поверх VFS - PullRequest
2 голосов
/ 31 мая 2011

проблема, которую я пытаюсь решить, заключается в сохранении большого количества (миллионов) небольших файлов (до 50 КБ), которые отправляются по сети. Сохранение выполняется последовательно: сервер получает файл или каталог (по сети), сохраняет его на диск; следующий прибывает, он сохранен и т. д. Очевидно, что производительность не приемлема, если сосуществуют несколько серверных процессов (скажем, у меня есть 5 процессов, которые все читают из сети и пишут одновременно), потому что планировщику ввода-вывода не удается эффективно объединить ввод-вывод пишет.

Предлагаемое решение заключается в реализации некоторой буферизации: у каждого серверного процесса должен быть кэш объемом 50 МБ, в который он должен записать текущий файл, выполнить chdir и т. Д .; когда буфер заполнен, он должен быть синхронизирован с диском, поэтому получается пакет ввода-вывода.

Мои вопросы к вам: 1) я знаю, что уже существует буферный механизм (дисковый буфер); Как вы думаете, приведенный выше сценарий добавит улучшения? (дизайн намного сложнее, и реализовать простой тестовый пример непросто)

2) есть ли у вас какие-либо предложения, где искать, если бы я это реализовал?

Большое спасибо.

Ответы [ 3 ]

1 голос
/ 31 мая 2011

Вам нужно будет сделать лучше, чем

«очевидно, что производительность не приемлема».

В частности

  • Как вы измеряете это?У вас есть точная, воспроизводимая цифра
  • Какова ваша цель?

Чтобы выполнить оптимизацию, вам нужны две вещи: метод ее измерения (метрика) ицель (чтобы вы знали, когда остановиться, или насколько полезна или бесполезна конкретная техника).

Боюсь, что ни с того, ни с сего ты утонул.

0 голосов
/ 04 декабря 2014

Создание / переименование файла, его синхронизация, наличие большого количества файлов в каталоге и большое количество файлов (с ненужными отходами) - некоторые из медленных операций в вашем сценарии. Однако, чтобы избежать их, это только помогло бы написать меньшие файлы (например, выписать архивы, объединенный файл или подобный). Я бы на самом деле попробовал (ограниченный) параллельный асинхронный или синхронизированный подход. Планировщик ввода-вывода и кэши обычно довольно хороши.

0 голосов
/ 31 мая 2011

Насколько важны эти записи? У меня есть три предложения (которые можно объединить), но одно из них - большая работа, а одно менее безопасное ...

Журналирование

Я предполагаю, что вы видите низкую производительность из-за ведения журнала , характерного для большинства современных файловых систем Linux. Журналирование приводит к вставке барьеров в очередь ввода-вывода при записи метаданных файла. Вы можете попробовать отключить предохранитель (и возможно увеличит скорость) с mount(8) параметрами barrier=0 и data=writeback.

Но если происходит сбой, журнал не сможет предотвратить длительный fsck(8). И есть вероятность, что fsck(8) будет выбрасывать ваши данные при устранении проблемы. С одной стороны, это не легкомысленный шаг, с другой стороны, в прежние времена мы запускали наши ext2 файловые системы в режиме async без журнала в обе стороны, и нам понравилось.

IO Scheduler Лифт

Другая возможность - поменять лифт IO; смотрите Documentation/block/switching-sched.txt в дереве исходников ядра Linux. Короткая версия: deadline, noop, as и cfq доступны. cfq - это ядро ​​по умолчанию и, вероятно, то, что использует ваша система. Вы можете проверить:

$ cat /sys/block/sda/queue/scheduler
noop deadline [cfq] 

Наиболее важные части из файла:

As of the Linux 2.6.10 kernel, it is now possible to change the
IO scheduler for a given block device on the fly (thus making it possible,
for instance, to set the CFQ scheduler for the system default, but
set a specific device to use the deadline or noop schedulers - which
can improve that device's throughput).

To set a specific scheduler, simply do this:

echo SCHEDNAME > /sys/block/DEV/queue/scheduler

where SCHEDNAME is the name of a defined IO scheduler, and DEV is the
device name (hda, hdb, sga, or whatever you happen to have).

The list of defined schedulers can be found by simply doing
a "cat /sys/block/DEV/queue/scheduler" - the list of valid names
will be displayed, with the currently selected scheduler in brackets:

# cat /sys/block/hda/queue/scheduler
noop deadline [cfq]
# echo deadline > /sys/block/hda/queue/scheduler
# cat /sys/block/hda/queue/scheduler
noop [deadline] cfq

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

Изменения в приложении

Другая возможность состоит в том, чтобы радикально изменить ваше приложение, чтобы самим связывать файлы и записывать на диск меньше, более крупных файлов. Я знаю, это звучит странно, но (а) команда разработчиков iD упаковала свои карты, текстуры, объекты и т. Д. В гигантские zip файлы, которые они считывали в программу с помощью нескольких системных вызовов, распаковывали и запускали, потому что они нашли производительность намного лучше, чем чтение нескольких сотен или нескольких тысяч небольших файлов. Время загрузки между уровнями было значительно короче. (b) Команда рабочего стола Gnome и группа рабочего стола KDE использовали разные подходы к загрузке своих значков и файлов ресурсов: команда KDE упаковывает свои многочисленные небольшие файлы в более крупные пакеты какого-либо типа, а команда Gnome этого не делала. Команда Gnome имела более длительные задержки при запуске и надеялась, что ядро ​​может предпринять некоторые усилия, чтобы улучшить время запуска. Команда ядра продолжала предлагать меньший, больший, файловый подход.

...