gpt4 book ai didi

performance - 为什么 Perl 循环中的函数调用这么慢?

转载 作者:行者123 更新时间:2023-12-03 14:30:46 29 4
gpt4 key购买 nike

我正在用 Perl 编写一个文件解析器,所以不得不遍历文件。文件由固定长度的记录组成,我想创建一个单独的函数来解析给定的记录并在循环中调用该函数。但是,大文件的最终结果变得很慢,我的猜测是我不应该使用外部函数。因此,我在循环中使用和不使用函数调用进行了一些虚拟测试:

[一种]

foreach (1 .. 10000000) {
$a = &get_string();
}

sub get_string {
return sprintf("%s\n", 'abc');
}

[乙]
foreach (1 .. 10000000) {
$a = sprintf "%s\n", 'abc';
}

测量显示 A 代码的运行速度比代码 B 慢 3-4 倍。我事先知道代码 A 应该运行得更慢,但我仍然很惊讶差异如此之大。还尝试使用 Python 和 Java 运行类似的测试。在 Python 代码中,A 等效代码比 B 慢约 20%,并且 Java 代码或多或少以相同的速度运行(如预期)。将功能从 sprintf 更改为其他功能没有显示出任何显着差异。

有什么办法可以帮助 Perl 更快地运行这样的循环?我在这里做错了什么,还是 Perl 的功能调用是这样的开销?

最佳答案

Perl 函数调用很慢。这很糟糕,因为你想做的事情,将你的代码分解成可维护的函数,正是会减慢程序速度的事情。他们为什么慢? Perl 在进入子例程时会做很多事情,这是因为它是非常动态的(即,您可以在运行时处理很多事情)。它必须获取该名称的代码引用,检查它是否是代码引用,设置一个新的词法暂存器(存储 my 变量),一个新的动态范围(存储 local 变量),设置 @_ 仅举几例,检查它被调用的上下文并传递返回值。已尝试优化此过程,但尚未得到返回。有关血腥的详细信息,请参阅 pp_entersub in pp_hot.c

在 5.10.0 中也有一个减慢功能的错误。如果您使用的是 5.10.0,请升级。

因此,避免在长循环中一遍又一遍地调用函数。特别是如果它是嵌套的。你能缓存结果吗,也许使用 Memoize ?工作必须在循环内完成吗?它是否必须在最内层循环内完成?例如:

for my $thing (@things) {
for my $person (@persons) {
print header($thing);
print message_for($person);
}
}

header 的调用可以移出 @persons 循环,从而将调用次数从 @things * @persons 减少到 @things
for my $thing (@things) {
my $header = header($thing);

for my $person (@persons) {
print $header;
print message_for($person);
}
}

关于performance - 为什么 Perl 循环中的函数调用这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3255512/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com