Swift vs Java-填充大数组的速度

Swift vs Java-填充大数组的速度,java,arrays,performance,swift,Java,Arrays,Performance,Swift,我只是在填充一个大数组时对Java和Swift进行了一个小的速度比较。 我得出了以下结果: 敏捷的 导入基础 let start=CFAbsoluteTimeGetCurrent() var intArray=Int[]() 对于var i=0;iappend在运行时调整数组的大小(每个循环!!),而Java代码创建一个大小为300000的数组,只在其中设置元素 调整大小意味着内存复制操作,而在Java代码中,设置索引是常数时间 而且,JIT编译器可能刚刚决定你的循环是无用的,并对整个过程进行

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


敏捷的 <代码>导入基础 let start=CFAbsoluteTimeGetCurrent() var intArray=Int[]()
对于var i=0;i
append
在运行时调整数组的大小(每个循环!!),而Java代码创建一个大小为300000的数组,只在其中设置元素

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

而且,JIT编译器可能刚刚决定你的循环是无用的,并对整个过程进行了优化。

你在比较苹果和梨。。 这两种实现之间有一个根本的区别

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

但是,swift实现可能会在每次迭代时调整基础存储的大小,因为您要追加元素,而不仅仅是将其存储在特定位置。最有可能的是,旧存储的resize+拷贝不会在每次迭代中都出现,但这是一种可能性;在循环过程中,它肯定会不止一次发生


我该怎么修? 要修复swift实施,您应使用在创建intArray时直接分配所需存储,如以下示例中所示:

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

对于var i=0;我我意识到这是很古老的,但我在躲避无关的东西时偶然发现了它,我想我会提供一些。。。更新

首先,Swift中的语法现在与菲利浦·罗塞恩(Filip Roséen)回答时大不相同。例如,不再有C样式的循环。在编译器上也做了一些工作

正如前面的答案所解释的,您正在比较两种不同的东西(增长数组和初始化数组)。然而,由于各种变化,Swift现在大大快于过去

请原谅我的Java代码,如果它是次优的;这几乎是我第一次编写Java

以下是我用来动态增长阵列的代码:

爪哇:

计时(每个中位数为五次):


显然,Swift在2018年的表现与几年前大不相同

我会非常小心您的Java代码,因为我不认为JIT编译器优化整个循环是不合理的,因为您不使用它。此外,我怀疑Swift
append()
方法有一些额外的幕后工作要做,以便将另一个元素添加到数组中,但由于我对该语言的了解程度不高,我不能肯定。此外,这两个代码段并不完全相同,因为您没有在Java代码中添加任何内容。我不能肯定这是一个公平的比较。我同意这一点。这听起来很像
append
函数是在一个恒定的时间内执行的,因为没有索引,在java代码中时间是线性的。@IvayloToskov我认为这不完全正确,因为在java中设置数组元素是恒定的时间。
append()
以固定时间执行的唯一方法是,如果
intArray
是一个链表,则情况绝对不是这样。这两个程序是不同的。你的结论是无效的。对这个错误结论的反对票有点困惑!=错误的问题。我们是否确定每个循环都调整了数组的大小?我认为大多数
append
的实现只会在需要时调整大小,当它调整大小时,它会将当前大小翻倍。明白了,谢谢您的重播。是否有可能创建一个固定大小的数组,并像java代码中那样添加项?我尝试了“intArray.insert(0,atIndex:I)”,但结果更糟。您可以使用这个var array=Int[](count:300000,repeatedValue:0)从一开始就为您分配足够的空间。@El_Chippo如果您不想
insert
,那会更糟!您只需要一个简单的赋值:
intArray[i]=0
。实际上,我建议在两个程序中都将其改为
intArray[I]=I
,这样循环就不会被优化了。我该如何修复它呢?第节,这个答案可能应该被标记为已接受的答案。即使您一次分配了所有Swift数组,我仍然会对Java代码保持警惕,因为JIT编译器可能会进行优化。谢谢-这正是我想要的!您确实可以禁用JIT编译器,但您不会真正获得有效的Swift与Java比较,因为谁在生产Java机器上禁用了JIT编译器?但是如果目标是将数组中的每个对象初始化为特定值,则使用单行语句来实现。代码段中的循环毫无意义。
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");
var intArray = Int[](count: 300000, repeatedValue: 0)
for var i = 0; i <= 300000; ++i {
    intArray[i] = 0
}
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