อะไรทำให้ JNI โทรช้า?


194

ฉันรู้ว่า 'การข้ามเขตแดน' เมื่อทำการโทร JNI ใน Java ช้า

อย่างไรก็ตามฉันอยากรู้ว่าอะไรทำให้ช้าลง? การนำ jvm ไปปฏิบัติใช้ทำอะไรเมื่อทำการโทร JNI ที่ทำให้ช้ามาก?


2
(+1) คำถามที่ดี ในขณะที่เราอยู่ในหัวข้อนี้ฉันอยากจะสนับสนุนให้ทุกคนที่ได้ทำการวัดประสิทธิภาพจริงเพื่อโพสต์สิ่งที่พวกเขาค้นพบ
NPE

2
การเรียก JNI จำเป็นต้องแปลงออบเจ็กต์ Java ที่ส่งผ่านไปยังสิ่งที่ C (ตัวอย่าง) สามารถเข้าใจได้ เดียวกันกับค่าตอบแทน การแปลงชนิดและการเรียกมาร์แชลล์สแต็กเป็นส่วนที่ดีของมัน
Dave Newton

เดฟฉันเข้าใจและเคยได้ยินเรื่องนั้นมาก่อน แต่สิ่งที่แน่นอนคือการแปลงเป็นอย่างไร นั่นคือ 'บางสิ่ง'? ฉันกำลังมองหารายละเอียด
pdeva

การใช้ ByteBuffers โดยตรงเพื่อส่งผ่านข้อมูลระหว่าง Java และ C อาจส่งผลให้ค่าใช้จ่ายค่อนข้างต่ำ
Peter Lawrey

6
การโทรต้องใช้เฟรมสแต็ก C ที่เหมาะสมผลักดัน CPU register ที่มีประโยชน์ทั้งหมด (และกลับมาอีกครั้ง) การโทรต้องการการฟันดาบและยังป้องกันการปรับให้เหมาะสมเช่น inline นอกจากนี้เธรดยังต้องปล่อยให้ล็อกการประมวลผลสแต็ก (ตัวอย่างเช่นเพื่อให้ล็อคแบบเอนเอียงสามารถทำงานได้ในขณะที่อยู่ในเนทีฟ) แล้วรับกลับมา
bestsss

คำตอบ:


174

อันดับแรกมันน่าสังเกตว่า "ช้า" เรากำลังพูดถึงบางสิ่งบางอย่างที่อาจใช้เวลาหลายสิบวินาที สำหรับวิธีเนทีฟเล็กน้อยในปี 2010 ฉันวัดการโทรเฉลี่ย 40 ns บนเดสก์ท็อป Windows ของฉันและ 11 ns บนเดสก์ท็อป Mac ของฉัน หากคุณไม่ได้โทรออกหลายสายคุณจะไม่สังเกตเห็น

ที่กล่าวว่าการเรียกใช้เมธอดเนทีฟอาจช้ากว่าการเรียกเมธอด Java ปกติ สาเหตุประกอบด้วย:

  • วิธีการเนทิฟจะไม่ถูก inlined โดย JVM และจะไม่ถูกคอมไพล์แบบทันเวลาสำหรับเครื่องนี้โดยเฉพาะ
  • อาเรย์ Java อาจถูกคัดลอกเพื่อการเข้าถึงในรหัสเนทีฟและคัดลอกในภายหลัง ค่าใช้จ่ายสามารถเป็นเชิงเส้นในขนาดของอาร์เรย์ ฉันวัดการคัดลอก JNI ของอาร์เรย์ 100,000 ชุดโดยเฉลี่ยประมาณ 75 ไมโครวินาทีบนเดสก์ท็อป Windows ของฉันและ 82 microseconds บน Mac โชคดีที่การเข้าถึงโดยตรงอาจจะได้รับผ่านทางGetPrimitiveArrayCriticalหรือNewDirectByteBuffer
  • หากเมธอดถูกส่งผ่านอ็อบเจ็กต์หรือต้องการโทรกลับดังนั้นเมธอดเนทีฟน่าจะทำการเรียกไปยัง JVM ของตัวเอง การเข้าใช้งานฟิลด์วิธีการและประเภทจากโค้ดเนทีฟต้องการสิ่งที่คล้ายกับรีเฟลคชัน ลายเซ็นถูกระบุในสตริงและสอบถามจาก JVM นี่คือทั้งช้าและผิดพลาดได้ง่าย
  • Java Strings เป็นวัตถุมีความยาวและถูกเข้ารหัส การเข้าถึงหรือสร้างสตริงอาจต้องการสำเนา O (n)

