如何提高File :: Find :: Rule调用的性能?

时间:2011-02-19 17:30:54

标签: perl file unix find posix

我正在使用File::Find::Rule$dir中指定的目录中找到一级深度的用户可执行文件夹:

my @subDirs = File::Find::Rule->permissions(isExecutable => 1, user => "$uid")->
                                extras({ follow => 1, follow_skip => 2 })->
                                directory->
                                maxdepth(1)->
                                in( $dir );

以下是使用UNIX find实用程序的粗略等效项:

my $subDirStr = `find $dir -maxdepth 1 -type d -user $username -perm -100`;
chomp($subDirStr); 
my @subDirs = split("\n", $subDirStr);

两者都在具有恢复此数据权限的脚本中运行。

如果我在命令行上运行find语句,结果会立即恢复。

如果我通过Perl脚本运行上述任一语句,结果需要几秒钟才能运行。

我可以通过编程方式进行哪些操作来提高两种Perl方法中的任何一种的性能?

3 个答案:

答案 0 :(得分:5)

我怀疑您看到的延迟是由于生成所有结果所需的时间长度。当然,如果您将find命令传递到less,您会立即获得结果,但如果将其传输到tail,您可能会看到与您在Perl脚本中看到的类似的延迟。

在您的两个替代实现中,您正在创建一个包含所有匹配文件列表的数组 - 在文件匹配过程完成之前,您的代码将不会继续。

您也可以使用这样的迭代器方法:

my $rule = File::Find::Rule->permissions(isExecutable => 1, user => $uid)
                           ->extras({ follow => 1, follow_skip => 2 })
                           ->directory
                           ->maxdepth(1)
                           ->start($dir);
while( defined ( my $path = $rule->match ) ) {
    ...
}

为了完整性,您可以使用find命令获得类似的结果。您可以显式使用管道并一次读取一个结果,而不是使用反引号:

open my $pipe, 'find $dir -maxdepth 1 -type d -user $username -perm -100|' or die "Can't run find: $!";
while(my $path = <$pipe>) {
    ...
}

请注意,通过这两个示例,您的代码可以在找到第一个匹配项后立即开始处理结果。但是,处理最后一个结果所用的总时间与原始代码的差别不大。

答案 1 :(得分:3)

我暂时忽略File :: Find :: Rule部分,并关注命令行中find的差异与perl中反引号的查找。

首先,请验证除了find...命令之外什么也不做的脚本仍有问题,由您作为同一用户运行,并且在与快速运行的命令行调用相同的目录上运行。< / p>

如果没有问题,我们需要了解您的脚本的更多信息。或者你需要逐个删除脚本中的内容,直到你只需要执行find命令,然后看看需要删除哪些内容才能解决问题。

如果是,请尝试使用完整路径(例如/usr/bin/find)而不是find来消除PATH差异或shell别名导致差异的可能性。

同时检查命令行运行和反引号运行的输出是否相同。

尝试将两者的输出重定向到/ dev / null(在反引号内,对于perl版本),看看是否会对时间产生任何影响。

答案 2 :(得分:0)

你必须意识到通过反引号或system()通过perl调用命令会导致perl分离出一个shell,然后运行所需的命令。这将总是较慢,但在具有空闲资源的快速系统上,它可能不是很明显。