JavaRush /จาวาบล็อก /Random-TH /คอฟฟี่เบรค #210. นักสะสมขยะทุกประเภทใน Java ที่คุณควรรู้

คอฟฟี่เบรค #210. นักสะสมขยะทุกประเภทใน Java ที่คุณควรรู้

เผยแพร่ในกลุ่ม
ที่มา: Hackernoon คุณจะได้เรียนรู้จุดแข็งและจุดอ่อนของ Garbage Collector แต่ละประเภทที่ใช้ในการพัฒนา Java ผ่านโพสต์นี้ คอฟฟี่เบรค #210.  ตัวรวบรวมขยะทุกประเภทใน Java ที่คุณควรรู้ - 1คำถามเกี่ยวกับ Garbage Collector (GC) มีอยู่ในการสัมภาษณ์เกือบทุกครั้ง ดังนั้นฉันจึงตัดสินใจรวบรวมข้อมูลที่จำเป็นทั้งหมดเกี่ยวกับพวกเขาโดยใช้หลักการที่ฉันชอบ - สั้นและเรียบง่าย ก่อนอื่น เรามาเริ่มด้วยจุดประสงค์ของ CG และสาเหตุที่เราต้องการเครื่องเก็บขยะหลายประเภท ในภาษาเช่น C เราจำเป็นต้องเก็บข้อมูลอ็อบเจ็กต์ไว้ในหน่วยความจำและเขียนโค้ดสำเร็จรูปจำนวนมากเพื่อเพิ่มหน่วยความจำนั้น แน่นอนว่าหน่วยความจำรั่วเป็นเรื่องปกติในโปรแกรมดังกล่าว Java แก้ปัญหาหน่วยความจำรั่วโดยใช้ตัวรวบรวมขยะ และคุณในฐานะนักพัฒนาควรรู้ว่าตัวเก็บขยะตัวไหนดีที่สุดที่จะใช้ หลายอย่างขึ้นอยู่กับว่าโปรแกรมของคุณทำงานที่ไหนและอย่างไร อาจทำงานบนฮาร์ดแวร์ที่อ่อนแอหรือมีวัตถุจำนวนมาก หรือโปรแกรมของคุณต้องเร็วมาก ตามเงื่อนไขเหล่านี้ คุณควรปรับแต่งตัวรวบรวมขยะของคุณเพื่อให้ได้ประสิทธิภาพตามที่ต้องการ เอาล่ะ มาเริ่มกันเลย

JVM จัดการกับหน่วยความจำอย่างไร

