두 개의 작은 배열을 모아 새로운 객체 배열을 만들고 싶습니다.
null 일 수 없지만 크기는 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);
또는
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]
}
}
유일한 차이점은 코드의 모양입니까?
편집 : 연결된 질문에 감사하지만 해결되지 않은 토론이있는 것 같습니다.
it is not for native typesbyte [], Object [], char [] 이면 정말 더 빠릅니까? 다른 모든 경우에는 유형 검사가 실행됩니다. 이것은 내 경우이므로 동등합니다.
또 다른 연결된 질문에서 그들은 the size matters a lot크기가> 24 인 경우 system.arraycopy ()가 이기고 10보다 작은 경우 수동 for 루프가 더 좋다고 말합니다 .
이제 정말 혼란 스러워요.
답변
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);
}
나는 JUnit 테스트 정말 벤치마킹을위한 최상의하지 알고 있지만
testHardCopyBytes 완료에 0.157s했다
및
testArrayCopyBytes 완료에 0.086s했다.
가상 머신에 의존한다고 생각하지만 단일 배열 요소를 복사하는 대신 메모리 블록을 복사하는 것처럼 보입니다. 이것은 절대적으로 성능을 향상시킬 것입니다.
편집 :
System.arraycopy의 성능이 온통있는 것 같습니다. 바이트 대신 문자열이 사용되고 배열이 작 으면 (크기 10) 다음과 같은 결과가 나타납니다.
String HC: 60306 ns
String AC: 4812 ns
byte HC: 4490 ns
byte AC: 9945 ns
배열의 크기가 0x1000000 일 때의 모습은 다음과 같습니다. System.arraycopy가 더 큰 배열에서 확실히 승리하는 것처럼 보입니다.
Strs HC: 51730575 ns
Strs AC: 24033154 ns
Bytes HC: 28521827 ns
Bytes AC: 5264961 ns
얼마나 특이한가!
참고 문헌이 다르게 복사된다는 점을 지적 해 주신 Daren에게 감사드립니다. 이것은 이것을 훨씬 더 흥미로운 문제로 만들었습니다!
답변
Arrays.copyOf(T[], int)읽기 쉽습니다. 내부적으로는 System.arraycopy()네이티브 호출을 사용합니다.
더 빨리 얻을 수 없습니다!
답변
가상 머신에 따라 다르지만 System.arraycopy는 기본 성능에 가장 근접한 성능을 제공해야합니다.
저는 2 년 동안 임베디드 시스템 (성능이 가장 중요한 곳)을위한 자바 개발자로 일했으며 System.arraycopy를 사용할 수있는 모든 곳에서 주로 사용했거나 기존 코드에서 사용하는 것을 보았습니다. 성능이 문제가 될 때 항상 루프보다 선호됩니다. 성능이 큰 문제가 아니라면 루프를 사용합니다. 훨씬 읽기 쉽습니다.
답변
추측과 구식 정보에 의존하는 대신 다음을 사용하여 몇 가지 벤치 마크를 실행했습니다. 캘리퍼스. 실제로 Caliper에는 CopyArrayBenchmark이 질문을 정확하게 측정하는를 포함하여 몇 가지 예제가 있습니다 ! 당신이해야 할 일은 달리기
mvn exec:java -Dexec.mainClass=com.google.caliper.runner.CaliperMain -Dexec.args=examples.CopyArrayBenchmark
내 결과는 2010 년 중반 MacBook Pro (Intel Arrandale i7, 8GiB RAM이있는 macOS 10.11.6)에서 실행되는 Oracle의 Java HotSpot (TM) 64 비트 서버 VM, 1.8.0_31-b13을 기반으로합니다. 원시 타이밍 데이터를 게시하는 것이 유용하다고 생각하지 않습니다. 오히려 지원 시각화를 통해 결론을 요약하겠습니다.
요약해서 말하자면:
for각 요소를 새로 인스턴스화 된 배열로 복사 하는 수동 루프를 작성하는 것은 짧은 배열이든 긴 배열이든간에 결코 유리하지 않습니다.Arrays.copyOf(array, array.length)그리고array.clone()둘 다 지속적으로 빠릅니다. 이 두 기술은 성능면에서 거의 동일합니다. 당신이 선택하는 것은 취향의 문제입니다.System.arraycopy(src, 0, dest, 0, src.length)는 및 만큼 빠르지 만 일관성이 없습니다. (50000 s 의 경우를 참조하십시오 .) 그것과 호출의 장황함 때문에 어떤 요소가 어디에서 복사되는지에 대한 미세 제어가 필요한 경우 권장 합니다.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;
}
System.arraycopy()JNI (Java Native Interface)를 사용하여 배열 (또는 그 일부)을 복사하므로 여기에서 확인할 수 있듯이 매우 빠릅니다.
답변
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;
}
답변
System.arraycopy()메모리에서 직접 복사 작업을 수행하는 기본 호출입니다. 단일 메모리 복사본은 항상 for 루프보다 빠릅니다.



