为什么Moose代码这么慢?

时间:2010-10-12 13:14:42

标签: perl sax moose

我正在尝试解析一个大型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是否是瓶颈?麋总是这么慢,还是我错了?

更新对数据的20,000行子集进行配置文件显示Moose是瓶颈 - 特别是在Class :: MOP :: Class :: compute_all_applicable_attributes(13.9%)和其他类中和穆斯班。

3 个答案:

答案 0 :(得分:22)

虽然Moose在启动时做了相当多的工作,有时会让它看起来有点慢,但是它生成的代码,特别是属性的访问器等,通常比普通的perl程序员能够快得多。写。因此,鉴于您的过程的运行时间很长,我怀疑Moose引起的任何开销都是相关的。

但是,从您展示的代码中,我无法确定您的瓶颈是什么,即使我坚信它不是Moose。我还想指出,做__PACKAGE__->meta->make_immutable,说你上课现在已经“最终确定”允许Moose做一些进一步的优化,但我仍然怀疑这是导致你麻烦的原因。

如果您采用较小的数据样本,那么您的程序将在合理的时间内完成,并在Devel::NYTProf等分析器中查看。这将能够告诉您程序中的确切时间花在哪里,因此您可以专门优化这些部分以获得最大的收益。

一种可能性是你使用的类型限制减慢了很多。实际上,在对它们的每次写入访问(或类实例化)上彻底验证实例属性并不是大多数程序员通常会做的事情。如果您对数据的有效性有足够的肯定,则可以尝试使用更简单的约束,例如ArrayRef而不是ArrayRef[Node]。这样,只会检查属性值本身的类型,而不是该数组引用中每个元素的值。

但是,仍然可以描述您的代码。不要猜。

答案 1 :(得分:7)

我非常怀疑你的速度问题不是在Moose中,而是在内存分配和磁盘交换方面。即使没有做 - > gt> meta-> make_immutable,根据您的20K子集的时间,您的脚本应该在大约2小时内完成(((11 *(13_000_000 / 20_000))/ 60)== ~119分钟。通过执行 - > meta-> make_immutable,它会将其降低到大约。 65分钟左右。

再次尝试运行你的大脚本,看看你的内存和交换正在做什么,我怀疑你给你的磁盘带来了可怕的颠簸。

答案 2 :(得分:2)

我已经使用XML::Twig 745mb文件成功编写了大型XML处理应用程序,在一个合理大小的盒子上运行时间不到一小时。

但正如其他用户已经提到的那样,您需要对代码进行分析,以确定导致问题的确切原因。