день добрый!
Появилась необходимость возвращать из процедуры список файлов в некоторой директории. Обязательное условие - файлы должны быть отсортированы по времени создания.
Пока пользуюсь таким вот конвейером, но почему-то есть подозрение, что это можно сделать проще/производительней.
Поделитесь идеей, кому не лень. Буду очень благодаренsub get_new_messages($) {
my( $dir, @files );
$dir = shift;
if( opendir(DIR, $dir) ) {
@files = sort { (stat($a))[10] <=> (stat($b))[10] }
grep { -f }
map { "$dir/$_" }
readdir(DIR);
closedir(DIR);
} else {
logging( LOG_WARNING, "Can not open dir [%s]: %s", $dir, $! );
}
return @files;
}
>[оверквотинг удален]
> map { "$dir/$_" }
>
> readdir(DIR);
> closedir(DIR);
> } else {
> logging( LOG_WARNING, "Can not
>open dir [%s]: %s", $dir, $! );
> }
> return @files;
>}а почему просто не написать shell скрипт с использованием хотябы ls -t ?
А видимо это маленкий кусочек большого кода??
>А видимо это маленкий кусочек большого кода??конечно
>[оверквотинг удален]
> map { "$dir/$_" }
>
> readdir(DIR);
> closedir(DIR);
> } else {
> logging( LOG_WARNING, "Can not
>open dir [%s]: %s", $dir, $! );
> }
> return @files;
>}я думаю тормоза связаны с многочисленными вызовами команды stat в сортировке, поэтому смею предложить вариант такой:
#!/usr/bin/perl -w
use strict;
use Data::Dumper;#my $debugit=1;
sub SimpleReadDirSortByTime
{
my ($path) = shift;
my @dir;
opendir(Z, $path) or do{ print "can?t opendir $path: $!\n"; return [] };@dir =grep { -f } map { "$path/$_" } readdir(Z);
my @ds;
foreach my $i (@dir){
push @ds, (stat($i))[10];
}
print Dumper(@ds);
my @sdir = @dir[sort { $ds[$a] <=> $ds[$b] } 0..$#dir];
closedir(Z);
return @sdir;
}my @D = SimpleReadDirSortByTime('./testdir');
print Dumper(@D);
>я думаю тормоза связаны с многочисленными вызовами команды stat в сортировкеда, действительно, stat в сортировке выглядит совершенно не гут
Давно не писал на перле, захотелось поизвращаться. После всяких ужимок и прыжков получилось вот это:
sub get_new_messages($) {
my( $dir, @files );
$dir = shift;
@files = map { $_->[0] }
sort { $b->[1] <=> $a->[1] }
map { [ $_, -C ] }
grep { -f }
<$dir/*>;
return @files;
}На скорость еще не проверял правда
>[оверквотинг удален]
> sort { $b->[1] <=> $a->[1] }
>
> map { [ $_, -C ] }
>
> grep { -f }
> <$dir/*>;
> return @files;
>}
>
>На скорость еще не проверял правдада классно, думаю будет быстрее, тока сортировка у тебя почему то в обратном порядке стала.
>да классно, думаю будет быстрее,неа, этот вариант полностью сливает твоему, в основном из-за <*>
Лидеры:
sub get_sorted_file_list11($) {
my( $dir, @files, @ctime, @sorted );
$dir = shift;
if( opendir( DIR, $dir ) ) {
@files = grep { -f } map {"$dir/$_"} readdir(DIR);
closedir(DIR);
@ctime = map { (stat)[10] } @files;
@sorted = @files[ sort{ $ctime[$a] <=> $ctime[$b] } 0..$#files ];
} else {
warn $!;
}
return @sorted;
}
sub get_sorted_file_list10($) {
my( $dir, @files, @ctime, @sorted );
$dir = shift;
if( opendir( DIR, $dir ) ) {
@files = grep { -f } map {"$dir/$_"} readdir(DIR);
closedir(DIR);
@ctime = map { -C } @files;
@sorted = @files[ sort{ $ctime[$b] <=> $ctime[$a] } 0..$#files ];
} else {
warn $!;
}
return @sorted;
}sub get_sorted_file_list8($) {
my( $dir, @files );
$dir = shift;
if( opendir(DIR, $dir) ) {
@files = map { $_->[0] }
sort { $b->[1] <=> $a->[1] }
grep { -f $_->[0] }
map { [ "$dir/$_", -C "$dir/$_" ] }
readdir(DIR);
closedir(DIR);
} else {
warn "Can not open dir [$dir]: $!\n";
}
return @files;
}
Benchmark: timing 10000 iterations of var10, var11, var8...
var10: 53 wallclock secs (13.47 usr + 36.22 sys = 49.69 CPU) @ 201.26/s (n=10000)
var11: 58 wallclock secs (17.66 usr + 37.02 sys = 54.68 CPU) @ 182.88/s (n=10000)
var8: 55 wallclock secs (14.72 usr + 37.12 sys = 51.84 CPU) @ 192.92/s (n=10000)
>тока сортировка у тебя почему то в
>обратном порядке стала.-M -A и -С возвращают число дней, чем больше результат, тем старее файл. Вроде все правильно, результаты по крайней мере сходятся с ожидаемыми )))