100 000 файлов в одном каталоге

Недавно у нас возник спор с коллегами об ограничениях файловых систем и максимально допустимом количестве файлов в одном каталоге под Linux. В частности, известное решение для файлового кэширования сайтов (сброс всего подряд в один каталог в виде файликов) начинает работать крайне неэффективно когда число файликов в одной директории превышает десятки тысяч.

Для тех, кто не хочет / не может поставить эксперимент и поверить своим глазам, я привожу результаты из реальной практики:

Дано: ubuntu server с ядром 2.6.32, заведомо пустой и без нагрузки (Load Averages честный ноль). Берём и пишем php-скрипт, который будет создавать файлы с рандомным контентом и замерять время их считывания.

for ($i=0;$i<10000;$i++)
{
$c=md5(time().rand(1,10000000));
$c=str_repeat($c,3000);
file_put_contents('./output/'.$i.'.txt',$c);
$n=rand(0,$i);
$t1=microtime_float();
$a=file_get_contents('./output/'.$n.'.txt');
$t2=microtime_float();
$t=$t2-$t1;
if ($t>0.1) { echo ($i."=".$t."\n"); }
}
function microtime_float()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}

Скрипт будет складывать файлики в директорию ./output, не поленитесь её создать. В скрипте объявляется цикл, который тупо создаёт файлики подряд от 0 до 10000 штук, наполняя каждый из них случайным контентом. Сразу после создания случайный файл из этой кучи считывается, при этом замеряется время (в миллисекундах). Далее в условии “if ($t…” вы можете указывать, какие величины вам нужно показывать на экране.

В самом начале работы скрипта, пока счётчик файлов в пределах 100, время считывания составляет исчезающе малые 0.001 секунды. Когда счётчик приближается к 5000, среднее время считывания составляет 0.6 секунды. Это в сотни раз больше! Дальше тестировать не было смысла, так как задержки стали заметны визуально. И это, повторюсь, происходило на пустом сервере без какой-либо посещаемости.

Давайте спросим у Капитана Очевидности, что же делать в такой ситуации? Решение просто как 5 копеек: раскладывайте файлы по директориям таким образом, чтобы в каждой было не более 5-10 тысяч файлов. Например, если у вас предполагается файловый кэш на 100 000 файлов в одном каталоге, делайте так:

/path-to-cache/dir1/dir2/filename.txt

Здесь dir1 – это первый символ в имени файла, dir2 – второй символ. При этой схеме в каждом каталоге будет не более 1000 файлов.