Чтение тысяч файлов в ближайшем будущем - PullRequest
1 голос
/ 14 апреля 2019

Я работаю над сценарием, который должен прочитать десятки тысяч файлов с диска. Я пытаюсь понять лучший способ сделать это. Я столкнулся с проблемой, когда я использую map, чтобы сделать это, используя два пакета clj-glob и clojure-mail:

(def sent-mail-paths
  (->> (str maildir-path "/*/_sent_mail/*")
       (glob) ;; returns files using clojure.java.io/as-file
       (map str) ;; i just want the paths
))

(def msgs
  (->> sent-mail-paths ;; 30K + paths
       (map mail/file->message)))

, где функция glob в первом блоке взята из clj-glob и использует as-file для возврата набора файловых объектов (см. здесь ). Я хочу только строки пути, поэтому я делаю (map str). Функция mail/file->message во втором блоке использует with-open вместе с классом java FileInputStream для чтения файлов (см. здесь ).

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

(count msgs)

Ошибка:

(Слишком много открытых файлов в системе)

Единственный способ выполнить эту работу - использовать doseq:

(def msgs (->> list-of-paths ;; 30K+ paths
               (map mail/file->message)))

(def final (atom []))
(doseq [x result]
  (swap! final conj (mail/file->message x)))

Мой вопрос заключается в том, является ли это лучшим (единственным?) Способом выполнить этот процесс, не открывая одновременно тысячи и тысячи файлов? Я не до конца понимаю, почему я не могу использовать ленивую последовательность, возвращаемую map. Почему это в конечном итоге открывает тонны файлов.

Кстати, одна вещь, которую я заметил, это то, что clj-glob, который не является исправным пакетом, не использует with-open, когда он вызывает as-file ...

1 Ответ

1 голос
/ 14 апреля 2019

Даже если вы правильно открываете / закрываете файлы, есть вероятность, что во время выполнения программы вы достигнете внутренне определенного предела числа дескрипторов файлов, которые вы можете запрограммировать (это часто встречается в долгоживущих программах, таких какв виде микросервисов).

Здесь вы можете прочитать о том, как посмотреть, какой сейчас этот предел и как его увеличить: https://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/

...