循环排序列表 - 为什么这样更快?

发布于 2024-08-09 04:03:13 字数 830 浏览 7 评论 0原文

以下示例中的 List1 是 SortedList(Of MyClass),包含 251 个成员。

前两个代码块在 15.5 秒内执行。

 For cnt As Integer = 1 To 1000000
        For Each TempDE In List1
            Dim F As String = TempDE.Key
            TempDE.Value.x1 = 444
        Next
    Next

 

    For cnt As Integer = 1 To 1000000
        For Each TempDE As KeyValuePair(Of String, phatob) In List2
            Dim F As String = TempDE.Key
            TempDE.Value.x1 = 444
        Next
    Next

这个执行时间为 5.6 秒。

    For cnt As Integer = 0 To 999999
        For cnt2 As Integer = 0 To 250
            Dim F As String = List1.Keys(cnt2)
            List1.Values(cnt2).x1 = 444
        Next

    Next

为什么前两个代码块慢得多?

List1 in the following example is a SortedList(Of MyClass) and contains 251 members.

The first two codeblocks execute in 15.5 seconds.

 For cnt As Integer = 1 To 1000000
        For Each TempDE In List1
            Dim F As String = TempDE.Key
            TempDE.Value.x1 = 444
        Next
    Next

 

    For cnt As Integer = 1 To 1000000
        For Each TempDE As KeyValuePair(Of String, phatob) In List2
            Dim F As String = TempDE.Key
            TempDE.Value.x1 = 444
        Next
    Next

This one executes in 5.6 seconds.

    For cnt As Integer = 0 To 999999
        For cnt2 As Integer = 0 To 250
            Dim F As String = List1.Keys(cnt2)
            List1.Values(cnt2).x1 = 444
        Next

    Next

Why are the first two codeblocks so much slower?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

迷爱 2024-08-16 04:03:13

SortedList 通过实现 IComparer 来扩展 Collection,以提供排序功能。在内部,它实现了 2 个数组来存储列表的元素 - 一个用于键的数组,一个用于值的数组。 .NET 数组针对快速有序和快速随机访问进行了优化。

我怀疑前两个语句速度慢的原因是 SortedList 中的 foreach 语句是 Enumerator 的包装器。调用 foreach 将查询枚举器,调用 MoveNext 和 Current。此外,在遍历列表时,遍历通用列表可能会涉及装箱和拆箱,并且可能会产生通常通过索引访问不会获得的性能开销。

The SortedList extends a Collection by implementing IComparer to provide the sort functionality. Internally, it implements 2 arrays to store the elements of the list - one array for the key and one for the values. The .NET Array is optimised for fast in-order and fast random access.

My suspicion why the first 2 are slow is because the foreach statement in a SortedList is a wrapper around the Enumerator. Calling foreach will query for the enumerator, call MoveNext and Current. In addition, going though the generic list can potentially involve boxing and unboxing as you traverse the list, and can create performance overhead that you would not normally get by accessing by Index.

记忆消瘦 2024-08-16 04:03:13

我试图四处寻找一些关于 For Each 行为的文档,但我找不到它。

我的理论是,使用 For Each 语句将列表中的对象复制到内存中的另一个位置,然后在循环的每次迭代结束时将其复制回列表中。

另一种可能性是,它在每次迭代开始时调用构造函数,然后解构并再次调用构造函数以重置下一次迭代。

我不确定这些理论中的任何一个,但 3 和(1 或 2)之间的主要区别是缺少 For Each

编辑:在 MSDN 找到一些文档。

这是摘录:

当开始执行 For Each...Next 循环时,Visual Basic 将验证该组是否引用了有效的集合对象。如果不是,它会抛出异常。否则,它调用 MoveNext 方法和枚举器对象的 Current 属性来返回第一个元素。如果 MoveNext 指示没有下一个元素,即集合为空,则 For Each 循环终止,控制权传递到 Next 语句后面的语句。否则,Visual Basic 将 element 设置为第一个元素并运行语句块。

因此,总体而言,听起来 For Each 更加“受管理”,并且花费了大量开销来确保一切都匹配。结果,速度变慢了。

I tried to look around for some documentation on exactly how For Each behaves, but I couldn't find it.

My theory is that using the For Each statements copies the object in the list to another spot in memory and then copies it back into the list when each iteration of the loop ends.

Another possibility is that it calls the constructor at the start of every iteration and then deconstructs and calls the constructor again to reset for the next iteration.

I'm not sure on either of these theories, but the major difference between 3 and (1 or 2) is the lack of For Each.

EDIT: Found some documentation at MSDN.

Here's an excerpt:

When execution of the For Each...Next loop begins, Visual Basic verifies that group refers to a valid collection object. If not, it throws an exception. Otherwise, it calls the MoveNext method and the Current property of the enumerator object to return the first element. If MoveNext indicates that there is no next element, that is, if the collection is empty, then the For Each loop terminates and control passes to the statement following the Next statement. Otherwise, Visual Basic sets element to the first element and runs the statement block.

So overall it sounds like For Each is more "managed" and does a lot of overhead to make sure everything matches up. As a result, it's slower.

月光色 2024-08-16 04:03:13

我认为由于固定的循环范围,编译器可以更好地优化块 3。在块 1 和 2 中,编译器在评估 List 之前不会知道循环的上限是什么,从而使其变慢。

I would think the compiler can better optimize block 3 because of the fixed loop range. In blocks one and 2 the compiler won't know what the upper limit of the loop is until it evaluates the List thus making it slower.

素衣风尘叹 2024-08-16 04:03:13

我的随机猜测:
List1 包含约 750 个元素(而不仅仅是 250 个)。
第三种情况更快,因为它不会迭代 List1 具有的每个元素。

My random guess:
List1 contains ~750 elements (and not just 250).
Your third case is faster, because it does not iterate over each element which List1 has.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文