เวลาคอมไพล์ JVM เทียบกับแคชโค้ด

ฉันได้เปรียบเทียบแอปของฉันและวิเคราะห์ด้วย JMC ฉันสังเกตเห็นว่าภายใต้โหลด มันจะทำการคอมไพล์ JIT ค่อนข้างน้อย ถ้าฉันส่งธุรกรรมจำนวนมากต่อวินาที เวลาในการคอมไพล์จะเพิ่มขึ้นอย่างรวดเร็ว เวลาในการคอมไพล์จะเพิ่มขึ้นตามสัดส่วนเสมอเมื่อมีการทดสอบโหลดหนักกับแอป

ฉันยังสังเกตเห็นว่า Code Cache เพิ่มขึ้นอย่างช้าๆ เช่นกัน ดังนั้นฉันจึงตัดสินใจเพิ่มการสำรอง Code Cache เป็น 500MB เพื่อทดสอบ ย้ายไม่ดี! ตอนนี้มันใช้เวลามากขึ้นในการดำเนินการ JIT

จากนั้นฉันก็ปิดการใช้งานการล้างแคชโค้ดอย่างชัดเจนผ่าน -XX:-UseCodeCacheFlushing อย่างไรก็ตาม ฉันสังเกตเห็นว่าการใช้งาน Code Cache สูงสุดนั้นมีขนาดใหญ่กว่าขนาดปัจจุบัน สิ่งนี้ทำให้ฉันมีคำถามสองสามข้อ:

ป้อนคำอธิบายรูปภาพที่นี่

  1. JVM พยายามแคชการคอมไพล์ JIT ทุกครั้งหรือไม่
  2. เหตุใดขนาดแคชโค้ดสูงสุดจึงใหญ่กว่าขนาดปัจจุบันแม้ว่าฉันจะปิดใช้งานการฟลัชแล้วก็ตาม
  3. มีโค้ดที่คอมไพล์ "ชั่วคราว" ที่ถูกลบออกโดยอัตโนมัติหลังจากฟังก์ชันสิ้นสุดหรือไม่

person stan    schedule 13.07.2018    source แหล่งที่มา


คำตอบ (1)


ใน HotSpot JVM วิธีการคอมไพล์ด้วย JIT ทั้งหมดจะยังคงอยู่ใน CodeCache จนกว่าจะถูกเรียกคืน UseCodeCacheFlushing ส่งผลกระทบต่อการเรียกคืนวิธีการคอมไพล์แบบเย็น (แต่ยังคงใช้ได้) อย่างไรก็ตาม CodeCache อาจมีวิธีการที่ล้าสมัยหรือไม่ถูกต้อง ("ซอมบี้") ซึ่งอาจถูกล้างข้อมูลในรอบการกวาดครั้งถัดไปแม้ว่าจะมี -XX:-UseCodeCacheFlushing ก็ตาม

  • ใน โหมดการคอมไพล์แบบแบ่งระดับ (ค่าเริ่มต้นตั้งแต่ JDK 8) วิธีการอาจถูกคอมไพล์หลายครั้งโดยมีระดับการปรับให้เหมาะสมที่แตกต่างกัน เมื่อติดตั้งวิธีการเวอร์ชันที่ได้รับการปรับปรุง (ระดับ 4) แล้ว เวอร์ชันก่อนหน้าจะล้าสมัยและสามารถเรียกคืนได้หลังจากการเปิดใช้งานเวอร์ชันนั้นเสร็จสมบูรณ์ทั้งหมด
  • วิธีการคอมไพล์แบบเก็งกำไรอาจไม่ถูกต้องเมื่อการเก็งกำไรล้มเหลว (เช่น หลังจากโหลดคลาสใหม่) วิธีการดังกล่าวก็กลายเป็นซอมบี้และสามารถเรียกคืนได้ในภายหลัง
  • อีกตัวอย่างหนึ่งคือการคอมไพล์ OSR นี่คือเวอร์ชันของวิธีการที่ถูกคอมไพล์เป็นพิเศษสำหรับการถ่ายโอนการดำเนินการจากล่ามไปเป็นโค้ดที่คอมไพล์ในขณะที่เมธอดกำลังทำงานอยู่ ตอบคำถามที่ 3 ของคุณ นี่เป็นวิธี "ชั่วคราว" ซึ่งจะล้าสมัยหลังจากติดตั้งวิธีการคอมไพล์เวอร์ชันเต็มและการเปิดใช้งาน OSR ทั้งหมดเสร็จสมบูรณ์

มีแฟล็ก JVM แยกต่างหาก -XX:-MethodFlushing เพื่อป้องกันการกวาดล้าง CodeCache โดยสิ้นเชิง รวมถึงวิธีซอมบี้ด้วย

person apangin    schedule 13.07.2018
comment
ขอบคุณสำหรับคำอธิบายโดยละเอียด คุณรู้หรือไม่ว่าการคอมไพล์ OSR จะทำงานแม้ว่าวิธีการทั้งหมดจะใหญ่เกินกว่าจะคอมไพล์ได้หรือไม่? ดังนั้นมีเพียงบางส่วนของวิธีการเท่านั้นที่คอมไพล์ผ่าน OSR แล้วล้างออกเมื่อเสร็จแล้ว - person stan; 13.07.2018
comment
@StanislavPalatnik Limits ส่วนใหญ่จะเหมือนกันสำหรับการรวบรวม OSR และที่ไม่ใช่ OSR แต่ขีดจำกัดบนนั้นใหญ่พอ (8,000 ไบต์รหัส) ที่จะไม่เป็นปัญหาในแอปพลิเคชันจริง - person apangin; 13.07.2018