Если вы выполняете некоторую фильтрацию, которую предлагает ваш комментарий в самом глубоком foreach, и вы игнорируете большинство строк в журналах, то вы можете попробовать заменить my $cat = `cat $file`;
на my $cat = `grep PATTERN $file`;
, чтобы хотя бы смягчить Perl памяти, если файлы большие. Может быть, даже такие большие, что они вызывают перестановку дисков из-за нехватки памяти, что и является вашей реальной проблемой с вашим perl кодом. Во многих, если не в большинстве версий grep, PATTERN также может быть регулярным выражением типа perl с параметром -P
: grep -P 'REGEXP' file
.
Если медлительность равна, например, 99% IO (чтение с диска и / или пишет, что вы можете узнать по time perl script.pl
и посмотреть, если real
из вывода time
намного больше, чем другие), то, вероятно, вы мало что можете сделать, за исключением того, что ваша система может сделать сжатые файлы журнала. Иногда, если у вас медленный диск, может быть диск, смонтированный в сети, и быстрые процессоры, распаковка + обработка может быть быстрее, чем просто обработка несжатых файлов. Возможно, так: my $cat = ` zcat $file.gz | grep PATTERN `;
Также вы можете попробовать распараллелить с fork
, добавив этот внешний for-l oop:
my $LogPath = "/path/to/log/file";
my $list = `ls -1 $LogPath/*.log`;
my $jobs=4; #split work into 4 jobs (splits work to up to 4 CPUs)
for my $job (1..$jobs){
next if !fork;
my $i=0;
my @array_list = grep $i++ % $jobs == $job-1, #do only what this process should
split(/\n/, $list);
foreach $file (@array_list){
my $cat = `cat $file`;
my @content = split(/\n/, $cat);
foreach $line (@content) {
....
#Doing some operation if the matching content found
....
....
}
}
last;
}
(Кстати, for и foreach являются синонимами, не знаю, почему так много perl кодеров беспокоятся о четырех последних символах foreach)