Swift vs Java - 加速大阵列的速度

时间:2014-06-12 21:20:54

标签: java arrays performance swift

我刚刚在填充大数组时对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


爪哇

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");

结果:时间:3毫秒


这让我感到震惊;

  • 比Java快了550倍?或者我使用的是一些未经优化的代码?

3 个答案:

答案 0 :(得分:32)

你正在比较苹果和梨..

两种实现之间存在根本区别。

您的 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
}

答案 1 :(得分:8)

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

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

另外,JIT编译器可能刚刚决定你的循环没用,并优化了整个过程。

答案 2 :(得分:1)

我意识到这已经很老了,但我随机遇到了它而DuckDucking因为一些无关的东西,我想我会提供一些......更新。

首先,现在Swift中的语法与FilipRoséen的回答完全不同。例如,没有更多C风格的循环。在编译器上也做了一些工作。

就像之前的答案解释一样,您正在比较两种不同的东西(增长数组与初始化数组)。但是,由于各种变化,Swift现在大大快了。

请原谅我的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")

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

爪哇:

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
显然,Swift的性能行为与2018年相比在几年前有很大差异。