我正在尝试解析一个大型 XML 文件。我使用 XML::SAX(使用 Expat,而不是 perl 实现)读取它并将所有第二级及以下节点放入我的“节点”类:
package Node;
use Moose;
has "name" =>
(
isa => "Str",
reader => 'getName'
);
has "text" =>
(
is => "rw",
isa => "Str"
);
has "attrs" =>
(
is => "rw",
isa => "HashRef[Str]"
);
has "subNodes" =>
(
is => "rw",
isa => "ArrayRef[Node]",
default => sub { [] }
);
sub subNode
{
my ($self, $name) = @_;
my $subNodeRef = $self->subNodes;
my @matchingSubnodes = grep { $_->getName eq $name } @$subNodeRef;
if (scalar(@matchingSubnodes) == 1)
{
return $matchingSubnodes[0];
}
return undef;
}
1;
在“end_element”子中,我检查这是否是我关心的节点,如果是,我会做一些进一步的处理。
这在我的测试文件上一切正常,但前天我把它扔到了我的真实文件中,全部 1300 万行,而且它需要永远。它已经运行了超过 36 个小时。我如何判断瓶颈是 Moose 还是 XML::SAX?驼鹿总是这么慢,还是我用错了?
更新 对 20,000 行数据子集进行分析表明,瓶颈是 Moose - 特别是在 Class::MOP::Class::compute_all_applicable_attributes (13.9%) 和其他 Class 和 Moose 类中。
最佳答案
虽然 Moose 在启动时做了很多工作,有时会显得有点慢,但它生成的代码,尤其是属性的访问器之类的东西,通常比普通 perl 程序员能够编写的要快得多。因此,考虑到您的流程的运行时间很长,我怀疑 Moose 引起的任何开销是否相关。
但是,从您展示的代码中,我无法确定您的瓶颈是什么,尽管我坚信它不是 Moose。我还想指出,做__PACKAGE__->meta->make_immutable
, 声明你的类(class)现在已经“完成”允许 Moose 做一些进一步的优化,但我仍然怀疑这就是给你带来麻烦的原因。
您如何取较小的数据样本,以便您的程序在合理的时间内完成,然后在分析器(例如 Devel::NYTProf
)中查看该数据。 .这将能够告诉您程序中的时间究竟花在哪里,因此您可以专门优化这些部分以获得最大可能的 yield 。
一种可能性是您使用的类型约束使事情变慢了很多。实际上,在对它们的每次写访问(或在类实例化)上彻底验证实例属性,并不是大多数程序员通常会做的事情。您可以尝试使用更简单的约束,例如 ArrayRef
而不是 ArrayRef[Node]
,如果您对数据的有效性有足够的把握。这样,只会检查属性值本身的类型,而不是该数组引用中每个元素的值。
但是,仍然要分析您的代码。别猜了。
关于perl - 为什么 Moose 代码这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3915062/