【问题标题】:Why use Lists, when Arrays are faster?当数组更快时,为什么要使用列表?
【发布时间】:2016-08-24 15:53:47
【问题描述】:

我注意到数组的执行速度比 Haxe 的链接列表快得多(至少在 cpp 上)。我得到的结果如下。

Main.hx:40: With 1 items, Array is 14% faster than List.
Main.hx:40: With 5 items, Array is 58% faster than List.
Main.hx:40: With 10 items, Array is 59% faster than List.
Main.hx:40: With 100 items, Array is 54% faster than List.
Main.hx:40: With 1000 items, Array is 56% faster than List.
Main.hx:40: With 10000 items, Array is 55% faster than List.
Main.hx:40: With 100000 items, Array is 52% faster than List.

这让我感到眼花缭乱。即使必须连续复制项目,Array 怎么能这么快?那为什么还要使用列表呢?

package tests;

import haxe.Timer;

class Main 
{

    static function main() 
    {
        var arr:Array<Int> = new Array();
        var list:List<Int> = new List();
        var result = new List();

        for (items in [1, 5, 10, 100, 1000, 10000, 100000]) {
            var listtime = timeit(10000, function() {
                for (i in 0...items)
                    list.add(i);
                for (x in list)
                    result.add(x);
                result.clear();
                list = new List();
            });

            var arrtime = timeit(10000, function() {
                for (i in 0...items)
                    arr.push(i);
                for (x in arr)
                    result.add(x);
                result.clear();
                arr = new Array();
            });

            if (arrtime < listtime)
                trace('With $items items, Array is ${Std.int((1-arrtime/listtime)*100)}% faster than List.');
            else
                trace('With $items items, List is ${Std.int((1-listtime/arrtime)*100)}% faster than Array.');
        }
    }

    static public function timeit<T>(times:Int, f:Void -> T):Float {
        var start = Timer.stamp();
        for (i in 0...times) {
            f();
        }
        var time = Timer.stamp() - start;
        return time;
    }

}

【问题讨论】:

  • 另外,如果你看看列表是如何在 haxe 中实现的,它们会出于任何原因创建一堆迷你数组,并向每个数组添加 2 个元素,这自然比仅仅添加到数组要慢。

标签: arrays performance list haxe


【解决方案1】:

Array 怎么能这么快,即使它必须连续复制项目?

数组的线性处理速度更快,因为数组内容连续存储在内存中。当您线性访问内存时,多个对象同时被提取到处理器缓存中。另一方面,链表节点分散在整个内存中,因此对它们进行线性处理会导致在主内存中访问更多。读取缓存比读取主内存要快得多。

那为什么还要使用列表呢?

使用链表的一个主要原因是,插入新元素或删除现有元素不会使对链表中其他元素的引用(包括迭代器和指针)无效。数组不能有这样的保证。

【讨论】:

  • 选择这个作为接受,因为它有更多的信息。
【解决方案2】:

当数组更快时,为什么要使用列表?

更快是为了什么?当在其他元素之间插入元素或删除列表中间的元素时,链表通常要快得多。在位置i 插入或删除数组(至少是C 样式数组)需要移动i 之后的每个元素。使用链表,您只需要更改几个指针。

再次尝试您的测试,但不要将元素推到列表的末尾,而是将它们插入到开头。

【讨论】:

  • 嗯,我明白了。不知道为什么我没想到。
  • 对于您的“在开头插入”示例,std::deque 会比列表更快,所以我认为它本身不能很好地证明使用列表的合理性。
  • @user2079303 你没抓住重点,不同的数据结构有不同的优缺点。我说 在开头插入它们 因为在 OP 测试的上下文中,这是一个简单的更改,它显示了列表比数组快的情况。
  • @Caleb 你错过了我评论的重点,即被问到的问题是“为什么使用列表(当数组更快时)?”在一个上下文中列表比数组快只是在该上下文中不使用数组的一个论据。如果没有比列表更好的替代方案的用例,那么永远不要使用列表。我承认你的例子确实很好地指出了导致 Seeq 发布问题的错误推理。
【解决方案3】:

有一篇文章广泛讨论了这个问题:

https://github.com/delahee/haxe.opt/blob/master/list_vs_array.md

TLDR :这取决于您的用例,但列表在某些情况下肯定会更快。

【讨论】:

    猜你喜欢
    • 2015-06-29
    • 2014-10-12
    • 2015-01-02
    • 2019-03-07
    • 1970-01-01
    • 2015-10-14
    • 2016-05-15
    相关资源
    最近更新 更多