Индексы Unix - фрагментация и выгрузка содержимого каталога - PullRequest
1 голос
/ 27 октября 2009

У нас возникла проблема в Linux, из-за того, что индексы каталогов становились большими и медленно перемещались с течением времени, так как многие файлы создаются и удаляются. Например:

% ls -ld foo
drwxr-xr-x    2 webuser  webuser   1562624 Oct 26 18:25 foo
% time find foo -type f | wc -l
    518
real    0m1.777s
user    0m0.000s
sys     0m0.010s

% cp -R foo foo.tmp
% ls -ld foo.tmp                                                                       
drwxr-xr-x    2 webuser  webuser     45056 Oct 26 18:25 foo.tmp   
% time find foo.tmp -type f | wc -l
    518
real    0m0.198s
user    0m0.000s
sys     0m0.010s

Исходный каталог содержит 518 файлов, для его представления требуется 1,5 МБ, а для обхода требуется 1,7 секунды.

Перестроенный каталог имеет такое же количество файлов, для его представления требуется 45 КБ и 0,2 секунды для перехода.

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

Мне также интересно, есть ли способ выгрузить буквенное двоичное содержимое каталога - то есть прочитать каталог, как если бы он был файлом - что, возможно, дало бы мне понимание того, почему он такой большой. Ни read (), ни sysread () из Perl не позволят мне:

 swartz> perl -Mautodie -MPOSIX -e 'sysopen(my $fh, "foo", O_RDONLY); my $len = sysread($fh, $buf, 1024);'
 Can't sysread($fh, '', '1024'): Is a directory at -e line 1

Системная информация:

Linux 2.6.18-128.el5PAE #1 SMP Wed Dec 17 12:02:33 EST 2008 i686 i686 i386 GNU/Linux

Спасибо!

Jon

Ответы [ 2 ]

2 голосов
/ 27 октября 2009

В вопросе 1 внешняя фрагментация обычно приводит к накладным расходам примерно в 2 раза или около того, 1 плюс вы получаете внутреннюю фрагментацию из-за гранулярности распределения. Ничто из этого не подходит для объяснения ваших наблюдений.

Итак, я не думаю, что это нормальная стационарная фрагментация.

Самым очевидным предположением является то, что 1,5 МБ является отметкой максимальной воды; когда-то он действительно имел либо 1,5 МБ байтов записей, либо 1,5 МБ / 2 байта записей с ожидаемой фрагментацией.

Другое предположение состоит в том, что правило 50% терпит поражение от немарковского распределения. Представьте, что я называю файлы "tmp% d", поэтому tmp1, tmp2, ... tmp1000, tmp1001, ...

Проблема здесь в том, что rm tmp1 не освобождает место для tmp1001. Это явно дикое предположение.

Q2: Не существует хорошего способа чтения необработанного каталога. AFAIK, вам нужно будет либо взломать ядро, либо использовать debugfs для изменения типа inode, прочитать его, затем изменить его обратно, либо использовать debugfs для чтения inode, получения номеров блоков, а затем чтения блоков. Функциональный подход к отладке, вероятно, более разумен.

Вы можете решить проблему с производительностью, убедившись, что индексация включена. Смотри tune2fs.


1 Правило Кнута о пятидесяти процентах: в стационарном состоянии 50% операций - это выделения, 50% - освобождения, 50% свободных блоков объединяются, затем дыры составляют 50% распределений и 50% пространства впустую. (Ака, 100% накладных расходов.) Это считается "нормальным". У Маллока та же проблема.

0 голосов
/ 29 января 2015

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

Я думаю, у вас есть в основном две меры для решения этой проблемы:

  1. Создайте структуру подкаталогов, чтобы предотвратить слишком много дочерних элементов в одном родительском каталоге. Например, если вы создаете файлы, путь которых имеет формат, такой как dir/file-%06d, то у вас будет один миллион детей с ожидаемым огромным индексом каталога. Вы бы предпочли спроектировать некоторую структуру поддерева, разбивающую имена файлов на их префиксы переменных, например, если ваш файл file-123456.ext, выделите их под чем-то вроде dir/files/1/2/3/4/123456.ext. Эта стратегия ограничит максимальное количество детей до 1000 под конечным листом каталога. Уровень декомпозиции будет зависеть от размера переменной части имени файла.

  2. В качестве меры противодействия, когда у вас уже есть огромные inode-ы каталогов, остается сделать немного больше, чем создать новый (small-inode) одноуровневый каталог, чтобы переместить все оригинальные (.) Файлы в новый каталог , чтобы удалить исходный каталог и переименовать новый каталог в исходное имя. Остерегайтесь одновременно работающих служб по исходному пути.

Некоторые shell-фу, включающие find и stat --printf='%b' или %s в каталогах, могут помочь вам обнаружить другие проблемные места в вашей файловой системе и поставить их под пристальное наблюдение.

Для получения подробной информации о файловой системе, посмотрите этот пост на ServerFault.com

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