Java Virtual Machine (JVM) แบ่งหน่วยความจำออกเป็นสองส่วน ได้แก่ ฮีปซึ่งเก็บข้อมูลแอปพลิเคชัน และไม่ใช่ฮีปซึ่งเก็บโค้ดโปรแกรมและข้อมูลอื่น ๆ หันมาสนใจบริเวณฮีปกันดีกว่า นี่คือจุดที่โปรแกรมของเราสร้างวัตถุใหม่ ตัวรวบรวมขยะทั้งหมดขึ้นอยู่กับข้อเท็จจริงที่ว่าหลายโปรแกรมใช้วัตถุชั่วคราว นั่นคือวัตถุเหล่านี้ถูกสร้างขึ้นจากนั้นจึงทำหน้าที่ให้สำเร็จและไม่จำเป็นอีกต่อไป วัตถุดังกล่าวส่วนใหญ่ แต่วัตถุบางชิ้นอาจมีอายุการใช้งานนานกว่ามาก บางทีอาจตลอดระยะเวลาของโปรแกรมด้วยซ้ำ นี่คือที่มาของแนวคิดในการแบ่งวัตถุออกเป็นรุ่นเยาว์และรุ่นเก่า และเราต้องตรวจสอบรุ่นน้องบ่อยๆ ความจริงก็คือกระบวนการเก็บขยะแบ่งออกเป็นการทำความสะอาดเล็กน้อยซึ่งส่งผลต่อคนรุ่นใหม่เท่านั้น และการทำความสะอาดแบบสมบูรณ์ซึ่งอาจส่งผลต่อทั้งสองรุ่น โปรดจำไว้ว่าตัวรวบรวมขยะเป็นโปรแกรม และต้องใช้เวลาและทรัพยากรจากคอมพิวเตอร์ของคุณในการทำงาน ซึ่งส่งผลต่อการใช้งานของเราด้วย มันส่งผลกระทบอย่างไร? ตัวอย่างเช่น ในการดำเนินการรวบรวมขยะ JVM จะหยุดแอปพลิเคชันของเราชั่วคราว สิ่งนี้เรียกว่าการหยุดชั่วคราว (STW) ในระหว่างนี้ เธรดแอปพลิเคชันทั้งหมดจะถูกระงับ แต่แอปพลิเคชันภายในกลับไม่รู้เรื่องนี้เลย สำหรับการใช้งาน เวลาจะไหลอย่างเท่าเทียมกัน ทำไมมันถึงแย่ขนาดนี้? ลองนึกภาพว่าคุณกำลังเขียนแอปพลิเคชันแลกเปลี่ยนหรือแอปพลิเคชันสำหรับระบบขับเคลื่อนอัตโนมัติบนเครื่องบิน แอปพลิเคชันของคุณอาจเข้าสู่โหมดสลีปหนึ่งวินาที และลักษณะของปัญหาของคุณอาจเปลี่ยนแปลงไปอย่างมาก นั่นคือการหยุดชั่วคราวเป็นพารามิเตอร์ที่สำคัญสำหรับตัวรวบรวมขยะทุกคน คุณสมบัติพื้นฐานถัดไปของตัวรวบรวมขยะคือเวลาทั้งหมดที่ใช้ในการรวบรวมขยะซึ่งสัมพันธ์กับเวลาดำเนินการทั้งหมดของโปรแกรม สิ่งนี้หมายความว่าอย่างไรและเหตุใดจึงสำคัญมาก? แทนที่จะเป็นช่วง "หยุดโลก" ครั้งใหญ่ เราสามารถเลือกอัลกอริธึมที่มีการหยุดชั่วคราวเล็กน้อยหลายครั้งได้ การพักผ่อนเล็กๆ น้อยๆ จะดีกว่า แต่ไม่มีอะไรได้มาฟรีๆ ในกรณีนี้ เราจ่ายเงินโดยการเพิ่มเวลาดำเนินการทั้งหมดของโปรแกรม และเราต้องคำนึงถึงเรื่องนี้ด้วย พารามิเตอร์ถัดไปคือจำนวนทรัพยากรฮาร์ดแวร์ ตัวรวบรวมแต่ละตัวต้องการหน่วยความจำเพื่อจัดเก็บข้อมูลออบเจ็กต์และตัวประมวลผลเพื่อดำเนินการล้างข้อมูล พารามิเตอร์สุดท้ายคือความเร็ว ประสิทธิภาพการรวบรวมขยะหมายถึงความรวดเร็วและมีประสิทธิภาพที่ตัวรวบรวมขยะ (GC) เรียกคืนหน่วยความจำที่โปรแกรมไม่ได้ใช้อีกต่อไป พารามิเตอร์ทั้งหมดเหล่านี้มีอิทธิพลต่ออัลกอริธึมซึ่งสามารถเพิ่มหน่วยความจำได้อย่างรวดเร็วที่สุดในขณะที่ใช้ทรัพยากรน้อยที่สุด มาดูคนเก็บขยะที่มีให้เราบ้าง ในการสัมภาษณ์คุณต้องรู้ห้าข้อแรก อีกสองคนนั้นยากกว่ามาก

อนุกรม GC

