我想创建一个新的对象数组,将两个较小的数组放在一起.
它们不能为空,但大小可能为0.
我无法在这两种方式之间进行选择:它们是等效还是更高效(例如system.arraycopy()复制整个块)?
MyObject[] things = new MyObject[publicThings.length+privateThings.length];
System.arraycopy(publicThings, 0, things, 0, publicThings.length);
System.arraycopy(privateThings, 0, things, publicThings.length, privateThings.length);
Run Code Online (Sandbox Code Playgroud)
要么
MyObject[] things = new MyObject[publicThings.length+privateThings.length];
for (int i = 0; i < things.length; i++) {
if (i<publicThings.length){
things[i] = publicThings[i]
} else {
things[i] = privateThings[i-publicThings.length]
}
}
Run Code Online (Sandbox Code Playgroud)
唯一的区别是代码的外观?
编辑:感谢链接的问题,但他们似乎有一个未解决的讨论:
如果it is not for native types:byte [],Object [],char [] 真的更快吗?在所有其他情况下,执行类型检查,这将是我的情况,因此将是等效的......不是吗?
在另一个相关问题上,他们说the size matters a lot,对于size> 24,system.arraycopy()获胜,小于10,手动for循环更好......
现在我真的很困惑.
Tre*_*all 85
public void testHardCopyBytes()
{
byte[] bytes = new byte[0x5000000]; /*~83mb buffer*/
byte[] out = new byte[bytes.length];
for(int i = 0; i < out.length; i++)
{
out[i] = bytes[i];
}
}
public void testArrayCopyBytes()
{
byte[] bytes = new byte[0x5000000]; /*~83mb buffer*/
byte[] out = new byte[bytes.length];
System.arraycopy(bytes, 0, out, 0, out.length);
}
Run Code Online (Sandbox Code Playgroud)
我知道JUnit测试并不是最适合基准测试的,但
testHardCopyBytes需要0.157秒才能完成
,
testArrayCopyBytes需要0.086秒才能完成.
我认为这取决于虚拟机,但它看起来好像是复制内存块而不是复制单个数组元素.这绝对会提高性能.
编辑:
看起来System.arraycopy的表现已经到处都是.当使用字符串而不是字节,并且数组很小(大小为10)时,我得到以下结果:
String HC: 60306 ns
String AC: 4812 ns
byte HC: 4490 ns
byte AC: 9945 ns
Run Code Online (Sandbox Code Playgroud)
这是数组大小为0x1000000时的样子.看起来System.arraycopy肯定会赢得更大的数组.
Strs HC: 51730575 ns
Strs AC: 24033154 ns
Bytes HC: 28521827 ns
Bytes AC: 5264961 ns
Run Code Online (Sandbox Code Playgroud)
多奇怪啊!
谢谢,达人,指出参考文献的复制方式不同.这使得这个问题变得更加有趣!
Phi*_*der 36
Arrays.copyOf(T[], int)更容易阅读.Internaly它使用的System.arraycopy()是本机调用.
你不能更快!
s.t*_*.ts 15
它取决于虚拟机,但System.arraycopy应该为您提供最接近本机性能的功能.
我作为嵌入式系统的Java开发人员已经工作了两年(性能是一个非常重要的优先事项),并且可以使用System.arraycopy,我主要使用它/看到它在现有代码中使用.当性能成为问题时,它始终优先于循环.如果性能不是一个大问题,我会选择循环.更容易阅读.
我没有依赖猜测和可能过时的信息,而是使用卡尺运行了一些基准测试.实际上,Caliper附带了一些例子,其中包括一个CopyArrayBenchmark测量这个问题的例子!你所要做的就是跑步
mvn exec:java -Dexec.mainClass=com.google.caliper.runner.CaliperMain -Dexec.args=examples.CopyArrayBenchmark
Run Code Online (Sandbox Code Playgroud)
我的结果基于Oracle的Java HotSpot(TM)64位服务器VM,1.8.0_31-b13,运行于2010年中期的MacBook Pro(带有Intel Arrandale i7的macOS 10.11.6,8 GiB RAM).我不相信发布原始时序数据是有用的.相反,我将用支持的可视化来总结结论.
综上所述:
for无论是对于短数组还是长数组,编写手动循环以将每个元素复制到新实例化的数组中都是不利的.Arrays.copyOf(array, array.length)并且array.clone()都一直很快.这两种技术的性能几乎相同; 你选择哪一个是品味问题.System.arraycopy(src, 0, dest, 0, src.length)几乎一样快和,但并不完全一致等等.(看看50000 秒的情况.)因为这个,以及电话的详细程度,如果您需要精确控制哪些元素被复制到哪里,我会建议.Arrays.copyOf(array, array.length)array.clone()intSystem.arraycopy()以下是时间图:
执行本机方法Arrays.copyOf(T[], int)确实有一些开销,但并不意味着它使用JNI执行它并不快.
最简单的方法是编写基准测试和测试.
你可以检查它Arrays.copyOf(T[], int)比你的正常for循环更快.
来自这里的基准代码: -
public void test(int copySize, int copyCount, int testRep) {
System.out.println("Copy size = " + copySize);
System.out.println("Copy count = " + copyCount);
System.out.println();
for (int i = testRep; i > 0; --i) {
copy(copySize, copyCount);
loop(copySize, copyCount);
}
System.out.println();
}
public void copy(int copySize, int copyCount) {
int[] src = newSrc(copySize + 1);
int[] dst = new int[copySize + 1];
long begin = System.nanoTime();
for (int count = copyCount; count > 0; --count) {
System.arraycopy(src, 1, dst, 0, copySize);
dst[copySize] = src[copySize] + 1;
System.arraycopy(dst, 0, src, 0, copySize);
src[copySize] = dst[copySize];
}
long end = System.nanoTime();
System.out.println("Arraycopy: " + (end - begin) / 1e9 + " s");
}
public void loop(int copySize, int copyCount) {
int[] src = newSrc(copySize + 1);
int[] dst = new int[copySize + 1];
long begin = System.nanoTime();
for (int count = copyCount; count > 0; --count) {
for (int i = copySize - 1; i >= 0; --i) {
dst[i] = src[i + 1];
}
dst[copySize] = src[copySize] + 1;
for (int i = copySize - 1; i >= 0; --i) {
src[i] = dst[i];
}
src[copySize] = dst[copySize];
}
long end = System.nanoTime();
System.out.println("Man. loop: " + (end - begin) / 1e9 + " s");
}
public int[] newSrc(int arraySize) {
int[] src = new int[arraySize];
for (int i = arraySize - 1; i >= 0; --i) {
src[i] = i;
}
return src;
}
Run Code Online (Sandbox Code Playgroud)
System.arraycopy()使用JNI(Java Native Interface)来复制数组(或部分数组),所以它非常快,因为你可以在这里确认
小智 5
不可能Arrays.copyOf快System.arraycopy于此,因为这是实现copyOf:
public static int[] copyOf(int[] original, int newLength) {
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
63056 次 |
| 最近记录: |