我正在尝试解析一个大型XML文件.我使用XML :: SAX(使用Expat,而不是perl实现)读取它,并将所有第二级及以下节点放入我的"Node"类:
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;
Run Code Online (Sandbox Code Playgroud)
在"end_element"子中,我检查这是否是我关心的节点,如果是,我会做一些进一步的处理.
这一切都在我的测试文件上工作得很好,但是前天我把它扔到了我的真实文件中,所有这一切都是1300万行,并且它将永远消失.它已运行超过36小时.我如何判断Moose或XML :: SAX是否是瓶颈?麋总是这么慢,还是我错了?
更新在数据的20,000行子集上执行配置文件显示Moose是瓶颈 - 特别是在Class :: MOP :: Class :: compute_all_applicable_attributes(13.9%)以及其他Class和Moose类中.
raf*_*afl 22
虽然Moose在启动时做了很多工作,有时会让它看起来有点慢,但它生成的代码,尤其是属性的访问器等,通常比普通的perl程序员能够编写的速度快得多.因此,鉴于您的流程的运行时间很长,我怀疑Moose引起的任何开销都是相关的.
但是,从您展示的代码中,我无法确定您的瓶颈是什么,即使我坚信它不是Moose.我还想指出,做到__PACKAGE__->meta->make_immutable,说你上课现在已经"最终确定"允许穆斯做一些进一步的优化,但我仍然怀疑这是什么导致你的麻烦.
如果您采用较小的数据样本,那么您的程序将在合理的时间内完成,并在分析器中查看,例如Devel::NYTProf.这将能够告诉您程序中的确切时间花在哪里,因此您可以专门优化这些部分以获得最大的收益.
一种可能性是你使用的类型限制减慢了很多东西.实际上,在对它们的每一次写入访问(或类实例化)上彻底验证实例属性并不是大多数程序员通常会做的事情.你可以尝试使用简单的约束条件,如ArrayRef替代ArrayRef[Node],如果你对你的数据的有效性足够的肯定.这样,只会检查属性值本身的类型,而不是该数组引用中每个元素的值.
但是,仍然可以分析您的代码.不要猜.
小智 7
我非常怀疑你的速度问题不是在Moose中,而是在内存分配和磁盘交换方面.即使没有做 - > meta-> make_immutable,基于你的20K子集的时间,你的脚本应该在大约2小时内完成(((11*(13_000_000/20_000))/ 60)== ~119分钟.通过 - > meta-> make_immutable,它可以将其减少到大约.65分钟左右.
尝试再次运行你的大脚本,看看你的内存和交换正在做什么,我怀疑你给你的磁盘一个可怕的颠簸.