Serial GC คือตัวรวบรวมขยะของ Java Virtual Machine และถูกนำมาใช้ตั้งแต่จุดเริ่มต้นของ Java มันมีประโยชน์สำหรับโปรแกรมที่มีฮีปขนาดเล็กและทำงานบนเครื่องที่ทรงพลังน้อยกว่า คนเก็บขยะนี้จะแบ่งกองออกเป็นภูมิภาคต่างๆ ซึ่งรวมถึงอีเดนและผู้รอดชีวิต ภูมิภาคอีเดนคือแหล่งรวมหน่วยความจำสำหรับอ็อบเจ็กต์ส่วนใหญ่ที่ได้รับการจัดสรรตั้งแต่แรก Survivor คือสระน้ำที่บรรจุวัตถุที่รอดจากการเก็บขยะในภูมิภาคอีเดน เมื่อฮีปเต็ม วัตถุต่างๆ จะถูกย้ายระหว่างภูมิภาคอีเดนและผู้รอดชีวิต JVM ติดตามการเคลื่อนไหวของวัตถุในพื้นที่ผู้รอดชีวิตอย่างต่อเนื่อง และเลือกเกณฑ์ที่เหมาะสมสำหรับจำนวนการเคลื่อนไหวดังกล่าว หลังจากนั้นวัตถุจะถูกย้ายไปยังพื้นที่ครอบครอง เมื่อมีพื้นที่ไม่เพียงพอในภูมิภาค Tenured การรวบรวมขยะทั้งหมดจะเข้ามาแทนที่ โดยทำงานกับวัตถุของทั้งสองรุ่น ข้อได้เปรียบหลักของตัวรวบรวมขยะนี้คือความต้องการทรัพยากรต่ำ ดังนั้นโปรเซสเซอร์ที่ใช้พลังงานต่ำจึงเพียงพอที่จะดำเนินการรวบรวม ข้อเสียเปรียบหลักของ Serial GC คือการหยุดชั่วคราวเป็นเวลานานระหว่างการรวบรวมขยะ โดยเฉพาะอย่างยิ่งเมื่อมีข้อมูลจำนวนมาก

ซีจีขนาน

ตัวรวบรวมขยะแบบขนาน (Parallel CG) คล้ายกับตัวสร้างลำดับ รวมถึงการประมวลผลงานบางอย่างแบบขนานและความสามารถในการปรับแต่งการตั้งค่าประสิทธิภาพโดยอัตโนมัติ Parallel GC คือตัวรวบรวมขยะ Java Virtual Machine ตามแนวคิดของ Serial GC แต่มีความเท่าเทียมและความชาญฉลาดเพิ่มเติม หากคอมพิวเตอร์มีแกนประมวลผลมากกว่าหนึ่งคอร์ JVM เวอร์ชันเก่าจะเลือก Parallel GC โดยอัตโนมัติ ฮีปที่นี่แบ่งออกเป็นภูมิภาคเดียวกับใน Serial GC - Eden, Survivor 0, Survivor 1 และ Old Gen (Tenured) อย่างไรก็ตาม เธรดจำนวนมากมีส่วนร่วมในการรวบรวมขยะแบบขนาน และตัวรวบรวมสามารถปรับให้เข้ากับพารามิเตอร์ประสิทธิภาพที่ต้องการได้ แต่ละเธรดตัวรวบรวมมีพื้นที่หน่วยความจำที่ต้องล้าง นอกจากนี้ Parallel GC ยังมีการตั้งค่าที่มุ่งบรรลุประสิทธิภาพการรวบรวมขยะตามที่ต้องการอีกด้วย ตัวรวบรวมใช้สถิติจากการรวบรวมขยะก่อนหน้านี้เพื่อปรับแต่งการตั้งค่าประสิทธิภาพสำหรับคอลเลกชันในอนาคต Parallel GC ให้การปรับแต่งพารามิเตอร์ประสิทธิภาพโดยอัตโนมัติและลดเวลาหยุดชั่วคราวในการสร้าง แต่มีข้อเสียเปรียบเล็กน้อยประการหนึ่งในรูปแบบของการกระจายตัวของหน่วยความจำบางส่วน เหมาะสำหรับแอปพลิเคชันส่วนใหญ่ แต่สำหรับโปรแกรมที่ซับซ้อนกว่า ควรเลือกการใช้งานตัวรวบรวมขยะขั้นสูง ข้อดี: เร็วกว่า Serial GC ในหลาย ๆ กรณี มีความเร็วที่ดี จุดด้อย: ใช้ทรัพยากรมากขึ้นและการหยุดชั่วคราวอาจใช้เวลานาน แต่เราสามารถปรับระยะเวลาการหยุดชั่วคราวสูงสุดของ Stop-The-World ได้

กวาดมาร์คพร้อมกัน

