การใช้ตารางแฮชในการรวบรวมขยะจะช่วยแก้ปัญหาเครื่องหมายและการกวาดโลกหรือไม่


13

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

แต่จะเกิดอะไรขึ้นถ้าคุณมีตารางแฮชที่มี ID วัตถุเป็นคีย์และตัวชี้เป็นค่าและการอ้างอิงจะชี้ไปที่ ID ดังกล่าวแทนที่จะเป็นที่อยู่ของวัตถุ ... ดังนั้นการแก้ไขการอ้างอิงจะต้องเปลี่ยนค่าเดียวเท่านั้น พยายามเขียนลงในระหว่างการคัดลอก ...

ความคิดของฉันมีข้อผิดพลาดหรือไม่?

คำตอบ:


19

การอัปเดตข้อมูลอ้างอิงไม่ใช่สิ่งเดียวที่ต้องหยุดชั่วคราว อัลกอริธึมมาตรฐานทั่วไปจัดกลุ่มภายใต้ "mark-sweep" ทั้งหมดคิดว่ากราฟวัตถุทั้งหมดยังคงไม่เปลี่ยนแปลงในขณะที่มันถูกทำเครื่องหมาย การจัดการการแก้ไขอย่างถูกต้อง (สร้างวัตถุใหม่การอ้างอิงที่เปลี่ยนแปลง) ต้องการอัลกอริธึมทางเลือกที่ค่อนข้างยุ่งยากเช่นอัลกอริธึมสามสี คำว่าร่มคือ "การเก็บขยะพร้อมกัน"

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

อย่างไรก็ตามมันจะมีข้อเสียอย่างรุนแรง นอกเหนือจากการใช้พื้นที่เพิ่มเติม ( อย่างน้อยสองคำพิเศษสำหรับวัตถุทั้งหมด) มันทำให้การอ้างอิงทุกอย่างมีราคาแพงกว่ามาก แม้แต่สิ่งที่เรียบง่ายเช่นเดียวกับการรับแอตทริบิวต์ตอนนี้เกี่ยวข้องกับการค้นหาตารางแฮชเต็ม ฉันคาดการณ์ว่าประสิทธิภาพการทำงานจะแย่กว่าการติดตามแบบส่วนเพิ่ม


ดีที่เรามีจำนวนมากของหน่วยความจำในวันนี้เพื่อให้เราสามารถมีสมมติว่า 50 ตาราง Mb และกัญชาอาจจะเป็นโมดูโลง่ายดังนั้นเพียงหนึ่งคำแนะนำ ...
mrpyo

3
@mrpyo กำลังดึงขนาดของตารางแฮช, การดำเนินการแบบโมดูโล, การอ้างอิงจากตารางแฮชชดเชยเพื่อให้ได้ตัวชี้วัตถุจริง, อ้างอิงกับวัตถุนั้นเอง รวมทั้งอาจมีการสับทะเบียน เราจบด้วยคำแนะนำ 4+ นอกจากนี้ชุดรูปแบบนี้มีปัญหาเกี่ยวกับตำแหน่งหน่วยความจำ: ขณะนี้ทั้งตารางแฮชและข้อมูลเองต้องพอดีกับแคช
amon

@mrpyo คุณต้องการหนึ่งรายการ (ID วัตถุ -> ที่อยู่ปัจจุบัน) ต่อวัตถุใช่ไหม และไม่ว่าฟังก์ชันแฮชจะมีราคาถูกเพียงใดคุณจะมีการชนกันและจำเป็นต้องแก้ไข สิ่งที่อมรพูดด้วย

@amon เป็นเพียงเรื่องของเวลาก่อนที่ซีพียูมี 50 MB หรือมากกว่าของแคช :)
Moz