บางการสนทนาเพิ่มเติมอาจลงวันที่สามารถพบได้ใน "ประสิทธิภาพแพลตฟอร์มJava¿: กลยุทธ์และกลยุทธ์", 2000, โดย Steve Wilson และ Jeff Kesselman ในหัวข้อ "9.2: การตรวจสอบค่าใช้จ่าย JNI" ประมาณหนึ่งในสามของวิธีลงหน้านี้ให้ไว้ในความคิดเห็นโดย @Philip ด้านล่าง

IBM developerWorks ในกระดาษ 2009 "แนวทางปฏิบัติที่ดีที่สุดสำหรับการใช้ Java Native Interface"ให้คำแนะนำเกี่ยวกับการหลีกเลี่ยงข้อผิดพลาดด้านประสิทธิภาพด้วย JNI


1
คำตอบนี้อ้างว่าโค้ดเนทีฟบางตัวสามารถถูก Inline โดย JVM
AH

5
คำตอบนั้นตั้งข้อสังเกตว่าโค้ดเนทีฟมาตรฐานบางตัวถูก inline ใน JVM แทนที่จะใช้ JNI ข้างต้น "วิธีการดั้งเดิม" หมายถึงกรณีทั่วไปของวิธีการดั้งเดิมที่ผู้ใช้กำหนดเองที่นำมาใช้ผ่าน JNI ขอบคุณสำหรับตัวชี้ไปที่ sun.misc.Unsafe
Andy Thomas

ฉันไม่ต้องการอ้างสิทธิ์ว่าวิธีนี้สามารถใช้สำหรับการโทร JNI ทุกครั้ง แต่มันจะไม่เจ็บที่จะรู้ว่ามีเป็นบางพื้นกลางระหว่าง bytecode บริสุทธิ์และรหัส JNI บริสุทธิ์ อาจจะส่งผลต่อการตัดสินใจออกแบบ บางทีกลไกนี้อาจเป็นลักษณะทั่วไปในอนาคต
AH

3
@AH คุณเข้าใจผิดเกี่ยวกับ JNI พวกเขาแตกต่างกันมากsun.misc.Unsafeและสิ่งอื่น ๆ อีกมากมายเช่นSystem.currentTimeMillis/nanoTimeได้รับการจัดการผ่าน 'เวทมนตร์' โดย JVM พวกเขาไม่ใช่ JNI และพวกเขาไม่มีไฟล์. c / .h ที่เหมาะสมการถอด JVM impl เอง ไม่สามารถทำตามวิธีการได้เว้นแต่คุณจะเขียน / เจาะระบบ JVM
bestsss

1
" เอกสาร java.sun.com นี้ " ใช้งานไม่ได้ในขณะนี้ - นี่คือลิงก์ที่ใช้งานได้
Philip Guin

25

เป็นมูลค่าการกล่าวขวัญว่าไม่ใช่ทุกวิธี Java ทำเครื่องหมายด้วย native "ช้า" บางส่วนของพวกเขาภายในที่ทำให้พวกเขาเร็วมาก หากต้องการตรวจสอบว่าคนที่มีที่แท้จริงและคนที่ไม่ได้คุณสามารถมองหาdo_intrinsicที่vmSymbols.hpp


23

โดยพื้นฐานแล้ว JVM จะสร้างพารามิเตอร์ C สำหรับการโทร JNI แต่ละครั้งและรหัสนั้นไม่ได้รับการปรับให้เหมาะสม

มีรายละเอียดเพิ่มเติมมากมายที่ระบุไว้ในบทความนี้

หากคุณสนใจในการเปรียบเทียบ JNI กับ native code โปรเจคนี้มีรหัสสำหรับการรัน benchmark


2
กระดาษที่คุณเชื่อมโยงดูเหมือนจะเป็นกระดาษมาตรฐานประสิทธิภาพมากกว่ากระดาษที่อธิบายว่า JNI ทำงานอย่างไรภายใน
pdeva

@pdeva น่าเสียดายที่แหล่งข้อมูลอื่นที่ฉันพบเชื่อมโยงกับ java.sun.com และลิงก์นั้นยังไม่ได้รับการอัพเดตนับตั้งแต่มีการซื้อ Oracle ฉันกำลังมองหารายละเอียดเพิ่มเติมเกี่ยวกับการฝึกงาน JNI
dmck

13
บทความเกี่ยวกับ Java 1.3 - ค่อนข้างนานมาแล้ว ปัญหาของเวลาดังกล่าวยังคงใช้กับ Java 7 หรือไม่?
AH
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.