ตัวรวบรวมขยะ Concurrent Mark Sweep (CMS) มีจุดมุ่งหมายเพื่อลดระยะเวลาการหยุดชั่วคราวสูงสุดโดยการรันงานการรวบรวมขยะบางอย่างพร้อมกับเธรดของแอปพลิเคชัน ตัวรวบรวมขยะนี้เหมาะสำหรับการจัดการข้อมูลจำนวนมากในหน่วยความจำ Concurrent Mark Sweep (CMS) เป็นทางเลือกแทน Parallel GC ใน Java Virtual Machine (JVM) มีไว้สำหรับแอปพลิเคชันที่ต้องการเข้าถึงคอร์โปรเซสเซอร์หลายตัวและไวต่อการหยุดชั่วคราวของ Stop-The-World CMS ดำเนินการตามขั้นตอนการรวบรวมขยะควบคู่ไปกับโปรแกรมหลัก ซึ่งทำให้โปรแกรมทำงานโดยไม่หยุด ใช้การจัดระเบียบหน่วยความจำแบบเดียวกับตัวรวบรวมแบบอนุกรมและแบบขนาน แต่ไม่ได้รอให้พื้นที่ Tenured เต็มก่อนจึงจะทำการล้างข้อมูลรุ่นเก่า แต่จะทำงานในเบื้องหลังและพยายามทำให้ภูมิภาคที่ครอบครองมีขนาดกะทัดรัด Mark Sweep ที่เกิดขึ้นพร้อมกันเริ่มต้นด้วยขั้นตอนการทำเครื่องหมายเริ่มต้นที่จะหยุดเธรดหลักของแอปพลิเคชันเป็นเวลาสั้นๆ และทำเครื่องหมายออบเจ็กต์ทั้งหมดที่สามารถเข้าถึงได้จากรูท จากนั้นเธรดหลักของแอปพลิเคชันจะดำเนินการต่อและ CMS จะเริ่มค้นหาออบเจ็กต์ที่ใช้งานอยู่ทั้งหมดที่สามารถเข้าถึงได้โดยลิงก์จากออบเจ็กต์รูทที่ทำเครื่องหมายไว้ หลังจากทำเครื่องหมายวัตถุที่มีชีวิตทั้งหมดแล้ว ตัวรวบรวมจะล้างความทรงจำของวัตถุที่ตายแล้วในเธรดคู่ขนานหลายเธรด ข้อดีประการหนึ่งของ CMS คือการมุ่งเน้นไปที่การลดเวลาหยุดทำงานให้เหลือน้อยที่สุด ซึ่งเป็นสิ่งสำคัญสำหรับหลายแอปพลิเคชัน อย่างไรก็ตาม ต้องเสียสละในแง่ของทรัพยากร CPU และแบนด์วิธโดยรวม นอกจากนี้ CMS จะไม่บีบอัดออบเจ็กต์ในรุ่นเก่า ซึ่งนำไปสู่การแตกแฟรกเมนต์ การหยุดชั่วคราวเป็นเวลานานเนื่องจากความล้มเหลวของโหมดขนานที่อาจเกิดขึ้นอาจเป็นเรื่องน่าประหลาดใจ (แม้ว่าจะไม่ได้เกิดขึ้นบ่อยก็ตาม) หากมีหน่วยความจำเพียงพอ CMS จะสามารถหลีกเลี่ยงการหยุดชั่วคราวดังกล่าวได้ ข้อดี: รวดเร็ว. มีการหยุดหยุดโลกชั่วคราวเล็กน้อย จุดด้อย: ใช้หน่วยความจำมากขึ้น หากมีหน่วยความจำไม่เพียงพอ การหยุดชั่วคราวอาจใช้เวลานาน ไม่ค่อยดีนักหากแอปพลิเคชันสร้างวัตถุจำนวนมาก

ขยะมูลฝอยก่อน