1
@ Ӎσᶎตามเวลาที่เราสามารถใส่ 50 MiB ของทรานซิสเตอร์บนชิปและยังมีความหน่วงแฝงต่ำพอที่จะทำงานเป็นแคช L1 หรือ L2 (แคช L3 มีขนาดสูงสุดถึง 15 MiB แต่โดยทั่วไปแล้วจะเป็นชิป AFAIK และไกลออกไป เวลาแฝงที่เลวร้ายยิ่งกว่า L1 และ L2) เราจะมีหน่วยความจำหลักจำนวนมาก (และข้อมูลที่จะใส่) ตารางไม่สามารถกำหนดขนาดตายตัวได้มันต้องเติบโตไปพร้อมกับฮีป

19

ปัญหาทั้งหมดในวิทยาการคอมพิวเตอร์สามารถแก้ไขได้โดยการอ้อมอีกระดับหนึ่ง ... ยกเว้นปัญหาของการอ้อมมากเกินไป

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

ฉันบอกว่าข้อเสนอของคุณย้ายปัญหาไม่ได้แก้ปัญหา ปัญหานี้เกี่ยวกับการนำ ID วัตถุมาใช้ซ้ำ ขณะนี้ ID วัตถุเป็นเทียบเท่าตัวชี้ของเราและมีที่อยู่จำนวน จำกัด เท่านั้น เป็นไปได้ (โดยเฉพาะกับระบบ 32 บิต) ที่ในช่วงอายุการใช้งานของโปรแกรมของคุณจะมีการสร้างออบเจ็กต์ INT_MAX มากกว่าเช่นในวงเช่น

while (true) {
    Object garbage = new Object();
}

หากเราเพิ่งเพิ่ม ID วัตถุสำหรับแต่ละวัตถุเราจะหมดรหัสในบางจุด ดังนั้นเราต้องค้นหาว่า ID ใดที่ยังใช้งานอยู่และรหัสใดที่ฟรีเพื่อให้สามารถเรียกคืนได้ ฟังดูคุ้น ๆ ไหม? ตอนนี้เรากลับมาที่จตุรัสหนึ่งแล้ว


มีใครสามารถใช้ ID ของที่มีขนาดใหญ่พอที่จะพูดได้ bitignum 256 บิต? ฉันไม่ได้พูดว่าความคิดนี้เป็นภาพรวมที่ดี แต่คุณสามารถนำ IDS กลับมาใช้ใหม่ได้
Vality

@ ความจริงสมจริงใช่ - เท่าที่เราจะเห็นว่าจะแก้ปัญหาการใช้ ID ซ้ำ แต่นี่เป็นเพียงอาร์กิวเมนต์“ 640K น่าจะเพียงพอสำหรับทุกคน” และไม่ได้แก้ปัญหาจริงๆ อีกมุมมองที่เป็นความหายนะคือขนาดของวัตถุทั้งหมด (และตารางแฮช) จะต้องเพิ่มขึ้นเพื่อรองรับตัวชี้ - ปลอมที่มีขนาดใหญ่เหล่านี้และในระหว่างการเข้าถึง hash เราต้องเปรียบเทียบ bigint นี้กับรหัสอื่น ๆ และใช้คำสั่งหลายคำสั่งเพื่อดำเนินการให้เสร็จสมบูรณ์ (บน 64 บิต: โหลด 8 ×, 4 ×เปรียบเทียบ, 3 ×และเพิ่มขึ้น 5 เท่าจาก ints ดั้งเดิม)
amon

ใช่คุณจะหมดรหัสหลังจากเวลาและจะต้องเปลี่ยนทั้งหมดของพวกเขาซึ่งจะต้องหยุดชั่วคราว แต่อาจเป็นเหตุการณ์ที่เกิดขึ้นได้ยาก ...
mrpyo

@ มอนเห็นด้วยเป็นอย่างมากทุกจุดที่ดีมาก ๆ มันก็ดีกว่าที่ฉันมีระบบที่ยั่งยืนอย่างแท้จริง สิ่งนี้จะช้าลงอย่างไม่น่าเชื่อไม่ว่าคุณจะทำอะไรก็ตามเป็นเรื่องที่น่าสนใจในทางทฤษฎีเท่านั้น โดยส่วนตัวแล้วฉันไม่ใช่แฟนเก็บขยะขนาดใหญ่อย่างไรก็ตาม: P
Vality

