programing

JNI 콜이 느려지는 이유는 무엇입니까?

prostudy 2022. 7. 16. 14:00
반응형

JNI 콜이 느려지는 이유는 무엇입니까?

자바에서 JNI 호출을 할 때 '경계 넘기기'가 느리다는 것을 알고 있습니다.

하지만 나는 무엇이 그것을 느리게 하는지 알고 싶다.JNI 호출이 느려지면 기본 jvm 구현에서 수행하는 작업은 무엇입니까?

우선, "느림"은 수십 나노초가 걸릴 수 있는 무언가에 대해 말하고 있다는 것을 주목할 필요가 있습니다.간단한 네이티브 방식의 경우 2010년에 Windows 데스크톱에서 평균 40ns, Mac 데스크톱에서 평균 11ns의 콜을 측정했습니다.전화를 많이 하지 않으면 눈치채지 못할 거예요.

즉, 네이티브 메서드 호출은 일반 Java 메서드 호출보다 느릴 수 있습니다.원인은 다음과 같습니다.

  • 네이티브 메서드는 JVM에 의해 인라인화되지 않습니다.또, 이 특정의 머신에 대해서 적시에 컴파일 되는 것도 아닙니다.이미 컴파일 되어 있습니다.
  • Java 배열은 네이티브 코드로 액세스하기 위해 복사한 후 나중에 다시 복사할 수 있습니다.비용은 어레이 크기에 따라 선형적일 수 있습니다.Windows 데스크탑에서는 평균 75마이크로초, Mac에서는 82마이크로초로 10만 어레이의 JNI 복사를 측정했습니다.다행히 직접 액세스는 GetPrimitiveArrayCritical 또는 NewDirectByteBuffer를 통해 얻을 수 있습니다.
  • 메서드가 오브젝트를 전달받았거나 콜백을 해야 하는 경우 네이티브메서드는 JVM에 대해 자체 콜을 발신합니다.네이티브 코드에서 Java 필드, 메서드 및 유형에 액세스하려면 리플렉션과 유사한 것이 필요합니다.시그니처는 문자열로 지정되며 JVM에서 쿼리됩니다.는 느리고 오류가 발생하기 쉽습니다.
  • Java String은 객체이며 길이가 있으며 인코딩되어 있습니다.문자열에 액세스하거나 작성하려면 O(n) 복사본이 필요할 수 있습니다.

자세한 내용은 "Java(tm) Platform Performance"에서 확인할 수 있습니다.Steve Wilson과 Jeff Kesselman의 Strategies and Tactics, 2000, 섹션 "9.2: JNI 비용 조사"에서.아래 @Philip의 코멘트에 기재되어 있는 이 페이지의 3분의 1 정도 아래에 있습니다.

2009년 IBM developerWorks 논문 "Java Native Interface 사용을 위한 모범 사례"는 JNI를 통한 성능 저하를 방지하기 위한 몇 가지 제안을 제공합니다.

모든 Java 메서드가 다음과 같이 마크된 것은 아님을 언급할 필요가 있습니다.native느리다.그 중 일부는 매우 빠르게 만드는 본질적 특성입니다.어떤 것이 본질적이고 어떤 것이 비본질적인지 확인하려면do_intrinsicvmSymbols.hpp로 이동합니다.

기본적으로 JVM은 각 JNI 콜의 C 파라미터를 해석적으로 구성하며 코드는 최적화되지 않습니다.

이 문서에는 더 많은 세부 사항이 요약되어 있습니다.

JNI와 네이티브 코드를 벤치마킹하는 데 관심이 있는 경우 이 프로젝트에는 벤치마크를 실행하기 위한 코드가 있습니다.

JNI에 대해서는 Java calling C++와 C++ calling java의 두 가지 방향이 있습니다."native" 키워드를 사용하여 C++(또는 C)를 호출하는 Java는 약 50클럭 사이클로 매우 빠릅니다.단, Java를 호출하는 C++는 다소 느립니다.Java/C++와의 연동을 많이 실시하고 있기 때문에, 1 콜 당 1000 클럭 사이클을 기준으로 하고 있기 때문에, 초당 200만 콜 정도의 콜을 수신할 수 있습니다."왜 느린가"라는 당신의 실제 질문에 답할 수는 없지만, varargs를 사용하여 네이티브 C++ 스택에서 Java 스택으로 인수를 전송하고 필요한 적합성을 검증하고 반환값에 대해 그 반대의 작업을 해야 한다고 추측합니다.

단, C++에서 Java 메서드로 콜을 발신하면 그 메서드가 복잡한 데이터 구조를 반환할 경우 결과에 대한 모든 액세스에 대해서도 JNI 콜을 발신할 필요가 있다는 점도 기억하십시오.복잡한 C++ 구조를 Java로 변환하는 경우에도 마찬가지입니다.예를 들어 C++ std::map <string, string>을 JSON에 시리얼화하고 문자열을 JNI를 통해 전달하며 맵 전체를 Java로 변환하는 경우를 가정하여 Java에서 맵으로 역직렬화하는 것이 훨씬 빠르다는 것을 실제로 알게 되었습니다.

언급URL : https://stackoverflow.com/questions/7699020/what-makes-jni-calls-slow

반응형