Garbage-First (G1) ถือเป็นอีกทางเลือกหนึ่งของ CMS โดยเฉพาะอย่างยิ่งสำหรับแอปพลิเคชันเซิร์ฟเวอร์ที่ทำงานบนเซิร์ฟเวอร์ที่มีโปรเซสเซอร์หลายตัวและการจัดการชุดข้อมูลขนาดใหญ่ ตัวรวบรวมขยะ G1 จะแปลงหน่วยความจำเป็นขอบเขตที่มีขนาดเท่ากันหลายส่วน ยกเว้นขอบเขตขนาดใหญ่ (ซึ่งสร้างขึ้นโดยการผสานขอบเขตปกติเพื่อรองรับวัตถุขนาดใหญ่) ภูมิภาคไม่จำเป็นต้องจัดเรียงเป็นแถวและสามารถเปลี่ยนสังกัดรุ่นได้ การล้างข้อมูลเล็กๆ น้อยๆ จะดำเนินการเป็นระยะๆ สำหรับคนรุ่นใหม่และเคลื่อนย้ายวัตถุไปยังภูมิภาคผู้รอดชีวิต หรืออัปเกรดเป็นรุ่นเก่าและโอนไปยัง Tenured การทำความสะอาดจะดำเนินการเฉพาะในภูมิภาคที่จำเป็นเพื่อหลีกเลี่ยงการเกินเวลาที่ต้องการ นักสะสมเองทำนายและเลือกภูมิภาคที่มีขยะมากที่สุดในการทำความสะอาด การกวาดแบบเต็มใช้การวนซ้ำเพื่อสร้างรายการวัตถุสดที่ทำงานขนานกับแอปพลิเคชันหลัก หลังจากการทำเครื่องหมาย G1 จะสลับไปใช้การล้างแบบผสม ซึ่งจะเพิ่มขอบเขตรุ่นที่เก่ากว่าให้กับชุดของขอบเขตรุ่นที่อายุน้อยกว่าที่จะทำการล้าง ตัวรวบรวมขยะ G1 ถือว่ามีความแม่นยำมากกว่าตัวรวบรวม CMS ในการคาดการณ์ขนาดการหยุดชั่วคราว และกระจายการรวบรวมขยะเมื่อเวลาผ่านไปได้ดีขึ้น เพื่อป้องกันการหยุดทำงานของแอปพลิเคชันที่ยาวนาน โดยเฉพาะอย่างยิ่งกับขนาดฮีปขนาดใหญ่ นอกจากนี้ยังไม่แยกส่วนหน่วยความจำเหมือนตัวรวบรวม CMS อย่างไรก็ตาม ตัวรวบรวม G1 ต้องการทรัพยากร CPU มากขึ้นเพื่อให้ทำงานคู่ขนานกับโปรแกรมหลัก ซึ่งจะลดปริมาณการประมวลผลของแอปพลิเคชัน ข้อดี: ทำงานได้ดีกว่า CMS มีการหยุดชั่วคราวที่สั้นกว่า จุดด้อย: ใช้ทรัพยากร CPU มากขึ้น นอกจากนี้ยังใช้หน่วยความจำมากขึ้นหากเรามีวัตถุที่ค่อนข้างใหญ่จำนวนมาก (มากกว่า 500 KB) เนื่องจากวางวัตถุดังกล่าวไว้ในภูมิภาคเดียว (1-32 MB)

เอปซิลอน จีซี

Epsilon GC ได้รับการออกแบบมาสำหรับสถานการณ์ที่ไม่จำเป็นต้องเก็บขยะ มันไม่ได้ดำเนินการรวบรวมขยะ แต่ใช้ TLAB (บัฟเฟอร์การจัดสรรเธรดในเครื่อง) เพื่อจัดสรรอ็อบเจ็กต์ใหม่ - บัฟเฟอร์หน่วยความจำขนาดเล็กที่ร้องขอโดยแต่ละเธรดจากฮีป อ็อบเจ็กต์ขนาดใหญ่ที่ไม่พอดีกับบล็อกหน่วยความจำคำขอบัฟเฟอร์สำหรับตัวมันเองโดยเฉพาะ เมื่อ Epsilon GC ทรัพยากรหมด OutOfMemoryError จะถูกสร้างขึ้นและกระบวนการยุติลง ประโยชน์ของ Epsilon GC ได้แก่ ความต้องการทรัพยากรที่ลดลงและการจัดสรรหน่วยความจำที่รวดเร็วยิ่งขึ้นสำหรับแอปพลิเคชันที่สร้างอ็อบเจ็กต์ทั้งหมดที่ต้องการเมื่อเริ่มต้นระบบหรือเรียกใช้แอปพลิเคชันที่มีอายุสั้นซึ่งไม่ได้ใช้หน่วยความจำที่จัดสรรทั้งหมด Epsilon GC ยังสามารถช่วยวิเคราะห์ความต้องการทรัพยากรที่ตัวรวบรวมขยะอื่นๆ เพิ่มลงในแอปพลิเคชันของคุณ ข้อดี: รวดเร็วมาก. จุดด้อย: ไม่เคลียร์สิ่งของ :) นักสะสมสองคนถัดไปนั้นมีความล้ำหน้าที่สุด แต่ก็ซับซ้อนที่สุดเช่นกัน ดังนั้นเราจะพิจารณาโดยย่อ

