2010-11-09 5 views
1

C'est niché sur 10 fonctions profondes, donc je vais juste coller les bits correspondants:Pourquoi ce code d'itération sur le DOM est-il lent?

Cette ligne est très lent:

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

Plus précisément, ce morceau à l'intérieur Filter_Chunk (jeu de mots) n'a pas pour but:

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; 

Il n'y a rien de trop compliqué là-dedans ... donc je pense que ça doit être le nombre de nœuds en Traverse() non?

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); 
} 

J'ai essayé de trouver <h3> nœuds sur stackoverflow.com. Il ne devrait pas y avoir plus de quelques milliers de nœuds, devrait-il y en avoir? Pourquoi cela prend-il plusieurs minutes à compléter?


En fait, il y a certainement un bug ici quelque part qui est à l'origine de revenir plus de nœuds que prévu ... I forked the question to address the issue

+1

duplication possible de [C# Performance du rendement imbriqué dans un arbre] (http://stackoverflow.com/questions/1043050/c-performance-of-nested-yield-in-a-tree) –

+0

Je ne peux pas vous donner toute sorte de réponse spécifique, mais je peux vous diriger vers un article intéressant sur Joelonsoftware.com Vers le bas Joel parle de la performance de l'utilisation de XML pour les grands ensembles de données. http://www.joelonsoftware.com/articles/fog0000000319.html –

+0

Juste une supposition: essayez d'utiliser une liste au lieu de IEnumerable/yield et dites-nous si cela aide. La raison de votre problème peut être le surcoût de la machine d'état que le compilateur construit en interne pour les indexeurs lors de l'utilisation de yield. –

Répondre

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

Ce code semble étrange pour moi. Children() est indépendant pour _context, donc cela n'a aucun sens d'écraser les enfants une fois pour chaque noeud dans _context.

+0

Vous avez raison. J'essayais de réutiliser une fonction que j'avais déjà. Acceptera de fermer la question :) – mpen

Questions connexes