【问题标题】:Swift vs Java - speed at filling big arraySwift vs Java - 填充大数组的速度
【发布时间】:2014-08-03 08:27:41
【问题描述】:

我只是在填充一个大数组时对 Java 和 Swift 进行了一个小的速度比较。 我想出了以下结果:


斯威夫特

import Foundation

let start = CFAbsoluteTimeGetCurrent()
var intArray = Int[]()
for var i = 0; i <= 300000; ++i {
    intArray.append(0)
}
let timeTaken = CFAbsoluteTimeGetCurrent() - start
println(timeTaken)

结果:1​​.66182696819305


Java

long start = System.currentTimeMillis();
int[] intArray;
int i = 0;
intArray = new int[300000];
for (i = 0; i < 300000; i++) {
    intArray[i]=0;
}
System.out.println("Time: "+(System.currentTimeMillis()-start)+"ms");

结果:时间:3ms


这让我有点震惊;

  • Swift 比 Java 慢 550 倍。还是我使用了一些未优化的代码?

【问题讨论】:

  • 我会非常警惕您的 Java 代码,因为我不认为 JIT 编译器优化整个循环是不合理的,因为您不使用它做任何事情。此外,我怀疑 Swift append() 方法需要做一些额外的幕后工作来将另一个元素添加到数组中,但由于我不太了解这种语言,所以我不能说当然。此外,这两个 sn-ps 并不完全等效,因为您没有在 Java 代码中附加任何内容。我肯定不会称这是一个公平的比较。
  • 我同意这一点。听起来很像 append 函数在恒定时间内执行,因为没有索引,在 java 代码中时间是线性的。
  • @IvayloToskov 我认为这并不完全正确,因为在 Java 中设置数组元素是常数时间。 append() 在恒定时间内执行的唯一方法是如果 intArray 是一个链表,那绝对不是这样。
  • 这两个程序不是等价的。你的结论无效。
  • 对这个错误的结论有点困惑!= 不好的问题。

标签: java arrays performance swift


【解决方案1】:

你在比较苹果和梨..

您的两个实现之间存在根本区别。

您的 java 实现将一次性为所有 300 000 元素分配内存,然后设置每个元素的值。

swift 实现将可能每次迭代中调整底层存储的大小,因为您正在附加一个元素,而不仅仅是将其存储在特定位置。很可能每次迭代都不会发生旧存储的调整大小+副本,但这是有可能的;而且它肯定会在你的循环中发生不止一次。


我该如何解决?

要修复 swift 实现,您应该使用 array-initializer 在创建 intArray 时直接分配所需的存储空间,如下例所示:

var intArray = Int[](count: 300000, repeatedValue: 0)
for var i = 0; i <= 300000; ++i {
    intArray[i] = 0
}

【讨论】:

  • 使用 How would I fix it? 部分,这个答案可能应该被标记为接受的答案。
  • 即使你一次性分配了 Swift 数组,我仍然会警惕 Java 代码,因为 JIT 编译器可能会优化。
  • 谢谢你——正是我想要的!
  • 您确实可以禁用 JIT 编译器,但您不会真正得到有效的 Swift 与 Java 比较,因为谁在生产 Java 机器上禁用了 JIT 编译器?
  • 但如果目标是将数组中的每个对象初始化为特定值,swift 使用单行语句来完成。代码 sn -p 中的循环是没有意义的。
【解决方案2】:

append 在运行时调整数组的大小(每个循环!!),而您的 Java 代码创建一个大小为 300000 的数组并在其中设置元素。

调整大小意味着内存复制操作,而在您的 Java 代码中设置索引是常数时间。

另外,JIT 编译器可能刚刚确定您的循环是无用的,并优化了整个事情。

【讨论】:

  • 我们确定每个循环都会调整数组的大小吗?我认为append 的大多数实现只会在需要时调整大小,当它确实调整大小时,它会将当前大小翻倍。
  • 明白,感谢重播。是否有可能创建一个固定大小的数组,并像在 java 代码中一样添加项目?我尝试了“intArray.insert(0, atIndex: i)”,结果更糟。
  • 你可以使用这个 var array = Int[](count: 300000, repeatValue: 0) 从一开始就为你分配足够的空间。
  • @El_Chippo 你不想insert,那更糟!你只需要一个简单的任务:intArray[i] = 0。我实际上建议在两个程序中将其更改为intArray[i] = i,这样循环就不会被优化掉。
【解决方案3】:

我意识到这已经很老了,但我在 DuckDucking 时偶然发现了它,我想我会提供一些……更新。

首先,现在 Swift 中的语法与 Filip Roséen 回答时的语法大不相同。例如,不再有 C 风格的循环。在编译器上也做了一些工作。

就像前面的答案解释的那样,您正在比较两个不同的事物(增长数组与初始化数组)。然而,由于各种变化,Swift 现在比以前快得多了。

如果我的 Java 代码不是最理想的,请原谅;这几乎是我第一次编写 Java。

这是我用来动态增长数组的代码:

Java:

import java.util.List;
import java.util.ArrayList;

public class java_GrowArray {
    public static void main(String[] args) {
        long start = System.nanoTime();

        List<Integer> intArray = new ArrayList<Integer>();

        for (int i = 0; i < 300000; i++) {
            intArray.add(0);
        }
        System.out.println("Time: "+(float)(System.nanoTime()-start)/1000000000 +" s");

    }
}

斯威夫特:

import Foundation

let start = CFAbsoluteTimeGetCurrent()

var intArray: [Int] = []
for _ in 0..<300000 {
    intArray.append(0)
}
let timeTaken = CFAbsoluteTimeGetCurrent() - start
print("Time: \(timeTaken) s")

下面是初始化固定大小数组的代码:

Java:

public class java_InitialiseArray {
    public static void main(String[] args) {
        long start = System.nanoTime();
        int[] intArray;
        int i = 0;
        intArray = new int[300000];
        for (i = 0; i < 300000; i++) {
            intArray[i]=0;
        }
        System.out.println("Time: "+(float)(System.nanoTime()-start)/1000000000 +" s");

    }
}

斯威夫特:

import Foundation

let start = CFAbsoluteTimeGetCurrent()
let intArray = [Int](repeating: 0, count: 300000)
let timeTaken = CFAbsoluteTimeGetCurrent() - start
print("Time: \(timeTaken) s")

时间(每次运行五次的中位数):

Grow array (Java):  0.01376 s
Grow array (Swift): 0.01035 s
Init array (Java):  0.00448 s
Init array (Swift): 0.00181 s

显然,2018 年 Swift 的性能行为与几年前相比有很大不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-14
    相关资源
    最近更新 更多