2014-01-21 2 views
5

Я смотрю на Roslyn September 2012 CTP с отражателем, и я заметил следующую глубину первого обход синтаксического дерева:Конкретного использования StrongBox

private IEnumerable<CommonSyntaxNode> DescendantNodesOnly(TextSpan span, 
    Func<CommonSyntaxNode, bool> descendIntoChildren, bool includeSelf) 
{ 
    if (includeSelf && IsInSpan(span, FullSpan)) 
    { 
     yield return this; 
    } 

    if ((descendIntoChildren != null) && !descendIntoChildren(this)) 
    { 
     yield break; 
    } 

    var queue = new Queue<StrongBox<IEnumerator<CommonSyntaxNode>>>(); 
    var stack = new Stack<StrongBox<IEnumerator<CommonSyntaxNode>>>(); 
    stack.Push(new StrongBox<IEnumerator<CommonSyntaxNode>>(ChildNodes().GetEnumerator())); 
    while (stack.Count > 0) 
    { 
     var enumerator = stack.Peek(); 
     StrongBox<IEnumerator<CommonSyntaxNode>> childEnumerator; 
     if (enumerator.Value.MoveNext()) 
     { 
      var current = enumerator.Value.Current; 
      if (IsInSpan(span, current.FullSpan)) 
      { 
       yield return current; 

       if ((descendIntoChildren == null) || descendIntoChildren(current)) 
       { 
        childEnumerator = queue.Count == 0 
         ? new StrongBox<IEnumerator<CommonSyntaxNode>>() 
         : queue.Dequeue(); 
        childEnumerator.Value = current.ChildNodes().GetEnumerator(); 
        stack.Push(childEnumerator); 
       } 
      } 
     } 
     else 
     { 
      childEnumerator = stack.Pop(); 
      childEnumerator.Value = null; 
      queue.Enqueue(childEnumerator); 
     } 
    } 
} 

Я предполагаю, что очередь для облегчения выполнения от выделяя и освобождая так много экземпляров IEnumerator<CommonSyntaxNode>.

Однако я не уверен, почему IEnumerator<CommonSyntaxNode> завернут в StrongBox<>. Какие компромиссы производительности и безопасности связаны с упаковкой IEnumerator<CommonSyntaxNode>, которая обычно является типом значений, внутри ссылочного типа StrongBox<>?

ответ

0

Использование IEnumerator было ошибкой. Код должен был использовать ChildSyntaxList.Enumerator, который является структурой. Использование StrongBox для перфоманса, чтобы не нужно толкать &, поменяйте счетчики с конца стека, когда они меняются.

+0

Я не вижу, как использование StrongBox делает разницу, поскольку вам все равно нужно нажать и поместить каждый экземпляр StrongBox из конца стека, когда он изменится. – cubetwo1729

2

CommonSyntaxNode - класс абзаца, который содержит много типов значений и может быть унаследован в большой объект.

IEnumerator<CommonSyntaxNode> содержит только ссылку на CommonSyntaxNode так кажется, как размер CommonSyntaxNode не будет влиять на Enumerator размер, так как это только ссылка, но:

так IEnumerator<T> «ы метод MoveNext() использует yield return;, каждая итерация в Enumerator приведет к тому, что метод сохранит его состояние до следующей итерации.

, так как весь государственный метод достаточно тяжелый, и он может содержать CommonSyntaxNode «S свойства для того, чтобы сделать логику MoveNext(), чем вся IEnumerator<CommonSyntaxNode> может быть довольно тяжелым на памяти.

использованием StrongBox<> вызывает Queue или Stack занимают лишь небольшой опорный объект (StrongBox<> вместо того, чтобы потенциально тяжелый на память IEnumerator<CommonSyntaxNode> - поэтому - ГХ является очистка Queue или Stack, содержащихс IEnumerator<CommonSyntaxNode> из памяти потенциально быстрее -. уменьшая общее потребление памяти приложения

отмечают, чтоПеречислитель- это структура, работающая с ней напрямую, означает глубокое копирование всей структуры, это небольшая структура, поэтому она не очень тяжелая, но все же ...

2

Преимущество StrongBox<T> - это когда элемент удален, StrongBox очищает внутренний контент - поэтому GC может затем собрать экземпляр T, который удерживается StrongBox, а Queue<T> заканчивается тем, что содержит только экземпляр StrongBox (вместо экземпляра T).