Недавно у нас возник спор с коллегами об ограничениях файловых систем и максимально допустимом количестве файлов в одном каталоге под 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 файлов.