Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在c中迭代堆栈的最快方法#_C#_Optimization_Stack - Fatal编程技术网

C# 在c中迭代堆栈的最快方法#

C# 在c中迭代堆栈的最快方法#,c#,optimization,stack,C#,Optimization,Stack,我觉得使用GetEnumerator()和casting IEnumerator.Current很昂贵。有更好的建议吗? 如果数据结构提供类似的功能和更好的性能,我愿意使用不同的数据结构 思考之后: 通用堆栈是一个更好的主意,这样就不需要强制转换了吗?是的,使用通用堆栈可以避免强制转换。如果您需要堆栈的功能(与列表或其他集合类型类似),那么是的,使用通用堆栈。这将加快一些速度,因为编译器将在运行时跳过强制转换(因为它是在编译时安装的) Stack stacky=新堆栈(); foreach(st

我觉得使用GetEnumerator()和casting IEnumerator.Current很昂贵。有更好的建议吗?

如果数据结构提供类似的功能和更好的性能,我愿意使用不同的数据结构

思考之后:

通用堆栈是一个更好的主意,这样就不需要强制转换了吗?

是的,使用通用堆栈可以避免强制转换。

如果您需要堆栈的功能(与列表或其他集合类型类似),那么是的,使用通用堆栈。这将加快一些速度,因为编译器将在运行时跳过强制转换(因为它是在编译时安装的)

Stack stacky=新堆栈();
foreach(stacky中的MyClass项目)
{
//这是你能达到的最快速度。
}

在泛型
IEnumerable
IEnumerator
上枚举时,如果迭代变量的类型为t,则不会创建强制转换,因此在大多数情况下使用泛型会更快,但泛型有一些非常微妙的问题,特别是在与值类型一起使用时

Rico Mariani(Microsoft performance architect)在一些帖子中详细介绍了这些差异和基础


你做过任何基准测试吗,或者它们只是直觉

如果您认为大部分处理时间都花在堆栈循环上,那么您应该对其进行基准测试,并确保情况确实如此。如果是,你有几个选择

  • 重新设计代码,这样循环就没有必要了
  • 找到一个更快的循环构造。(我会推荐泛型,尽管这没什么大不了的。再说一次,做基准测试)
  • 编辑:


    当您尝试在一个列表中查找或匹配两个列表或类似列表时,可能不需要循环。如果循环需要很长时间,请查看将列表放入二叉树或哈希映射是否有意义。创建枚举数可能会有初始成本,但如果重新设计代码,您可能会在以后进行O(1)次查找以获得初始成本。

    创建枚举数的另一种方法是使用ToArray方法,然后在数组上迭代。堆栈迭代器在检查堆栈是否已被修改时会产生一些轻微的开销,而在数组上的迭代会很快。但是,首先当然会有创建数组的开销。正如mats所说,您应该对备选方案进行基准测试。

    Stack
    (使用foreach)确实可以拯救演员阵容,但实际上是在宏大的计划中发挥作用。如果您有性能问题,我怀疑这是您可以增加很多价值的领域。使用剖析器,关注实际问题——否则这还为时过早

    请注意,如果您只想读取一次数据(即,您很乐意使用堆栈),那么这可能会更快(避免枚举器的开销);YMMV

    Stack-Stack=null;
    而(stack.Count>0)
    {
    T值=stack.Pop();
    //过程值
    }
    
    就速度而言,有多个变量,取决于上下文。例如,在自动内存管理的代码库(如C#)中,您可以获得分配峰值,这可能会影响游戏中的帧速率。您可以为此而不是foreach进行的一个很好的优化是一个带有while循环的枚举器:

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

    就CPU基准而言,这可能并不比foreach快,但foreach可能会出现意外的分配峰值,这最终会“降低”应用程序的性能。

    它们都是一样的。。。使用valuetypes时,强制转换只会稍微慢一点。根据使用情况,我怀疑这会对性能有多大影响。是的,这只是一种感觉。我将运行一些基准测试并查看。感谢“ToArray”非常昂贵。。。创建新对象的方式甚至在您开始对其进行评估之前,您将面临巨大的性能损失。您确定它非常昂贵吗?你量过了吗?
        Stack<T> stack = null;
        while (stack.Count > 0)
        {
            T value = stack.Pop();
            // process value
        }
    
    var enumerator = stack.GetEnumerator();
    
    while(enumerator.MoveNext ()) {
      // do stuff with enumerator value using enumerator.Current
      enumerator.Current = blah
    }