【问题标题】:C# Performance with collections and iterators集合和迭代器的 C# 性能
【发布时间】:2019-08-22 14:52:20
【问题描述】:

您能否解释一下示例 1 中采用的方法在性能上是否与示例 2 中的方法不同?如果是,哪一种最有效,为什么。

我所说的“性能”不仅与执行速度有关。我还想要一些关于不同系统资源使用的解释。

1.

    private IEnumerable<string> GetObjectsStrings(List<object> input)
    {
        IList<string> result = new List<string>();

        foreach (var item in input)
        {
            result.Add(item.ToString());
        }

        return result;
    }

2.

    private IEnumerable<string> GetObjectsStrings(List<object> input)
    {
        foreach (var item in input)
        {
            yield return item.ToString();
        }
    }

【问题讨论】:

  • 如果你想要更好的性能,你可能想要使用数组,但我相信这些都是一样的。创建一个测试套件,将在同一对象上执行的函数计时几千次。这会告诉你哪个跑得更快。
  • 为什么不简单地通过测量来尝试一下?
  • 我不想要更好的性能,我不是要求这个真实的案例场景。只是想知道我展示的第二种方法是否真的避免了可能由创建辅助数据结构引起的开销。
  • 我只是在搜索我要求“速度性能”的地方。通过将事情做得“更好”而不是更快,某些事情可以比其他事情表现得更好。

标签: c# .net performance oop iterator


【解决方案1】:

他们做的事情不同,所以肯定会有不同。

第一个是创建一个新列表,其中包含现有列表中项目的ToString 版本,然后返回该新列表。

第二个是迭代现有的 List,并返回 ToString 版本,而不制作任何副本。

2 是最有效的(就速度和内存使用而言),因为没有创建新列表或复制任何内容。

【讨论】:

  • 所以,这种方法的唯一优点是我不必在我的方法中创建对象来保存我正在处理的数据的副本,对吧?
  • 这不是唯一的优势,但我认为真正的问题是,你在做什么?这两个功能是“不同的”。输出可能是相同的,但它们是不同的。
  • 这正是我想问的。我看到这两个函数产生相同的输出(显然,给定相同的输入)。我想请这个主题的一些“专家”来解释为什么第二种方法在低级别进行内存优化,因为我没有自己找到这些信息并正确理解它的技能。
【解决方案2】:

在场景 1 中,您正在处理整个列表,然后通过 IEnumerable 接口返回该列表。无论调用者打算如何处理返回的IEnumerable,每次调用GetObjectsStrings 时都会处理整个列表。

在场景 2 中,您只处理来自input 列表的条目,其数量与调用者所需的一样多。所以,你正在创建一个迭代器。

这里有一个例子,它会有所作为:

var temp = GetObjectsStrings(input).First();

场景 1:您每次都为每个此类呼叫完全处理 input。 场景 2:您只处理 input 中的第一项。至此,迭代完成。

【讨论】:

  • 注意,如果使用 LINQ Select,也只会处理 1 个元素
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-26
  • 1970-01-01
相关资源
最近更新 更多