2012-12-18 4 views
12

가능한 중복 전화 :
What makes JNI calls slow?오버 헤드

먼저 나에게이 질문은 실제 필요보다 더 호기심 많은 태어난 가정 해 봅시다.

Java에서 JNI 호출을 수행 할 때 오버 헤드가 무엇인지 알고 싶습니다. 예를 들어 System.arraycopy과 배열을 할당하고 for 루프를 사용하여 요소를 복사하는 것입니다.

오버 헤드가 많은 경우 시스템 호출을 사용하는 대신 단순히 for 루프를 사용하여 보상하는 요소의 거친 "마법 번호"가있을 수 있습니다. 또한이 오버 헤드를 유발하는 시스템 호출에 정확히 무엇이 관련되어 있습니까? 스택이 호출 컨텍스트에 푸시되어야한다고 생각합니다.하지만이 작업은 다소 시간이 걸릴 수 있지만 전체 프로세스에 대한 좋은 설명을 찾을 수 없습니다.

은 내 질문을 명확히하자

나는 arraycopy를 사용하여 자바에서 배열을 복사하는 가장 빠른 방법이라는 것을 알고있다.

말하자면, 하나의 요소 배열을 복사하는 데 사용하고 있다고 가정 해 보겠습니다. 기본 OS에서 호출하기 때문에 에는이 오버 헤드가됩니다. 이 오버 헤드가 무엇인지, 호출 과정에서 어떤 일이 발생하는지 알고 싶습니다.

arraycopy를 사용하여 내 질문의 목적을 잘못 이해하면 죄송합니다. JNI 호출의 오버 헤드와 실제 호출에 관련된 내용을 알고 싶습니다.

+1

