суббота, 20 марта 2010 г.

Linux: максимальное количество файлов в папке

Цель эксперимента: определить, насколько комфортно будет ворочаться мой Linux в папке с большим количеством файлов.

Компьютер: Intel(R) Core(TM)2 Duo CPU E7300 @ 2.66GHz
Жёсткий диск: Seagate Barracuda ES SATA 3.0Gb/s 500Gb
Файловая система: wubi/ntfs/ext3 (использует раздел Widnows)
Операционная система: Ubuntu 8.10

Фаза 1. Создание файлов

Так как свободных инодов было всего 640 тысяч, я принял решение сгенерить полмиллиона файлов. Размер файлов был выбран в 2 килобайта.

Вот скрипт (newLISP):

(module "crypto.lsp")
(make-dir "/home/hilo/testdir")
(change-dir "/home/hilo/testdir")

(define (rand-2k)
(join (map (fn (x) (append (string x) ": " (join
(map string (rand 10 50))))) (sequence 0 37)) "\n"))

(time (dotimes (x 500000)
(write-file (append (crypto:md5 (string (random))) ".txt") (rand-2k))))


Время генерации файлов: 17 минут.

Фаза 2. Тест производительности

; Найти файлы по маске
(directory "." "7.*") ; 0,5с.

; Получить список вообще всех файлов
(directory ".") ; те же 0,5с.

; Отобрать 200 файлов и прочесть их из папки в память:
(map (fn (x) (read-file x)) (directory "." "6666.*")) ; Две секунды

; Прочесть один файл с известным именем:
(read-file "7777cc087494c9e6e474ac9fe6c01dfc.txt") ; 0,013 ms

; Прочесть файл из папки, в которой лежит всего несколько файлов:
(time (read-file "../ffec6ba54ea01fd951dc2433334abd0c.txt")) ; 0,014 ms

Вывод 1: скорость чтения файлов никак не зависит от того, сколько у них соседей в папке.
Вывод 2: файлы читаются мгновенно.
Вывод 3: непонятно, почему чтение 200 предварительно отобранных файлов занимает две секунды -- должно занимать полсекунды. Надо полагать, если сделать отбор имён, подождать две секунды, а потом прочесть их -- чтение займёт не полторы секунды, а несколько миллисекунд.

Фаза 3. Работа со встроенными командами Linux

3.1. Поиск через grep
grep -l "777" 5555* # 3 cекунды

3.2. ls
ls testdir > test.txt # 3 секунды (создался файл на 18 Мb)

3.3. Подсказка имени. Нажатие "Tab" для подсказки подвесило систему примерно на одну минуту, потом всё отвисло.

3.4. rm
rm * вылетел через 40 секунд с ошибкой:
"bash: /bin/rm: Слишком длинный список аргументов."

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

Фаза 4. Удаление файлов

(map delete-file (directory ".")) ; две минуты, под бодрое шуршание диска.

На начало эксперимента было свободно 641373 инодов из 856800. После окончания эксперимента свободных инодов стало 641279. Куда зажевались примерно 100 инодов -- неясно. Вероятно, на временные файлы операционной системы и временные файлы newLISP.

Общий вывод. Для серьёзной нагрузки 500 000 файлов -- это довольно натужно. Я бы предпочёл иметь запас по скорости раз в десять от демонстрируемого.

Впрочем, сначала я собираюсь обновить систему до 9.10 и посмотреть, насколько бодро пойдёт работа со встроенной файловой системой.

--- Продолжение ---

Проапгрейдился до 9.10. Файловая система ext4, созданная непосредственно на диске, без всяких промежуточных ntfs. Также немного упростил скрипт:

(make-dir "/tmp/testdir")
(change-dir "/tmp/testdir")

(define (string-append) (apply append (map string (args))))

(define (rand-2k x)
(write-file (string-append x ".txt")
(join (map (fn (x) (append (string x) ": " (join
(map string (rand 10 50))))) (sequence 0 37)) "\n")))

(define (gen-1k y)
(dotimes (x 1000) (rand-2k (string-append y "_" x)))
(println y))

(time (map gen-1k (sequence 0 999)))


Миллион файлов на этот раз создавался 32 минуты. В общем, практически столько же, сколько и в прошлый раз. А вот тайминг (время newLISP сообщает в миллисекундах):

> (time (directory "."))
563,001
> (time (directory "." "666.*"))
572,296 ; Это полсекунды
> (length (directory "."))
1000002
> (time (map read-file (directory "." "666.*")))
9913,617 ; 5 миллисекунд на файл
> (time (map read-file (directory "." "668_.*")))
1186,284 ; 1 миллисекунда на файл


Как видно, скорость поиска в директории увеличилась по сравнению с ntfs в два раза, а вот скорость чтения файлов почему-то сильно скачет. В дальнейших экспериментах скорость чтения одного файла составляла 10-50 миллисекунд на первый заход и примерно 0,02 миллисекунды на чтение кэшированного файла. Файлы, напомню, имеют размер в два килобайта.

Итоговый вывод остался неизменным: работать с миллионом файлов в одной папке можно, если имена файлов известны. Если требуется поиск -- возможны варианты. Полсекунды на поиск иногда уже чересчур.

Удаление заняло примерно полчаса:
(map delete-file (directory "."))


Затем тем же скриптом я успешно нагенерил минут за 40 миллион файлов для Windows:
http://hilocomod.blogspot.com/2010/03/windows.html

5 комментариев:

  1. А как встроенные команды Linux работают с миллионом файлов?

    ОтветитьУдалить
  2. Да нормально работают. Не особо быстро, но, например, ls > filelist.txt выполнился относительно быстро, равно как и rm *

    Вот в Окнах были проблемы со скоростью.

    ОтветитьУдалить
  3. Понятно. Интересный материал, спасибо.

    ОтветитьУдалить
  4. Спасибо. Помогло решить задачу.

    ОтветитьУдалить

Архив блога