gpt4 book ai didi

java - 使用 copyOfRange 拆分数组时奇怪的运行时间

转载 作者:行者123 更新时间:2023-12-01 09:47:06 26 4
gpt4 key购买 nike

我得到了一个逗号分隔的文件,其中包含 10 977 120 个随机数(60 MB),我已经得到了其中的总和。该任务是同时执行此操作,因此以尽可能快速的方式执行。长话短说,我将文本文件加载到字符串数组中。我的下一个想法是将该数组分成四个较小的部分,然后对于每个部分,有一个线程对该部分求和。

奇怪的是,当我将列表分成 4 部分时,我得到的运行时间非常不同。

我有一个如下所示的方法:

public void splitNumbers(String[] numbers){
int size = numbers.length;
String[][] numberssplit = new String[4][];
numberssplit[0] = Arrays.copyOfRange(numbers, 0, size/4);
numberssplit[1] = Arrays.copyOfRange(numbers, (size/4)+1, size/2);
numberssplit[2] = Arrays.copyOfRange(numbers, (size/2)+1, 3*(size/4));
numberssplit[3] = Arrays.copyOfRange(numbers, (3*(size/4))+1, size-1);
//MS: 2750
}

以上大约需要 2750 毫秒

numberssplit[0] = Arrays.copyOfRange(numbers, 0, size/4);
numberssplit[1] = Arrays.copyOfRange(numbers, (size/4)+1, size/2);
//numberssplit[2] = Arrays.copyOfRange(numbers, (size/2)+1, 3*(size/4));
//numberssplit[3] = Arrays.copyOfRange(numbers, (3*(size/4))+1, size-1);
MS: 5

但是,只分割两部分,需要 5 MS,看起来像是最后两部分花费的时间更长。

仅分割第三部分需要2毫秒

//numberssplit[0] = Arrays.copyOfRange(numbers, 0, size/4);
//numberssplit[1] = Arrays.copyOfRange(numbers, (size/4)+1, size/2);
numberssplit[2] = Arrays.copyOfRange(numbers, (size/2)+1, 3*(size/4));
//numberssplit[3] = Arrays.copyOfRange(numbers, (3*(size/4))+1, size-1);
//MS: 2

第四部分也是如此,因为它是唯一被分割的部分。

//numberssplit[0] = Arrays.copyOfRange(numbers, 0, size/4);
//numberssplit[1] = Arrays.copyOfRange(numbers, (size/4)+1, size/2);
//numberssplit[2] = Arrays.copyOfRange(numbers, (size/2)+1, 3*(size/4));
numberssplit[3] = Arrays.copyOfRange(numbers, (3*(size/4))+1, size-1);
//MS: 2

最后,最后两个未注释的,需要 2927 毫秒

//numberssplit[0] = Arrays.copyOfRange(numbers, 0, size/4);
//numberssplit[1] = Arrays.copyOfRange(numbers, (size/4)+1, size/2);
numberssplit[2] = Arrays.copyOfRange(numbers, (size/2)+1, 3*(size/4));
numberssplit[3] = Arrays.copyOfRange(numbers, (3*(size/4))+1, size-1);
//MS: 2927

似乎将 numbersplit[2]numbersplit[3] 组合起来需要更长的时间,但这是为什么呢?显然java在幕后做了一些魔法,但我看不到逻辑。那么发生了什么?

最佳答案

简短回答:使用 -verbose:gc 运行您的项目,输出将为您提供完整的答案。

长答案:

我已经使用您的代码的第一 block 进行了测试。首先,您将失去这些范围内的一个数字:

(size/4)+1, size/2
(size/2)+1, 3*(size/4)

这里有两个数字:

(3*(size/4))+1, size-1

说明 here :

from - the initial index of the range to be copied, inclusive to - the final index of the range to be copied, exclusive

由于 Array.copyOfRange 的复杂度为 (O(n)),因此这四个部分之间不应该有任何时间差。但如果您看到类似的内容,则意味着内存分配导致了内存问题。

看看这个:

package testproject;

import java.util.Arrays;

public class TestProject {

public static void main(String[] args) {
String[] numbers = getNumbers(0, 10000000);

long timestamp = System.currentTimeMillis();
System.out.println("Starting split");
String[][] splitted = splitNumbers(numbers);
System.out.println(System.currentTimeMillis() - timestamp);

timestamp = System.currentTimeMillis();
System.out.println("Starting split");
splitted = splitNumbers(numbers);
System.out.println(System.currentTimeMillis() - timestamp);
}

public static String[] getNumbers(int from, int to){
String[] res = new String[to-from];
for(int i=0; i<(to-from); i++){
res[i] = Integer.toString(from + i);
}
return res;
}

public static String[][] splitNumbers(String[] numbers){
int size = numbers.length;
String[][] numberssplit = new String[4][];
numberssplit[0] = Arrays.copyOfRange(numbers, 0, size/4);
numberssplit[1] = Arrays.copyOfRange(numbers, (size/4), size/2);
numberssplit[2] = Arrays.copyOfRange(numbers, (size/2), 3*(size/4));
numberssplit[3] = Arrays.copyOfRange(numbers, (3*(size/4)), size);
return numberssplit;
}
}

这里我们调用了 splitNumbers 两次。

我的电脑上的结果:

    Starting split
15
Starting split
[GC (Allocation Failure) 626829K->625997K(764928K), 0.2908820 secs]
[Full GC (Ergonomics) 625997K->625210K(1039872K), 3.2126996 secs]
3510

所以是的,正如您在这里看到的,我们隐藏了对垃圾收集器的调用。它们会导致你的问题。

关于java - 使用 copyOfRange 拆分数组时奇怪的运行时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37899007/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com