วิธีอุ่นเครื่องคลาส Java เพื่อหลีกเลี่ยงการโทรช้าครั้งแรก?


13

ฉันกำลังทำโปรเจ็กต์ที่ฉันต้องการให้การเรียกใช้ API ทั้งหมดใช้เวลาน้อยกว่า 1 วินาที แต่ฉันกำลังประสบปัญหากับการโทรครั้งแรกไปยังแต่ละเส้นทางที่ช้ากว่าครั้งต่อไปนี้

ขณะนี้การโทร / ล็อกอินครั้งแรกใช้เวลา 3.6 วินาทีและโทรถัดไปใช้เวลา 170ms และเหมือนกันสำหรับเส้นทางอื่น ๆ ทั้งหมด

ฉันค้นพบการใช้-XX:+TraceClassLoadingสิ่งนั้นในการโทรครั้งแรกชั้นเรียนถูกโหลดในหน่วยความจำและทำให้เกิดปัญหาประสิทธิภาพ

อย่างไรก็ตามฉันไม่พบวิธีที่ง่ายในการโหลดคลาสทั้งหมดเมื่อเริ่มต้นและสำหรับแต่ละบริการใหม่ฉันต้องเพิ่มการเรียกวอร์มอัพใน ApplicationRunner

ใครบ้างมีวิธีแก้ปัญหาในการโหลดคลาสของแอพพลิเคชั่น SpringBoot หรืออุ่นเครื่องเส้นทางทั้งหมด?


คุณสามารถเพิ่มรายละเอียดเพิ่มเติมได้ไหม? แอปพลิเคชันของคุณควบคุมอินสแตนซ์ได้หรือไม่ หรือคุณกำลังโทรหาบริการอื่น ๆ ? คุณโทรไปยังบริการอื่น ๆ อย่างไร?
Menios

Spring Boot ใช้การสแกนในชั้นเรียนอย่างเข้มข้นดังนั้นคุณไม่จำเป็นต้อง 'วอร์มอัพ' อะไร ๆ ในแอปพลิเคชันบนเดสก์ท็อป การโหลดเริ่มต้นที่ยาวนานนี้อาจเป็นผลมาจากการค้นหาทรัพยากร - เช่นการโหลดเทมเพลตหน้า
Alex Chernyshev

วิธีการทางอ้อม: ถ้าคุณมีการทดสอบหน่วย 100% สำหรับจุดสิ้นสุดที่คุณสามารถใช้ได้ คุณยังจะต้องรหัสต่อปลายทาง แต่คุณได้รับบางสิ่งบางอย่าง
Marged

1
อาจไม่เหมาะขึ้นอยู่กับโครงการที่คุณกำลังทำ แต่คุณสามารถโทรหาจุดปลายภายในเมื่อโหลดแอปพลิเคชันของคุณ
omoshiroiii

@omoshiroiii ไม่มีอะไรผิดปกติกับสิ่งนั้น เราทำมัน. ในการผลิต เหตุผลเกี่ยวข้องกับไลบรารีแบบไดนามิกบางส่วนที่ใช้invokedynamicและเรารู้ว่าความละเอียดจะช้าในการโทรครั้งแรกสำหรับพวกเขา (เรามีการโทรนับหมื่นนับพันครั้ง
ยูจีน

คำตอบ:


1

การโหลดคลาส Java นั้นขี้เกียจ นี่หมายความว่าคลาสจะถูกโหลดโดย JVM เมื่อต้องการและหากจำเป็นเท่านั้น

หากคุณต้องการบังคับให้โหลดคลาสอย่างกระตือรือร้นคุณเพียงแค่ต้องอ้างอิงคลาสเหล่านั้น Class.forName(className)วิธีหนึ่งในการทำก็คือการย้ำผ่านเนื้อหาขวดหรือไฟล์ระดับที่จะได้รับชื่อชั้นแล้วใช้พวกเขาที่จะเรียก

นอกจากนี้หากเวลาเริ่มต้นและประสิทธิภาพเป็นสิ่งสำคัญอย่างยิ่งสำหรับกรณีการใช้งานของคุณคุณอาจต้องการดูโซลูชันการรวบรวมเวลาก่อนหน้าเช่นGraalVMหรือลดเกณฑ์ของ JIT สำหรับการรวบรวม ( -XX:CompileThreshold)


ทั้งคู่จะไม่แก้ปัญหาของ OP การโหลดยังคงขี้เกียจใน GraalVM และJITไม่มีความหมายในการเรียกใช้ครั้งแรกจริงๆ
ยูจีน

นอกจากนี้ยังGraalVMเป็นสิ่งที่ดี แต่โปรดดูจำนวนของปัญหาที่มีใน GitHub: ทันทีที่คุณไปจากโครงการ sandbox เพื่อสิ่งที่ใหญ่กว่า (ฉันกำลังมองที่คุณสะท้อนส่วนใหญ่) คุณจะเจ็บปวดบางอย่าง อย่างน้อย. ประเด็นของฉันคือ: การสลับไปที่ GraalVM ไม่ใช่เรื่องง่าย
ยูจีน

ฉันคิดถึงการโหลดคลาสลงในขวด แต่ฉันไม่พบวิธีการทำคุณจะมีตัวอย่างหรือไม่?
Ybri

@Eugene ถ้าคุณอ่านคำตอบของฉันคุณจะเห็นว่าฉันไม่ได้พูด GraalVM หรือเกณฑ์ JIT จะเปลี่ยนความขี้เกียจของการโหลดคลาส คำตอบสำหรับคำถามของ OP เกี่ยวกับความเกียจคร้านคือย่อหน้าก่อนหน้านั้น ย่อหน้าสุดท้ายเป็นเพียงเคล็ดลับเพิ่มเติมในกรณีที่ OP ต้องการเพื่อเพิ่มประสิทธิภาพเวลา / ประสิทธิภาพการเริ่มต้นให้ดีขึ้นนอกเหนือจากการโหลดคลาส
andresp

1
@Ybri มีคำถามอื่น ๆ พร้อมคำตอบสำหรับคำถามที่นี่เช่นstackoverflow.com/questions/2370867/ …
andresp

0

สำหรับฉันตัวเลือกที่ทำงานได้อย่างเดียวที่คุณมีคือclass data sharingแพร่กระจายไปทั่วJEP 310 , JEP 341และJEP 350แต่สิ่งนี้ต้องการจาวา -13 เรากำลังทดสอบภายในสถานที่ทำงานของฉัน (ส่วนใหญ่เพื่อความสนุกสนานไม่โกหก) และผลลัพธ์ดูดีมาก

ตัวเลือกอื่นกำลังโทรหาจุดปลายทางของคุณเมื่อแอปพลิเคชันเริ่มต้น - ถ้าเป็นตัวเลือก อีกครั้งก็คือสำหรับเราเช่นเราเรียกพวกเขามีข้อมูลหุ่นคู่ของหลายร้อยครั้งในการอุ่นเครื่องรหัส แต่ในเวลาเดียวกันเรามีบริการที่จะเป็นไปไม่ได้นั่นคือเหตุผลที่สำรวจCDSด้วย


คุณจะจัดการการรับรองความถูกต้องและจุดสิ้นสุดการโพสต์เพื่อหลีกเลี่ยงการสร้างข้อมูลในฐานข้อมูลการผลิตของคุณได้อย่างไร
Ybri

@Yriri ทำไมฉันพูดไม่ได้สำหรับบางคน
ยูจีน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.