2010-11-09 164 views
1

这是嵌套约10种功能深,所以我就粘贴相关位:为什么这个迭代DOM愚蠢的代码很慢?

这一行实在是太慢了:

var nodes = Filter_Chunk(Traverse(), chunks.First()); 

具体而言,该块内Filter_Chunk(双关语不打算):

private static IEnumerable<HtmlNode> Filter_Chunk(IEnumerable<HtmlNode> nodes, string selectorChunk) 
{ 
    // ... 
    string tagName = selectorChunk; 
    foreach (var node in nodes) 
     if (node.Name == tagName) 
      yield return node; 

没有什么在那里太复杂了......所以我想它一定是在Traverse()右节点的数量之多?

public IEnumerable<HtmlNode> Traverse() 
{ 
    foreach (var node in _context) 
    { 
     yield return node; 
     foreach (var child in Children().Traverse()) 
      yield return child; 
    } 
} 

public SharpQuery Children() 
{ 
    return new SharpQuery(_context.SelectMany(n => n.ChildNodes).Where(n => n.NodeType == HtmlNodeType.Element), this); 
} 

我试过stackoverflow.com发现<h3>节点。不应该有超过几千个节点,应该在那里吗?为什么这需要很多分钟才能完成?


其实,有肯定在这里的某个地方一个错误,导致它比它应返回多个节点... I forked the question to address the issue

+1

[C#在树中嵌套良率的性能]可能的重复(http://stackoverflow.com/questions/1043050/c-performance-of-nested-yield-in-a-tree) – 2010-11-09 20:49:07

+0

我不能给你任何特定的答案,但是我可以给你一个关于Joelonsoftware.com的有趣的文章。在底部附近Joel谈论了在大型数据集中使用XML的性能问题。 http://www.joelonsoftware.com/articles/fog0000000319.html – 2010-11-09 20:51:15

+0

只是一个猜测:尝试使用列表而不是IEnumerable/yield并告诉我们是否有帮助。您的问题的原因可能是编译器在使用yield时在内部为索引器构建的状态机的开销。 – 2010-11-09 21:01:08

回答

2
public IEnumerable<HtmlNode> Traverse() 
{ 
    foreach (var node in _context) 
    { 
     yield return node; 
     foreach (var child in Children().Traverse()) 
      yield return child; 
    } 
} 

这段代码看起来很奇怪我。 Children()对于_context是独立的,所以对_context中的每个节点运行一次儿童是没有意义的。

+0

你说得对。我试图重新使用我已有的功能。将接受关闭问题:) – mpen 2010-11-09 22:49:52