@ มอน: มีรหัสในโลกมากกว่านี้ที่จะผิดพลาดเมื่อคุณใส่รหัส 64 บิต (584 ปีของ nanoseconds และคุณอาจจะสามารถจัดการจัดสรรหน่วยความจำเพื่อใช้เวลา 1ns โดยเฉพาะอย่างยิ่งถ้าคุณไม่ทำลายเคาน์เตอร์โลก ที่คายรหัส!) แต่แน่นอนถ้าคุณไม่จำเป็นต้องพึ่งพาสิ่งนั้นคุณก็ไม่จำเป็น
Steve Jessop

12

ในความคิดของคุณไม่มีข้อผิดพลาดคุณเพิ่งอธิบายสิ่งที่ใกล้เคียงกับวิธีการทำงานของตัวเก็บรวบรวมขยะ Java ดั้งเดิม

เครื่องเสมือน Java ดั้งเดิม [6] และเครื่องเสมือน Smalltalk บางเครื่องใช้ตัวชี้ทางอ้อมที่เรียกว่าหมายเลขอ้างอิงใน [6] เพื่ออ้างอิงถึงวัตถุ ที่จับทำให้การขนย้ายวัตถุในระหว่างการรวบรวมขยะง่ายขึ้นเนื่องจากที่จับมีเพียงหนึ่งตัวชี้โดยตรงไปยังวัตถุแต่ละตัว: หนึ่งในการจัดการ การอ้างอิงอื่น ๆ ทั้งหมดไปยังวัตถุทางอ้อมผ่าน han-dle ในระบบหน่วยความจำแบบใช้มือจับในขณะที่ที่อยู่วัตถุเปลี่ยนไปตามอายุการใช้งานของวัตถุและดังนั้นจึงไม่สามารถใช้สำหรับการแปลงแป้นพิมพ์ได้

การข้ามพื้นที่และเวลาอย่างมีประสิทธิภาพของวัตถุที่เก็บรวบรวมขยะ

ในการใช้งาน Java Virtual Machine ปัจจุบันของ Sun การอ้างอิงไปยังอินสแตนซ์ของคลาสเป็นตัวชี้ไปยังหมายเลขอ้างอิงที่เป็นคู่ของพอยน์เตอร์: หนึ่งไปยังตารางที่มีเมธอดของออบเจ็กต์และตัวชี้ไปยังออบเจ็กต์ Class ชนิดของวัตถุและอีกหน่วยความจำที่จัดสรรจาก Java heap สำหรับข้อมูลวัตถุ

ข้อมูลจำเพาะ Java Virtual Machine (1997)

ดังนั้นมันจึงทำงานได้ถูกลองใช้และความไร้ประสิทธิภาพของมันนำไปสู่การพัฒนาระบบมาร์คและกวาดทั่วไป


น่าจะเป็นที่จับเหล่านี้ไม่ได้เป็นกุญแจใน hashtable (เหมือนในคำถาม) ใช่ไหม? ไม่จำเป็นต้องมีเพียงแค่โครงสร้างที่มีตัวชี้ จากนั้นหมายเลขอ้างอิงจะมีขนาดเท่ากันทั้งหมดดังนั้นจึงสามารถจัดสรรออกจากตัวจัดสรรฮีปได้ ซึ่งโดยธรรมชาติแล้วมันไม่ต้องการการบดอัดภายใน คุณอาจโศกเศร้ากับความไม่สามารถของบล็อกขนาดใหญ่ที่ใช้โดยตัวจัดสรรนั้นเพื่อย้ายตัวเอง ซึ่งสามารถแก้ไขได้โดยการอ้อมอีกระดับ ;-)
Steve Jessop

@SteveJessop ใช่ไม่มี hashtable ในการนำ gc มาใช้แม้ว่าค่าของหมายเลขอ้างอิงก็เป็นค่าที่ส่งคืนโดยObject.getHashCode()
Pete Kirkham
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.