Go ใช้ Garbage Collection แบบไหน?


111

Go เป็นภาษาที่เก็บขยะ:

http://golang.org/doc/go_faq.html#garbage_collection

ที่นี่บอกว่าเป็นเครื่องเก็บขยะแบบมาร์คและกวาด แต่ไม่ได้เจาะลึกรายละเอียดและมีการแทนที่อยู่ในผลงาน ... แต่ย่อหน้านี้ดูเหมือนจะไม่ได้รับการอัปเดตมากนักนับตั้งแต่ Go เปิดตัว

มันยังคงทำเครื่องหมายและกวาด? หัวโบราณหรือเป๊ะ? เป็นรุ่น?


2
สำหรับการสนทนาเกี่ยวกับประวัติของ Go ที่เก็บขยะจนถึงเดือนกรกฎาคม 2018 โปรดดูblog.golang.org/ismmkeynote
Wildcard

คำตอบ:


117

แผนสำหรับ Go 1.4+ คนเก็บขยะ:

  • ไฮบริดหยุดโลก / ตัวสะสมพร้อมกัน
  • ชิ้นส่วนหยุดโลกถูก จำกัด โดยกำหนดเวลา 10ms
  • แกน CPU เฉพาะสำหรับการรันตัวรวบรวมพร้อมกัน
  • อัลกอริทึมการทำเครื่องหมายและกวาดสามสี
  • ไม่ใช่รุ่น
  • ไม่บดอัด
  • แม่นยำเต็มที่
  • ต้องเสียค่าใช้จ่ายเล็กน้อยหากโปรแกรมกำลังเคลื่อนย้ายตัวชี้ไปรอบ ๆ
  • เวลาในการตอบสนองต่ำกว่า แต่ก็มีแนวโน้มที่จะรับส่งข้อมูลต่ำกว่า Go 1.3 GC

ไป 1.3 การปรับปรุงตัวเก็บขยะที่ด้านบนของ Go 1.1:

  • การกวาดพร้อมกัน (ส่งผลให้เวลาหยุดชั่วคราวน้อยลง)
  • แม่นยำเต็มที่

ไป 1.1 คนเก็บขยะ:

  • ทำเครื่องหมายและกวาด (การใช้งานแบบขนาน)
  • ไม่ใช่รุ่น
  • ไม่บดอัด
  • แม่นยำเป็นส่วนใหญ่ (ยกเว้นสแต็กเฟรม)
  • หยุดโลก
  • การแสดงตามบิตแมป
  • ค่าใช้จ่ายเป็นศูนย์เมื่อโปรแกรมไม่ได้จัดสรรหน่วยความจำ (นั่นคือ: การสับพอยน์เตอร์รอบ ๆ นั้นเร็วเท่ากับใน C แม้ว่าในทางปฏิบัติจะทำงานค่อนข้างช้ากว่า C เนื่องจากคอมไพเลอร์ Go ไม่ก้าวหน้าเท่าคอมไพเลอร์ C เช่น GCC)
  • รองรับ Finalizers บนวัตถุ
  • ไม่มีการสนับสนุนสำหรับการอ้างอิงที่อ่อนแอ

ไป 1.0 คนเก็บขยะ:

  • เช่นเดียวกับ Go 1.1 แต่แทนที่จะเป็นความแม่นยำส่วนใหญ่คนเก็บขยะกลับอนุรักษ์นิยม GC แบบอนุรักษ์นิยมสามารถที่จะละเว้นวัตถุเช่น [] ไบต์

การแทนที่ GC ด้วย GC อื่นนั้นเป็นที่ถกเถียงกันเช่น:

  • ยกเว้นฮีปที่มีขนาดใหญ่มากยังไม่ชัดเจนว่า GC โดยรวมจะเร็วขึ้นหรือไม่
  • แพคเกจ "ไม่ปลอดภัย" ทำให้ยากที่จะใช้ GC ที่แม่นยำและกระชับ GC

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

3
@uriel: ใช่ฉันพูดถึงสิ่งนี้ในข้อที่ 1 ในคำตอบของฉัน - ข้อความ "(การใช้งานแบบขนาน)"

คำตอบนี้ยังคงเป็นปัจจุบันอยู่หรือไม่?
Kim Stebel

c # ตัวเก็บขยะมีความแม่นยำและใน c # เหมือนกันคุณสามารถอ้างอิงถึงสมาชิกของขีดและ c # มีโหมดที่ไม่ปลอดภัย แต่ฉันไม่แน่ใจว่ามันเปรียบเทียบกับการใช้งานที่ไม่ปลอดภัยได้อย่างไร
skyde

3
สิ่งที่เกี่ยวกับการอัปเดตคำตอบนี้ด้วย 1.5.x เพื่อสร้างบันทึกประวัติที่ดี
อิสมาเอล

32

(สำหรับGo 1.8 - Q1 2017 ดูด้านล่าง )

เครื่องเก็บขยะGo 1.5 พร้อมกันครั้งต่อไปเกี่ยวข้องกับความสามารถในการ "ก้าว" กล่าวว่า gc
นี่คือข้อเสนอที่นำเสนอในเอกสารนี้ซึ่งอาจใช้สำหรับ Go 1.5 แต่ยังช่วยให้เข้าใจ gc ใน Go

คุณสามารถเห็นสถานะก่อน 1.5 (Stop The World: STW)

ก่อนหน้า Go 1.5 Go ได้ใช้ตัวสะสมstop-the-world (STW) แบบขนาน
แม้ว่าคอลเลกชัน STW จะมีข้อเสียมากมาย แต่อย่างน้อยก็มีพฤติกรรมการเติบโตของฮีปที่คาดเดาได้และควบคุมได้