ซีจีซี

ZGC สามารถรักษาเวลาแฝงที่ต่ำกว่ามิลลิวินาทีได้ แม้ว่าจะต้องจัดการกับข้อมูลจำนวนมหาศาลก็ตาม ZGC เป็นตัวรวบรวมขยะที่พัฒนาโดย Oracle สำหรับ Java ซึ่งได้รับการออกแบบมาเพื่อให้ปริมาณงานสูงและมีเวลาแฝงต่ำเมื่อประมวลผลฮีปขนาดใหญ่ (สูงสุด 16 TB) ZGC ขึ้นอยู่กับหลักการของหน่วยความจำเสมือน และใช้การทำเครื่องหมายสีที่แตกต่างกันเพื่อติดตามสถานะของออบเจ็กต์ระหว่างการรวบรวมขยะ ข้อดี: การหยุดชั่วคราวน้อยกว่าหนึ่งมิลลิวินาที แม้แต่ในฮีปขนาดใหญ่ ซึ่งมีประโยชน์มากสำหรับแอปพลิเคชันที่ต้องใช้เวลาประมวลผลคิวรีสั้น มันทำงานได้กับฮีปที่มีขนาดใหญ่มากและมีปริมาณงานที่ดี ZGC สามารถบีบอัดหน่วยความจำฮีประหว่างการรวบรวมขยะ จุดด้อย: การใช้งาน CPU สูงและความต้องการด้านประสิทธิภาพที่สำคัญ ซึ่งสามารถชะลอเวลาเปิดแอปพลิเคชันได้

เชนันโดอาห์ จี.ซี.

Shenandoah GC เป็นอีกหนึ่งตัวรวบรวมขยะที่มีการหยุดชั่วคราวสั้นๆ โดยไม่คำนึงถึงขนาดฮีป เครื่องเก็บขยะนี้พัฒนาโดย Red Hat ได้รับการออกแบบมาเพื่อลดเวลาที่แอปพลิเคชันใช้ในการรวบรวมขยะ เช่นเดียวกับ ZGC มันเป็นตัวรวบรวมแบบขนาน ซึ่งหมายความว่ามันจะทำงานในขณะที่แอปพลิเคชันกำลังทำงานอยู่ ซึ่งช่วยลดการหยุดชั่วคราวให้เหลือน้อยที่สุด Shenandoah GC ใช้ "ตัวชี้การส่งต่อ" เพื่อย้ายวัตถุระหว่างการเก็บขยะ นอกจากนี้ยังมีเทคนิคที่เรียกว่า "การกำจัดสิ่งกีดขวางโหลด" เพื่อปรับปรุงประสิทธิภาพ ข้อดี: Shenandoah GC สามารถหยุดชั่วคราวได้ในเวลาสั้นๆ ซึ่งมักจะน้อยกว่า 10 มิลลิวินาที แม้จะอยู่ในฮีปขนาดใหญ่ก็ตาม ปริมาณงานที่ดี จุดด้อย: โหลดตัวประมวลผลสูงและความยากลำบากในการทำงานภายใต้ภาระหนัก

บทสรุป

คนเก็บขยะเป็นหนึ่งในงานที่ยากที่สุดในการเขียนโปรแกรม มีการพัฒนาใหม่อย่างต่อเนื่องในทิศทางนี้ แม้ว่าโปรแกรมเมอร์จะปรับแต่ง GC ได้ยาก แต่คุณยังคงต้องมีความรู้พื้นฐานเกี่ยวกับวิธีการทำงานของเครื่องมือเก็บขยะ
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION