2008-10-31 5 views
7

Я чувствую, что использование GetEnumerator() и литье IEnumerator.Current дорого. Любые лучшие предложения?

Я открыт для использования другой структуры данных, если он предлагает аналогичные возможности с лучшей производительностью.Самый быстрый способ перебора стека в C#

После мысли:
ли общий стек быть лучшей идеей, так что бросок не нужен?

+0

Все они будут одинаковыми ... при использовании valuetypes литье немного медленнее. В зависимости от использования, я сомневаюсь, что это сильно повлияет на производительность. – leppie 2008-10-31 09:12:22

ответ

6

Вы сделали какие-либо критерии, или они просто чувства кишки?

Если вы считаете, что большая часть времени обработки тратится на выполнение стеков, вам следует сравнить его и убедиться, что это так. Если это так, у вас есть несколько вариантов.

  1. Редизайн код так, что зацикливание не нужно
  2. Найти быстрее создания циклов. (Я бы порекомендовал дженерики, хотя это не имело бы большого значения. Опять же, делайте тесты).

EDIT:

Примеры зацикливания, которые не могут быть необходимы, когда вы попытаетесь сделать Lookups в списке или совпадают два списка или аналогичными. Если цикл занимает много времени, посмотрите, имеет ли смысл вносить списки в бинарные деревья или хеш-карты. Первоначальная стоимость их создания может быть начата, но если код будет переработан, вы можете получить это обратно, получив O (1) поисковые запросы позже.

+0

Да, сейчас это просто чувство. Я проведу бенчмаркинг и посмотрю. спасибо – 2008-10-31 10:17:16

5

Да, используя общий стек, вы сэкономите литье.

3

Если вам нужна функциональность стека (в виде списка или другого типа коллективизации), то да, используйте общий стек. Это немного ускорит работу, так как компилятор пропустит кастинг во время выполнения (потому что он включен во время компиляции).

Stack<MyClass> stacky = new Stack<MyClass>(); 

foreach (MyClass item in stacky) 
{ 
    // this is as fast as you're going to get. 
} 
2

перечисляя над общим IEnumerable<T> или IEnumerator<T> не не создает слепок, если итерация переменная типа T, так что да, используя родовое будет быстрее в большинстве случаев, но есть некоторые дженерики очень тонкие проблемы, особенно при использовании со значениями типов.

Rico Mariani (производительность архитектор Microsoft) имеет некоторые сообщения, детализирующие различия и подоплеку

0

Альтернативой созданию перечислителя является использование метода ToArray, а затем итерация по массиву. Итератор стека вызывает некоторые незначительные накладные расходы для проверки того, был ли стек изменен, тогда как итерация по массиву будет быстрой. Однако, конечно, накладные расходы на создание массива в первую очередь. Как говорят маты, вам следует сравнить альтернативы.

+0

Использование «ToArray» очень дорого ... у вас будет огромная потеря производительности, создающая новый объект, прежде чем вы даже начнете его повторять. – 2008-10-31 10:36:33

13

Stack<T> (с foreach) действительно сохранит бросок, но на самом деле бокс isn't all that bad в великой схеме вещей. Если у вас проблемы с производительностью, я сомневаюсь, что это та область, где вы можете добавить большую ценность.Используйте профилировщик и сосредоточьтесь на реальных проблемах - иначе это преждевременно.

Обратите внимание, что если вы хотите только один раз прочитать данные (то есть, вы счастливы использовать стек), то этот может быть быстрее (избегает накладных расходов перечислителя); YMMV.

Stack<T> stack = null; 
    while (stack.Count > 0) 
    { 
     T value = stack.Pop(); 
     // process value 
    } 
1

Что касается скорости, то существует несколько переменных, зависящих от контекста. Например, в кодовой базе, управляемой с помощью автоматической памяти, такой как C#, вы можете получить всплески распределения, которые могут повлиять на частоту кадров в чем-то вроде игры. Хорошая оптимизация вы можете сделать для этого вместо Еогеаспа является нумератор с временем циклом:

var enumerator = stack.GetEnumerator(); 

while(enumerator.MoveNext()) { 
    // do stuff with enumerator value using enumerator.Current 
    enumerator.Current = blah 
} 

Что касается тестов процессора, это, вероятно, не быстрее, чем Еогеасп, но Еогеасп может иметь непреднамеренное распределение шипы, которые могут в конечном счете «замедлить» производительность вашего приложения.