2013-07-18 3 views
8

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

В настоящее время я использую Perl-скрипт, который читает в каталоге массив, а затем захватывает размер массива и отправляет его в сценарий мониторинга. К сожалению, по мере роста нашей системы этот монитор становится все медленнее.

Я ищу способ, который будет работать намного быстрее, вместо того, чтобы приостанавливать и обновлять каждые 15-20 секунд после выполнения операции подсчета во всех связанных каталогах.

Я относительно уверен, что мое узкое место является считывающим каталогом в операции с массивом.

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

В моем коде я не считаю скрытые файлы или текстовые файлы, которые я использую для хранения информации о конфигурации. Было бы здорово, если бы эта функциональность была сохранена, но, безусловно, не является обязательной.

Я нашел несколько ссылок на подсчет inodes с кодом C или что-то в этом роде, но я не очень опытен в этой области.

Я хотел бы сделать этот монитор как можно скорее.

код Perl я использую выглядит следующим образом:

opendir (DIR, $currentDir) or die "Cannot open directory: $!"; 
@files = grep ! m/^\./ && ! /config_file/, readdir DIR; # skip hidden files and config files 
closedir(DIR); 
$count = @files; 
+0

использование перл нити или вилки, чтобы свести к минимуму время –

+0

ждет @mpapec Мне нравится идея, в лучшем случае это будет еще сделать мое время ожидания близко к количеству времени, которое было бы, если бы я выполнил этот код только в моем самом длинном каталоге? Если это так, это не плохая идея, но, к сожалению, большинство моих каталогов имеют менее 50 файлов, в то время как у одного или двух есть тысячи. Мне очень хотелось бы найти способ полностью уйти от чтения в каждом файле в каталоге. – Andrew

ответ

9

То, что вы делаете прямо сейчас читает весь каталог (более или менее) в память только отказаться от этого контента для его подсчета. Избегайте, что в потоковом каталог вместо:

my $count; 
opendir(my $dh, $curDir) or die "opendir($curdir): $!"; 
while (my $de = readdir($dh)) { 
    next if $de =~ /^\./ or $de =~ /config_file/; 
    $count++; 
} 
closedir($dh); 

Важно отметить, что не используют glob() в любой из его форм. glob() will expensively stat() every entry, который не накладные расходы вы хотите.

Теперь у вас могут быть гораздо более сложные и более легкие способы сделать это в зависимости от возможностей ОС или возможностей файловой системы (Linux, в качестве сравнения, предлагает inotify), но потоковая передача каталога, как указано выше, примерно так же хороша, как и вы «Допустим.

+0

Мне это нравится. Я думаю, вы правы. На данный момент я хочу держаться подальше от конкретных файловых систем. Я могу пойти по этому пути в будущем, но я хочу, чтобы эта вещь была как можно более переносимой. Благодаря! Это немного ускорилось. Это не намного быстрее, но это помогает. – Andrew

-1

Сохраните это.

@files = readdir(DIR) - 2; 

The -2 is because readdir counts "." and ".." as directory entries. 

print @files . " files found\n"; 
exit; 

1 найденные файлы

+0

Ваше предположение о том, что в любом каталоге имеется ровно 2 точечных файла, является крайне опасным и очень часто неверным предположением. кроме того, задан вопрос о том, чтобы исключить конкретные файлы конфигурации. последнее это предложение не быстрее предыдущего, поскольку узким местом является операция чтения, которая существует в вышеприведенном решении. – Andrew

+0

-1 Немного проблематично. 'readdir' в скалярном контексте возвращает следующую запись каталога, а не число (оставшихся?) записей. Затем вы вычитаете два из этого имени файла, которое, вероятно, преобразуется в числовое значение ноль. Затем вы назначаете скаляр -2 в список. И, как отметил @Andrew, OP все равно должен исключить все мелкие файлы и другие определенные шаблоны. – pilcrow