시스템 호출은 [시스템 호출] (https://en.wikipedia.org/wiki/System_call)과 혼동 될 수 있으므로 다소 혼란스러운 용어입니다. –

+0

그건 그렇고, 거기에 정보가 풍부한 http://stackoverflow.com/questions/2772152/why-is-system-arraycopy-native-in-java – NPE

+2

내 대답을 삭제, 이것이 도움이 될 것 같아요 : http : //stackoverflow.com/questions/7699020/what-makes-jni-calls-slow –

답변

9

...

당신은 system calls 상당히 비싸다 그 권리입니다.그러나 (System.arraycopy())은 잘못된 이름입니다. 시스템 호출이 필요 없습니다.

...이 호출에서 오버 헤드가 있어야합니다. 이 오버 헤드가 무엇인지, 호출 과정에서 어떤 일이 발생하는지 알고 싶습니다.

System.arraycopy()의 정의를 보면 native으로 선언됩니다. 즉,이 메소드는 C++로 구현됩니다. 그렇게 생각한다면 JDK 소스 코드를보고 C++ 기능을 찾을 수 있습니다. OpenJDK 7에서는 JVM_ArrayCopy()이고 hotspot/src/share/vm/prims/jvm.cpp에 있습니다. 구현은 놀라 울 정도로 복잡하지만 깊이 내려 간다는 것은 본질적으로 memcpy()입니다.

arraycopy()이 일반적인 네이티브 함수로 사용되는 경우이를 호출하는 데 오버 헤드가 있습니다. 인수 검사 등으로 인한 추가 오버 헤드가 있습니다.

그러나 JIT compiler은 대략 System.arraycopy()을 알고있을 가능성이 큽니다. 즉, C++ 함수를 호출하는 대신 컴파일러에서 배열 복사본을 수행하기 위해 특수하게 조작 된 컴퓨터 코드를 생성하는 방법을 알고 있습니다. 다른 JVM에 대해서는 알지 못하지만 HotSpot에는 System.arraycopy()에 대한 "내장"지원이 있습니다.

의 내가

배열이 작은 경우 하나 개의 요소의 배열을 복사하는 데 사용하고 있다고 가정 해 봅시다, 당신은 손으로 만들어진 루프 System.arraycopy()을 이길 수 있습니다. 컴파일 시간에 크기를 알면 더 잘 수행 할 수 있습니다. 이후 루프를 풀 수도 있습니다. 그러나 모든 상황은 가장 좁은 환경을 제외하고는 아무런 의미가 없습니다.

+0

+1 네이티브 콜을 인라이닝하는 것이 가장 중요하다. –

+0

나는 이것을 향해 지적했다. http://stackoverflow.com/questions/7699020/what-makes-jni-calls-slow가 가장 도움이 되었기 때문에 나는 받아 들일 수있다. 내가 사용한 용어를 정리해 주셔서 감사합니다. – pcalcao

+1

질문에 대한 가장 좋은 답변 중 +1 – Bohemian

0

주위가 잘못되었습니다. System.arraycopy에은()에는 "오버 헤드"가없는 JVM

에서 제공하는 슈퍼 빠른 네이티브 구현 - "장점"

2

는 java.util.Arrays.copyOf 구현 예를 살펴 보자에만있다

public static byte[] copyOf(byte[] original, int newLength) { 
    byte[] copy = new byte[newLength]; 
    System.arraycopy(original, 0, copy, 0, 
        Math.min(original.length, newLength)); 
    return copy; 
} 

이들은 가장 빠른 방법이기 때문에 System.arraycopy를 사용합니다.

당신은 질문이 정말 재미있다 http://www.javamex.com/tutorials/jni/overhead.shtml

UPDATE에서 살펴보고, 그래서

 long t0 = System.currentTimeMillis(); 
     byte[] a = new byte[100]; 
     byte[] b = new byte[100]; 
     for(int i = 0; i < 10000000; i++) { 
//   for(int j = 0; j < a.length; j++) { 
//    a[j] = b[j]; 
//   } 
      System.arraycopy(b, 0, a, 0, a.length); 
     } 
     System.out.println(System.currentTimeMillis() - t0); 

그것은 보여줍니다 좀 테스트를 완료했습니다 자바에서 네이티브 메소드를 호출하면 비용이 있는지 여부를 의미하는 경우 매우 짧은 배열 (< 10) System.arraycopy는 더 느려질 수 있습니다. 왜냐하면 네이티브이지만, 더 큰 배열에서는 더 이상 중요하지 않으므로 System.arraycopy가 훨씬 빠릅니다.

내가 그렇게 할 기본 OS를 호출하고있어 이후
+0

감사합니다. 링크를 위해 upvoted, 실제로 내가 찾고있는 것이 었습니다. – pcalcao

+0

몇 가지 테스트를 추가했습니다. 내 업데이트 –

+0

*을 참조하십시오.대부분의 경우 아마도 네이티브이기 때문입니다. * - 다른 가능성있는 설명이 있습니다. 예를 들어,'arraycopy() '가 인수를 검사하고 올바른 방법으로 복사본을 선택해야하는 도서가 있기 때문입니다. –

1

JNI 호출의 오버 헤드와 실제 호출에 관련된 내용을 알고 싶습니다.

System.arraycopy() 방법 *를 다소 복잡하며 가능성이라는 JIT 컴파일러를 인라인 (다른 응답 중 하나 있듯이).

반면에 JIT 컴파일러는 내장 된 고유 메소드이기 때문에 최적화 된 호출 순서를 사용합니다. 즉, 이것은 보통 JNI 호출이 아닌 것입니다.


* - System.arraycopy은 간단한 메모리 복사하지 않습니다. 배열 경계를 넘어 읽기 또는 쓰기를 피하기 위해 인수를 테스트해야합니다. 그리고 한 개체 배열에서 다른 개체 배열로 복사 할 때 은 복사 한 각 개체의 실제 유형을 확인해야합니다. 이 모든 것이 인라인에 합리적인 것보다 훨씬 많은 코드를 추가합니다.