我正在使用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方法中的任何一种的性能?
答案 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,然后运行所需的命令。这将总是较慢,但在具有空闲资源的快速系统上,它可能不是很明显。