Did some benchmarking today. I really like knowing the most effective way to solve
a certain problem and when
Corion posted his code above, I got curious. To Corion,
I would like to say that this is no "I'm right - you're wrong" kind of thing. I've
enjoyed your code (since I love and use eConsole) for a long time, and I really didn't
know which of the ways that was most effective, so please don't take this the wrong way.
If someone else have ideas about this please, give it a shot with your own code.
I use directory travering quite often so I would really be glad to be able to use the
most effective code in my programs.
Here we go:
use Benchmark;
use File::Spec;
use File::Find;
$t0 = new Benchmark;
&t1('C:\\Program');
$t1 = new Benchmark;
&t2('C:\\Program');
$t2 = new Benchmark;
&t3('C:\\Program');
$t3 = new Benchmark;
&t4('C:\\Program');
$t4 = new Benchmark;
&t5('C:\\Program');
$t5 = new Benchmark;
print "t1: ",timestr(timediff($t1, $t0)),"\n";
print "t2: ",timestr(timediff($t2, $t1)),"\n";
print "t3: ",timestr(timediff($t3, $t2)),"\n";
print "t4: ",timestr(timediff($t4, $t3)),"\n";
print "t5: ",timestr(timediff($t5, $t4)),"\n";
# Opens a dirhandle to read files, another to read sub-dirs and
# recursive calls itself foreach subdir it finds
sub t1 {
my $Dir = shift;
opendir(DIR, $Dir) || die "Can't opendir $Dir: $!";
my @Files = grep { /.txt/ && -f "$Dir/$_" } readdir(DIR);
closedir DIR;
opendir(DIR, $Dir) || die "Can't opendir $Dir: $!";
my @Dirs = grep { /^[^.].*/ && -d "$Dir/$_" } readdir(DIR);
closedir DIR;
foreach $file (@Files) { print $Dir."-".$file."\n"; }
foreach $SubDir (@Dirs) { &t1(join("\\",$Dir,$SubDir)); }
};
# Opens a dirhandle to read files, rewinds to read sub-dirs and
# recursive calls itself foreach subdir it finds
sub t2 {
my $Dir = shift;
opendir(DIR, $Dir) || die "Can't opendir $Dir: $!";
my @Files = grep { /.txt/ && -f "$Dir/$_" } readdir(DIR);
rewinddir(DIR);
my @Dirs = grep { /^[^.].*/ && -d "$Dir/$_" } readdir(DIR);
closedir DIR;
foreach $file (@Files) { print $Dir."-".$file."\n"; }
foreach $SubDir (@Dirs) { &t2(join("\\",$Dir,$SubDir)); }
};
# Opens a dirhandle to read all directory contents and
# recursive calls itself foreach subdir it finds
# Uses File::Spec, which makes it portable
sub t3 {
my ($Dir) = shift;
my ($entry,@direntries,$fullpath);
opendir( DIR, $Dir ) or die "Can't opendir $Dir: $!";
@direntries = readdir( DIR ) or die "Error reading $Dir : $!\n";
closedir DIR;
foreach $entry (@direntries) {
next if $entry =~ /^\.\.?$/;
$fullpath = File::Spec->catfile( $Dir, $entry );
if (-d $fullpath ) {
&t3($fullpath);
} elsif ( -f $fullpath && $entry =~ /.txt/) {
print $Dir."-".$entry."\n";
}
}
};
# Opens a dirhandle to read all directory contents and
# recursive calls itself foreach subdir it finds
sub t4 {
my ($Dir) = shift;
my ($entry,@direntries,$fullpath);
opendir( DIR, $Dir ) or die "Can't opendir $Dir: $!";
@direntries = readdir( DIR ) or die "Error reading $Dir : $!\n";
closedir DIR;
foreach $entry (@direntries) {
next if $entry =~ /^\.\.?$/;
$fullpath = join("\\",$Dir,$entry);
if (-d $fullpath ) {
&t4($fullpath);
} elsif ( -f $fullpath && $entry =~ /.txt/) {
print $Dir."-".$entry."\n";
}
}
};
# Uses File::Find (whatever it does...)
sub t5 {
my ($Dir) = shift;
find(\&found, $Dir);
}
sub found {
/.txt/ && print $File::Find::dir."-".$_."\n";
}
This test was run on a Pentiun 233 with 128Mb RAM, Windows 2000, FAT32 filesystem
C:\\Program holds 13477 files in 1206 folders of which 137 matches *.txt
t1: 27 wallclock secs ( 8.40 usr + 16.76 sys = 25.17 CPU)
t2: 24 wallclock secs ( 7.69 usr + 15.57 sys = 23.26 CPU)
t3: 47 wallclock secs (20.30 usr + 23.85 sys = 44.15 CPU)
t4: 36 wallclock secs (11.04 usr + 23.33 sys = 34.37 CPU)
t5: 30 wallclock secs (11.12 usr + 18.02 sys = 29.13 CPU)
/brother t0mas