我正在尝试解析大型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;

在“end_element”子节点中,我检查这是否是我关心的节点,如果是,则进行一些进一步的处理。

所有这些在我的测试文件上都可以正常工作,但是前天我把它扔到了我的真实文件中,所有的1300万行都花在了我的身上,而且这是永远的。它已经运行了36个多小时。如何判断是Moose还是XML::SAX成为瓶颈?是Moose总是这么慢,还是我用错了?

更新对数据的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/

10-12 17:47