https://40.media.tumblr.com/49e6556b94d75de1050c62539680fcf9/tumblr_inline_nr6qq8D9FE1sdck2n_540.jpg

(ภาพจากงานนำเสนอGopherCon 2015 " Go GC: Solving the Latency Problem in Go 1.5 ")

ลูกบิดปรับแต่ง แต่เพียงผู้เดียวสำหรับคอลเลกชัน STW คือ“ GOGC” การเติบโตของฮีปที่สัมพันธ์กันระหว่างคอลเลกชัน การตั้งค่าเริ่มต้น 100% เรียกใช้การรวบรวมขยะทุกครั้งที่ขนาดฮีปเพิ่มขึ้นเป็นสองเท่าของขนาดฮีปที่ใช้งานจริงเมื่อเทียบกับคอลเล็กชันก่อนหน้านี้:

https://docs.google.com/drawings/image?id=sLJ_JvGfPfPnojLlEGLCWkw&rev=1&h=113&w=424&ac=1

เวลา GC ในตัวรวบรวม STW

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

https://40.media.tumblr.com/783c6e557b427a5c023520578740eb94/tumblr_inline_nr6qqpmaJx1sdck2n_540.jpg

(ภาพจากงานนำเสนอGopherCon 2015 " Go GC: Solving the Latency Problem in Go 1.5 ")

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

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

การบรรลุความสมดุลที่เหมาะสมโดยไม่ต้องเสียสละการทำงานพร้อมกันจำเป็นต้องมีการเว้นจังหวะอย่างระมัดระวัง

GC pacing มีจุดมุ่งหมายเพื่อเพิ่มประสิทธิภาพตามสองมิติ ได้แก่ การเติบโตของฮีปและ CPU ที่ใช้โดยตัวรวบรวมขยะ

https://docs.google.com/drawings/image?id=sEZYCf7Mc0E0EGmy4gho3_w&rev=1&h=235&w=457&ac=1

การออกแบบการเว้นวรรค GC ประกอบด้วยสี่องค์ประกอบ:

  1. ตัวประมาณจำนวนงานสแกนที่วงจร GC จะต้องใช้
  2. กลไกสำหรับ mutators เพื่อดำเนินการสแกนจำนวนโดยประมาณตามเวลาที่การจัดสรรฮีปถึงเป้าหมายฮีป
  3. ตัวกำหนดตารางเวลาสำหรับการสแกนเบื้องหลังเมื่อ mutator ช่วยลดงบประมาณของ CPU และ
  4. ตัวควบคุมตามสัดส่วนสำหรับทริกเกอร์ GC

การออกแบบที่สมดุลสองมุมมองที่แตกต่างกันของเวลา: เวลา CPU และเวลาที่กอง

  • เวลาของ CPUก็เหมือนกับเวลานาฬิกาแขวนมาตรฐาน แต่จะผ่านไปGOMAXPROCSเร็วกว่า
    นั่นคือถ้าGOMAXPROCSเป็น 8 วินาที CPU แปดวินาทีจะผ่านทุก ๆ กำแพงวินาทีและ GC จะได้รับเวลา CPU สองวินาทีทุก ๆ วินาที
    ตัวกำหนดตารางเวลา CPU จัดการเวลาของ CPU
  • เวลาที่ผ่านไปของฮีปจะถูกวัดเป็นไบต์และเดินหน้าต่อไปเมื่อมิวเตเตอร์จัดสรร

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


20

นี่คือการใช้งาน GC:

https://github.com/golang/go/blob/master/src/runtime/mgc.go

จากเอกสารในแหล่งที่มา:

GC ทำงานพร้อมกันกับเธรด mutator เป็นประเภทที่ถูกต้อง (หรือที่เรียกว่าแม่นยำ) ช่วยให้เธรด GC หลายตัวทำงานแบบขนาน เป็นเครื่องหมายพร้อมกันและการกวาดที่ใช้ขีดกั้นการเขียน ไม่ใช่การสร้างและไม่บดอัด การจัดสรรทำได้โดยใช้ขนาดแยกตามพื้นที่การจัดสรร P เพื่อลดการแยกส่วนให้น้อยที่สุดในขณะที่กำจัดการล็อกในกรณีทั่วไป


8

Go 1.8 GC อาจมีการเปลี่ยนแปลงอีกครั้งโดยมีข้อเสนอ "กำจัด STW stack re-scan"

ตั้งแต่ Go 1.7 แหล่งที่มาของเวลาหยุดโลก (STW) ที่ไม่ถูก จำกัด และอาจไม่สำคัญอีกแหล่งหนึ่งคือการสแกนซ้ำแบบสแต็ก

เราเสนอเพื่อขจัดความจำเป็นในการสแต็คใหม่สแกนโดยสลับไปเขียนอุปสรรคไฮบริดที่รวมอุปสรรคยัวซ่าสไตล์การลบเขียน [Yuasa 90]และอุปสรรค Dijkstra สไตล์แทรกเขียน [Dijkstra 78]

การทดลองเบื้องต้นแสดงให้เห็นว่าวิธีนี้สามารถลดเวลา STW ในกรณีที่เลวร้ายที่สุดให้เหลือน้อยกว่า 50µsและวิธีนี้อาจทำให้สามารถกำจัดการยกเลิกเครื่องหมาย STW ได้โดยสิ้นเชิง

ประกาศอยู่ที่นี่และคุณสามารถดูแหล่งที่มาเกี่ยวข้องกระทำเป็นd70b0feและก่อนหน้านี้


3

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


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