เหตุใดจึงไม่ลบวัตถุ Java ทันทีหลังจากที่ไม่มีการอ้างอิงอีกต่อไป


77

ใน Java ทันทีที่วัตถุไม่มีการอ้างอิงใด ๆ อีกต่อไปวัตถุนั้นจะมีสิทธิ์ในการลบ แต่ JVM จะตัดสินใจเมื่อวัตถุถูกลบจริง ในการใช้คำศัพท์ Objective-C การอ้างอิง Java ทั้งหมดจะ "แข็งแรง" โดยเนื้อแท้ อย่างไรก็ตามใน Objective-C หากวัตถุไม่มีการอ้างอิงที่แข็งแกร่งอีกต่อไปวัตถุจะถูกลบทันที เหตุใดจึงไม่เป็นเช่นนี้ใน Java


46
คุณไม่ควรสนใจเมื่อวัตถุ Java ถูกลบจริง มันเป็นรายละเอียดการใช้งาน
Basile Starynkevitch

154
@BasileStarynkevitch คุณควรใส่ใจและท้าทายในการทำงานของระบบ / แพลตฟอร์มของคุณ การถามคำถามว่า 'อย่างไร' และ 'ทำไม' เป็นหนึ่งในวิธีที่ดีที่สุดในการเป็นโปรแกรมเมอร์ที่ดีขึ้น (และโดยทั่วไปแล้วคนฉลาดขึ้น)
Artur Biesiadowski

6
Objective C ทำอะไรเมื่อมีการอ้างอิงแบบวงกลม? ฉันคิดว่ามันรั่วแค่ไหนเหรอ?
Mehrdad

45
@ArturBiesiadowksi: ไม่ข้อกำหนดของ Java ไม่ได้บอกเมื่อวัตถุถูกลบ (และเช่นเดียวกันสำหรับR5RS ) คุณสามารถและอาจพัฒนาโปรแกรม Java ของคุณราวกับว่าการลบนั้นไม่เคยเกิดขึ้น (และสำหรับกระบวนการที่ใช้งานสั้น ๆ เช่น Java hello world มันจะไม่เกิดขึ้นจริง ๆ ) คุณอาจสนใจเกี่ยวกับชุดของสิ่งมีชีวิต (หรือการใช้หน่วยความจำ) ซึ่งเป็นเรื่องที่แตกต่าง
Basile Starynkevitch

28
อยู่มาวันหนึ่งสามเณรพูดกับอาจารย์ว่า "ฉันมีทางออกให้กับปัญหาการจัดสรรของเราเราจะให้การนับการอ้างอิงทุกครั้งและเมื่อถึงศูนย์เราจะสามารถลบวัตถุได้" ต้นแบบตอบว่า "วันหนึ่งสามเณรกล่าวว่าต้นแบบ" ผมมีวิธีการแก้ปัญหา ...
เอริค Lippert

คำตอบ:


79

ก่อนอื่น Java มีการอ้างอิงที่อ่อนแอและหมวดหมู่ความพยายามที่ดีที่สุดที่เรียกว่าการอ้างอิงแบบนุ่ม การอ้างอิงที่ไม่รัดกุมและแข็งแกร่งเป็นปัญหาที่แยกจากการนับการอ้างอิงกับการรวบรวมขยะอย่างสมบูรณ์

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

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


58
ภรรยาของโปรแกรมเมอร์ส่งเขาไปที่ซุปเปอร์มาร์เก็ต เธอบอกเขาว่า "ซื้อขนมปังหนึ่งก้อนและถ้าคุณเห็นไข่ให้หยิบโหล" โปรแกรมเมอร์กลับมาพร้อมกับขนมปังสิบก้อนภายใต้แขนของเขา
Neil

7
ฉันขอแนะนำให้กล่าวถึงเวลา gc รุ่นใหม่โดยทั่วไปจะเป็นสัดส่วนกับจำนวนของวัตถุสดดังนั้นการมีวัตถุที่ถูกลบมากกว่าหมายถึงค่าใช้จ่ายของพวกเขาจะไม่ถูกจ่ายในหลาย ๆ กรณี ลบเป็นง่ายๆเป็นตัวชี้พลิกพื้นที่รอดชีวิตและเลือก zeroing พื้นที่หน่วยความจำทั้งหมดใน memset ขนาดใหญ่ (ไม่แน่ใจว่ามันจะทำในตอนท้ายของ GC หรือตัดจำหน่ายในช่วงการจัดสรร tlabs หรือวัตถุตัวเองใน JVMs ปัจจุบัน)
Artur Biesiadowski

64
@ ไม่มีใครควรเป็น 13 ก้อนหรือ
JAD

67
"ปิดโดยข้อผิดพลาดหนึ่งบนทางเดิน 7"
joeytwiddle

13
@ JAD ฉันจะบอกว่า 13 แต่ส่วนใหญ่ไม่ได้มีแนวโน้มที่จะได้รับ ;)
Neil

86

เพราะการรู้บางสิ่งบางอย่างนั้นไม่มีการอ้างอิงอีกต่อไปจึงไม่ใช่เรื่องง่าย ไม่แม้แต่ใกล้ถึงง่าย

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


7
หรือคุณอาจใช้วิธีการของ Python ที่คุณใช้การคำนวณใหม่ให้มากที่สุดโดยหันไปใช้ GC เมื่อคุณคาดว่าจะมีหน่วยความจำรั่วไหลแบบวงกลม ฉันไม่เห็นว่าทำไมพวกเขาไม่สามารถนับยอดนอกเหนือจาก GC ได้
Mehrdad

27
@ Mehrdad พวกเขาทำได้ แต่อาจจะช้ากว่านี้ก็ได้ ไม่มีอะไรที่ห้ามไม่ให้คุณนำสิ่งนี้ไปใช้ แต่อย่าคาดหวังว่าจะเอาชนะ GCs ใด ๆ ใน Hotspot หรือ OpenJ9
Josef

21
@ jpmc26 เพราะหากคุณลบวัตถุทันทีที่ไม่ได้ใช้งานอีกต่อไปความน่าจะเป็นสูงที่คุณจะลบวัตถุเหล่านั้นในสถานการณ์โหลดสูงซึ่งเพิ่มภาระมากขึ้น GC สามารถทำงานได้เมื่อมีภาระน้อย การนับการอ้างอิงนั้นเป็นค่าใช้จ่ายเล็ก ๆ สำหรับการอ้างอิงทุกครั้ง ด้วย GC คุณสามารถทิ้งส่วนใหญ่ของหน่วยความจำโดยไม่มีการอ้างอิงโดยไม่ต้องจัดการกับวัตถุเดี่ยว
Josef

33
@Josef: การนับการอ้างอิงที่เหมาะสมนั้นไม่ฟรีเช่นกัน การอัปเดตการนับการอ้างอิงจำเป็นต้องมีการเพิ่ม / ลดจำนวนอะตอมซึ่งเป็นค่าใช้จ่ายที่น่าแปลกใจโดยเฉพาะอย่างยิ่งในสถาปัตยกรรมแบบมัลติคอร์ที่ทันสมัย ใน CPython มันไม่ใช่ปัญหามาก (CPython ช้าอย่างมากในตัวของมันเองและ GIL จำกัด ประสิทธิภาพการทำงานแบบมัลติเธรดในระดับ single-core) แต่สำหรับภาษาที่เร็วกว่าซึ่งรองรับการขนานมันอาจเป็นปัญหาได้ มันไม่ใช่โอกาสที่ PyPy จะกำจัดการนับการอ้างอิงโดยสมบูรณ์และเพียงแค่ใช้ GC
Matteo Italia

10
@ Mehrdad เมื่อคุณใช้การนับการอ้างอิง GC สำหรับ Java ฉันยินดีที่จะทดสอบเพื่อค้นหากรณีที่มันทำงานได้แย่กว่าการใช้งาน GC อื่น ๆ
Josef

45

AFAIK ข้อมูลจำเพาะ JVM (เขียนเป็นภาษาอังกฤษ) ไม่ได้กล่าวถึงเมื่อควรลบวัตถุ (หรือค่า) อย่างแน่นอนและปล่อยให้การนำไปใช้ (เช่นเดียวกันสำหรับR5RS ) อย่างใดมันต้องหรือแนะนำตัวเก็บขยะแต่ออกจากรายละเอียดเพื่อการดำเนินการ และเช่นเดียวกันสำหรับข้อกำหนดของ Java

โปรดจำไว้ว่าการเขียนโปรแกรมภาษาที่มีรายละเอียด (จากไวยากรณ์ , ความหมาย , ฯลฯ ... ), ไม่ได้ใช้งานซอฟต์แวร์ ภาษาอย่าง Java (หรือ JVM) มีการนำไปใช้งานหลายอย่าง สเปคของมันถูกตีพิมพ์ , ดาวน์โหลด (เพื่อให้คุณสามารถเรียนได้) และเขียนเป็นภาษาอังกฤษ §2.5.3กองข้อมูลจำเพาะของ JVM กล่าวถึงตัวรวบรวมขยะ:

ที่จัดเก็บฮีปสำหรับออบเจ็กต์ได้รับการเรียกคืนโดยระบบการจัดการที่จัดเก็บอัตโนมัติ วัตถุจะไม่ถูกยกเลิกการจัดสรรอย่างชัดเจน Java Virtual Machine ไม่มีระบบจัดการหน่วยเก็บข้อมูลอัตโนมัติประเภทใดเป็นพิเศษ

(การเน้นคือของฉัน; การสรุป BTW ถูกกล่าวถึงใน§12.6ของข้อมูลจำเพาะ Java และรุ่นของหน่วยความจำอยู่ในin17.4ของข้อมูลจำเพาะของ Java)

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

ฉันเดาว่าในการใช้งานJVMหลายครั้งที่รันโปรแกรม Java อายุสั้นเช่นสวัสดีชาวโลกตัวเก็บรวบรวมขยะจะไม่ถูกเรียกใช้เลยและไม่มีการลบเกิดขึ้น AFAIU พฤติกรรมดังกล่าวสอดคล้องกับข้อกำหนด Java จำนวนมาก

การใช้งาน JVM ส่วนใหญ่ใช้เทคนิคการคัดลอกgenerational (อย่างน้อยสำหรับวัตถุ Java ส่วนใหญ่ที่ไม่ได้ใช้การสรุปหรือการอ้างอิงที่อ่อนแอและการสรุปไม่รับประกันว่าจะเกิดขึ้นในเวลาอันสั้นและอาจถูกเลื่อนออกไป ขึ้นอยู่กับมาก) ซึ่งความคิดของการลบวัตถุแต่ละรายการไม่ได้ทำให้รู้สึกใด ๆ (ตั้งแต่บล็อกขนาดใหญ่ของหน่วยความจำ - โซนหน่วยความจำที่ควบคุมสำหรับวัตถุจำนวนมาก - บางทีหลายเมกะไบต์ในครั้งเดียวได้รับการปล่อยตัวในครั้งเดียว)

หากข้อกำหนด JVM ต้องการให้ลบแต่ละวัตถุออกโดยเร็วที่สุด (หรือเพิ่มข้อ จำกัด ในการลบวัตถุ) เทคนิคการสร้าง generational GC ที่มีประสิทธิภาพจะถูกห้ามและผู้ออกแบบ Java และ JVM นั้นฉลาดในการหลีกเลี่ยงสิ่งนั้น

BTW อาจเป็นไปได้ว่า JVM ไร้เดียงสาที่ไม่เคยลบวัตถุและไม่ปล่อยหน่วยความจำอาจเป็นไปตามข้อกำหนด (ตัวอักษรไม่ใช่จิตวิญญาณ) และแน่นอนสามารถใช้สิ่งสวัสดีโลกในทางปฏิบัติ (สังเกตว่าส่วนใหญ่ โปรแกรม Java อายุสั้นและขนาดเล็กอาจไม่จัดสรรหน่วยความจำเกินกว่าสองสามกิกะไบต์) แน่นอนเช่น JVM จะไม่คุ้มค่าการกล่าวขวัญและเป็นเพียงสิ่งที่ของเล่น (เหมือนนี้การดำเนินการmallocสำหรับ C) ดูEpsilon NoOp GCสำหรับข้อมูลเพิ่มเติม JVMs ในชีวิตจริงเป็นซอฟต์แวร์ที่ซับซ้อนมากและผสมผสานเทคนิคการรวบรวมขยะจำนวนมาก

นอกจากนี้Javaไม่เหมือนกับ JVM และคุณมีการนำ Java ไปใช้โดยไม่มี JVM (เช่นJava compilers ล่วงหน้า , รันไทม์ Android ) ในบางกรณี (ส่วนใหญ่เป็นนักวิชาการ) คุณอาจจินตนาการ (เรียกว่าเทคนิค "การรวบรวมเวลารวบรวมขยะ") ที่โปรแกรม Java ไม่ได้จัดสรรหรือลบที่รันไทม์ (เช่นเนื่องจากคอมไพเลอร์เพิ่มประสิทธิภาพได้ฉลาดพอที่จะใช้call stackและตัวแปรอัตโนมัติ )

เหตุใดจึงไม่ลบวัตถุ Java ทันทีหลังจากที่ไม่มีการอ้างอิงอีกต่อไป

เนื่องจากข้อกำหนดของ Java และ JVM ไม่ต้องการสิ่งนั้น


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

Objective-Cโปรดปรานอ้างอิงนับแนวทางการจัดการหน่วยความจำ และนั่นก็มีข้อผิดพลาด (เช่นโปรแกรมเมอร์ Objective-C ต้องดูแลเกี่ยวกับการอ้างอิงแบบวงกลมโดยการอธิบายการอ้างอิงที่อ่อนแอ แต่ JVM จัดการการอ้างอิงแบบวงกลมเป็นอย่างดีในทางปฏิบัติโดยไม่ต้องการความสนใจจากโปรแกรมเมอร์ Java)

นอกจากนี้ไม่มีกระสุนเงินในการเขียนโปรแกรมและการออกแบบการเขียนโปรแกรมภาษา (จะตระหนักถึงปัญหาลังเล ; เป็นวัตถุที่อยู่อาศัยที่มีประโยชน์คือundecidableทั่วไป)

นอกจากนี้คุณยังอาจจะอ่านSICP , การเขียนโปรแกรมภาษาเน้นที่มังกรหนังสือ , เสียงกระเพื่อมในชิ้นเล็ก ๆและระบบปฏิบัติการ: สามชิ้นง่าย พวกเขาไม่ได้เกี่ยวกับ Java แต่พวกเขาจะเปิดใจของคุณและควรช่วยให้เข้าใจสิ่งที่ JVM ควรทำและวิธีการใช้งานจริง (กับชิ้นส่วนอื่น ๆ ) ในคอมพิวเตอร์ของคุณ คุณสามารถใช้เวลาหลายเดือน (หรือหลายปี) ในการศึกษาซอร์สโค้ดที่ซับซ้อนของการใช้งาน JVM แบบโอเพ่นซอร์สที่มีอยู่(เช่นOpenJDKซึ่งมีซอร์สโค้ดหลายล้านเส้น)


20
"เป็นไปได้ว่า JVM ไร้เดียงสาที่ไม่เคยลบวัตถุและไม่ปล่อยหน่วยความจำอาจจะสอดคล้องกับสเปค" แน่นอนที่สุดมันสอดคล้องกับสเป็ค! Java 11 กำลังเพิ่มตัวรวบรวมขยะแบบไม่มี opสำหรับโปรแกรมอื่น ๆ ที่มีอายุสั้นมาก
Michael

6
"คุณไม่ควรสนใจเมื่อวัตถุถูกลบ" ไม่เห็นด้วย สำหรับหนึ่งคุณควรรู้ว่า RAII ไม่ใช่รูปแบบที่เป็นไปได้อีกต่อไปและคุณไม่สามารถพึ่งพาfinalizeการจัดการทรัพยากรใด ๆ (เช่น filehandles, การเชื่อมต่อฐานข้อมูล, ทรัพยากร gpu ฯลฯ )
Alexander

4
@Michael มันเหมาะสมสำหรับการประมวลผลแบบแบตช์ด้วยหน่วยความจำที่ใช้ ระบบปฏิบัติการสามารถพูดว่า "หน่วยความจำทั้งหมดที่ใช้โดยโปรแกรมนี้หายไปแล้ว!" หลังจากทั้งหมดซึ่งค่อนข้างเร็ว อันที่จริงมีการเขียนโปรแกรมหลายโปรแกรมใน C โดยเฉพาะอย่างยิ่งในโลกยูนิกซ์ยุคแรก ปาสกาลมีความน่ากลัวอย่างมาก "รีเซ็ตตัวชี้สแต็ก / กองเป็นจุดตรวจสอบที่บันทึกไว้ล่วงหน้า" ซึ่งอนุญาตให้คุณทำสิ่งเดียวกันได้มากแม้ว่ามันจะค่อนข้างไม่ปลอดภัย - ทำเครื่องหมายเริ่มงานย่อยรีเซ็ต
Luaan

6
@Alexander โดยทั่วไปนอกเหนือจาก C ++ (และบางภาษาที่จงใจนำมาใช้) โดยสมมติว่า RAII จะทำงานบน finalizers เพียงอย่างเดียวคือรูปแบบต่อต้านซึ่งควรได้รับการเตือนและแทนที่ด้วยบล็อกควบคุมทรัพยากรที่ชัดเจน จุดทั้งหมดของ GC คืออายุการใช้งานและทรัพยากรจะถูกแยกออกหลังจากทั้งหมด
Leushenko

3
@Lushushenko ฉันขอไม่เห็นด้วยอย่างยิ่งว่า "อายุการใช้งานและทรัพยากรจะแยกออก" เป็น "จุดทั้งหมด" ของ GC มันเป็นราคาติดลบที่คุณจ่ายสำหรับประเด็นหลักของ GC: การจัดการหน่วยความจำที่ง่ายและปลอดภัย "สมมติว่า RAII จะทำงานบนพื้นฐานของ finalizers เพียงอย่างเดียวคือการต่อต้านแบบ" ใน Java? บางที. แต่ไม่ได้อยู่ใน CPython, Rust, Swift หรือ Objective C "เตือนและแทนที่ด้วย Nope" บล็อกควบคุมทรัพยากรที่ชัดเจน "สิ่งเหล่านี้มีข้อ จำกัด อย่างเข้มงวดมากขึ้น วัตถุที่จัดการทรัพยากรผ่าน RAII ให้คุณจัดการเพื่อผ่านชีวิตที่กำหนดขอบเขต บล็อก try-with-resource จำกัด เพียงขอบเขตเดียว
Alexander

23

ในการใช้คำศัพท์ Objective-C การอ้างอิง Java ทั้งหมดจะ "แข็งแรง" โดยเนื้อแท้

ไม่ถูกต้อง - Java มีทั้งข้อมูลอ้างอิงที่อ่อนและอ่อนแม้ว่าจะมีการใช้งานที่ระดับออบเจ็กต์แทนที่จะเป็นคำหลักภาษา

ใน Objective-C หากวัตถุไม่มีการอ้างอิงที่แข็งแกร่งอีกต่อไปวัตถุนั้นจะถูกลบทันที

นั่นยังไม่ถูกต้องด้วย - Objective C บางรุ่นใช้ตัวเก็บขยะทั่วไป รุ่นอื่นไม่มีการเก็บขยะ

มันเป็นความจริงที่ Objective C เวอร์ชันใหม่กว่านั้นใช้การนับการอ้างอิงอัตโนมัติ (ARC) แทนที่จะใช้ GC แบบอิงการติดตามและสิ่งนี้ (บ่อยครั้ง) ส่งผลให้วัตถุถูก "ลบ" เมื่อจำนวนการอ้างอิงนั้นถึงศูนย์ อย่างไรก็ตามโปรดทราบว่าการนำ JVM ไปใช้นั้นสามารถปฏิบัติตามและทำงานตรงตามวิธีนี้ (heck มันอาจเป็นไปตามและไม่มี GC เลย)

ดังนั้นทำไมการปรับใช้ JVM ส่วนใหญ่จึงไม่ทำเช่นนี้และใช้อัลกอริทึม GC ที่อิงตามการติดตามแทน

พูดง่ายๆคือ ARC ไม่ได้เป็นยูโทเปียเหมือนที่ปรากฏครั้งแรก:

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

ARC มีข้อได้เปรียบแน่นอน - ง่ายต่อการนำไปใช้และการรวบรวมนั้นไม่แน่นอน แต่ข้อเสียข้างต้นคือเหตุผลที่การใช้งาน JVM ส่วนใหญ่จะใช้ GC แบบ generational และ trace


1
สิ่งที่ตลกคือแอปเปิ้ลเปลี่ยนไปใช้ ARC อย่างแม่นยำเพราะพวกเขาเห็นว่าในทางปฏิบัติมันมีประสิทธิภาพสูงกว่า GC อื่น ๆ อย่างมาก (โดยเฉพาะในรุ่นทั่วไป) เพื่อความเป็นธรรมนี่เป็นความจริงส่วนใหญ่บนแพลตฟอร์มที่ จำกัด หน่วยความจำ (iPhone) แต่ฉันจะตอบโต้คำสั่งของคุณว่า“ ARC ไม่ได้เป็นยูโทเปียตามที่ดูเหมือนครั้งแรก” โดยการกล่าวว่า GCs ทั่วไป (และอื่น ๆ ที่ไม่ได้กำหนดไว้) ไม่ได้เป็นยูโทเปียตามที่พวกเขาดูครั้งแรก: การทำลายล้างอาจเป็นตัวเลือกที่ดีกว่า สถานการณ์ส่วนใหญ่
Konrad Rudolph

3
@ KonradRudolph แม้ว่าฉันจะเป็นแฟนตัวยงของการทำลายล้างที่กำหนดเช่นกัน แต่ฉันไม่คิดว่า "ตัวเลือกที่ดีกว่าในสถานการณ์ส่วนใหญ่" ถือได้ แน่นอนว่าเป็นตัวเลือกที่ดีกว่าเมื่อเวลาแฝงหรือหน่วยความจำมีความสำคัญมากกว่าปริมาณงานเฉลี่ยและโดยเฉพาะอย่างยิ่งเมื่อตรรกะนั้นเรียบง่ายพอสมควร แต่มันไม่เหมือนกับแอปพลิเคชั่นที่ซับซ้อนจำนวนมากที่ต้องการการอ้างอิงแบบวนมากเป็นต้นและต้องการการทำงานที่รวดเร็วโดยเฉลี่ย แต่ไม่สนใจเวลาแฝงและมีหน่วยความจำมากมาย สำหรับสิ่งเหล่านี้เป็นที่น่าสงสัยว่า ARC เป็นความคิดที่ดีหรือไม่
leftaroundabout

1
@leftaroundabout ใน“ สถานการณ์ส่วนใหญ่” ทั้งปริมาณงานและความดันหน่วยความจำไม่เป็นคอขวดดังนั้นจึงไม่สำคัญเลย ตัวอย่างของคุณคือสถานการณ์จำลองหนึ่งสถานการณ์ จริงอยู่ที่มันไม่ใช่เรื่องแปลก แต่ฉันจะไม่ไปไกลเท่าที่อ้างว่ามันเป็นเรื่องธรรมดามากกว่าสถานการณ์อื่น ๆ ที่ ARC เหมาะสมกว่า นอกจากนี้ ARC สามารถจัดการกับรอบได้ดี มันแค่ต้องการความเรียบง่ายและการแทรกแซงด้วยตนเองโดยโปรแกรมเมอร์ สิ่งนี้ทำให้เป็นอุดมคติที่น้อยลง แต่แทบจะไม่เป็นตัวแบ่งข้อตกลง ฉันขอยืนยันว่าการสรุปกำหนดรูปแบบเป็นคุณลักษณะที่สำคัญกว่าที่คุณทำเป็น
Konrad Rudolph

3
@KonradRudolph ถ้า ARC ต้องการการแทรกแซงแบบแมนนวลอย่างง่ายโดยโปรแกรมเมอร์แล้วมันจะไม่จัดการกับวัฏจักร หากคุณเริ่มใช้รายการที่ลิงก์ทวีคูณอย่างหนัก ARC จะเปลี่ยนเป็นการจัดสรรหน่วยความจำด้วยตนเอง หากคุณมีกราฟขนาดใหญ่โดยพลการ ARC บังคับให้คุณเขียนตัวรวบรวมขยะ อาร์กิวเมนต์ GC จะเป็นว่าทรัพยากรที่ต้องการการทำลายไม่ใช่งานของระบบย่อยหน่วยความจำและเพื่อติดตามจำนวนที่ค่อนข้างน้อยพวกมันควรจะได้รับการกำหนดขั้นสุดท้ายด้วยการแทรกแซงด้วยตนเองโดยโปรแกรมเมอร์
prosfilaes

2
@KonradRudolph ARC และวนรอบจะนำไปสู่การรั่วไหลของหน่วยความจำหากไม่ได้จัดการด้วยตนเอง ในระบบที่ซับซ้อนเพียงพอการรั่วไหลที่สำคัญสามารถเกิดขึ้นได้หากเช่นวัตถุบางอย่างที่เก็บในแผนที่เก็บการอ้างอิงแผนที่นั้นการเปลี่ยนแปลงที่โปรแกรมเมอร์สามารถทำได้โดยไม่รับผิดชอบส่วนของการสร้างรหัสและการทำลายแผนที่นั้น กราฟขนาดใหญ่โดยพลการไม่ได้หมายความว่าพอยน์เตอร์ภายในไม่แข็งแรงซึ่งไม่เป็นไรสำหรับไอเท็มที่เชื่อมโยงกับการหายไป การจัดการกับปัญหาหน่วยความจำรั่วมีปัญหาน้อยกว่าการปิดไฟล์ด้วยตนเองหรือไม่ฉันจะไม่พูด แต่มันเป็นเรื่องจริง
prosfilaes

5

Java ไม่ได้ระบุอย่างแม่นยำเมื่อวัตถุได้รับการรวบรวมเพราะให้อิสระในการใช้งานเพื่อเลือกวิธีจัดการกับการเก็บขยะ

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

ในรหัสแบบมัลติเธรดค่าใช้จ่ายจะสูงกว่า มันเรียกร้องให้มีการเพิ่มขึ้น / ลดลงหรือล็อคอะตอมซึ่งทั้งสองอาจมีราคาแพง บนโปรเซสเซอร์ที่ทันสมัยการทำงานแบบปรมาณูอาจมีราคาสูงกว่าการลงทะเบียนแบบธรรมดาถึง 20 เท่า (แตกต่างอย่างชัดเจนจากตัวประมวลผลถึงตัวประมวลผล) สิ่งนี้สามารถเพิ่มค่าใช้จ่าย

ดังนั้นด้วยสิ่งนี้เราสามารถพิจารณาการแลกเปลี่ยนที่ทำโดยหลายรุ่น

  • Objective-C มุ่งเน้นไปที่ ARC - การนับการอ้างอิงอัตโนมัติ แนวทางของพวกเขาคือใช้การนับการอ้างอิงสำหรับทุกสิ่ง ไม่มีการตรวจจับรอบ (ที่ฉันรู้) ดังนั้นโปรแกรมเมอร์คาดว่าจะป้องกันไม่ให้รอบเกิดขึ้นซึ่งต้นทุนการพัฒนาเวลา ทฤษฎีของพวกเขาคือพอยน์เตอร์จะไม่ได้รับมอบหมายบ่อยครั้งและคอมไพเลอร์สามารถระบุสถานการณ์ที่จำนวนการอ้างอิงที่เพิ่มขึ้น / ลดลงไม่สามารถทำให้วัตถุตายได้และกำจัดการเพิ่มขึ้น / ลดลงอย่างสมบูรณ์ ดังนั้นจึงลดค่าใช้จ่ายในการนับการอ้างอิง

  • CPython ใช้กลไกไฮบริด พวกเขาใช้จำนวนการอ้างอิง แต่พวกเขายังมีตัวเก็บขยะที่ระบุรอบและเผยแพร่พวกเขา สิ่งนี้ให้ประโยชน์ของทั้งสองโลกโดยมีค่าใช้จ่ายของทั้งสองวิธี CPython จะต้องรักษาจำนวนการอ้างอิงและทำหนังสือเพื่อตรวจสอบวงจร CPython หลีกเลี่ยงสิ่งนี้ด้วยสองวิธี กำปั้นคือ CPython นั้นไม่ได้มีหลายเธรดอย่างสมบูรณ์ มันมีล็อคที่รู้จักในนาม GIL ซึ่ง จำกัด การทำงานหลายเธรด ซึ่งหมายความว่า CPython สามารถใช้การเพิ่ม / ลดลงตามปกติแทนที่จะเป็นอะตอมมิกซึ่งเร็วกว่ามาก CPython ก็ถูกตีความเช่นกันซึ่งหมายถึงการดำเนินการเช่นการมอบหมายให้ตัวแปรใช้คำสั่งจำนวนหนึ่งแล้วมากกว่า 1 ค่าใช้จ่ายเพิ่มเติมในการเพิ่ม / ลดลงซึ่งทำได้อย่างรวดเร็วในรหัส C นั้นเป็นปัญหาน้อยเพราะเรา ' เราได้ชำระค่าใช้จ่ายนี้แล้ว

  • Java ลงวิธีการที่ไม่รับประกันระบบการนับที่อ้างอิงเลย แน่นอนว่าข้อมูลจำเพาะไม่ได้พูดอะไรเกี่ยวกับวิธีการจัดการวัตถุอื่นนอกเหนือจากนั้นจะมีระบบการจัดการที่เก็บข้อมูลอัตโนมัติ อย่างไรก็ตามสเปคยังบ่งบอกถึงสมมติฐานอย่างมากว่าสิ่งนี้จะเป็นการรวบรวมขยะในวิธีที่จัดการกับรอบ โดยไม่ได้ระบุเมื่อวัตถุหมดอายุจาวาได้รับอิสรภาพในการใช้ตัวสะสมซึ่งไม่ต้องเสียเวลาเพิ่ม / ลด แน่นอนแอลกอร์ติห์ที่ฉลาดเช่นนักสะสมขยะทั่วไปสามารถจัดการกรณีง่าย ๆ ได้โดยไม่ต้องดูข้อมูลที่ถูกเรียกคืน (พวกเขาต้องดูข้อมูลที่ยังคงถูกอ้างอิงอยู่)

ดังนั้นเราจะเห็นได้ว่าทั้งสามคนนี้ต้องทำการแลกเปลี่ยนกัน ข้อตกลงที่ดีที่สุดนั้นขึ้นอยู่กับลักษณะของภาษาที่ต้องการใช้


4

แม้ว่าfinalizeหมูจะถูกสำรองไว้บน GC ของ Java แต่การเก็บขยะที่แกนของมันก็ไม่ได้สนใจวัตถุที่ตายแล้ว แต่เป็นวัตถุที่มีชีวิต ในระบบ GC บางระบบ (อาจรวมถึงการใช้งานบางอย่างของ Java) สิ่งเดียวที่แยกกลุ่มของบิตที่แสดงถึงวัตถุจากที่เก็บข้อมูลขนาดใหญ่ที่ไม่ได้ใช้สำหรับสิ่งใด ๆ อาจเป็นการอ้างอิงถึงอดีต ในขณะที่วัตถุที่มี finalizers ได้รับการเพิ่มเข้าไปในรายการพิเศษวัตถุอื่น ๆ อาจไม่มีอะไรในจักรวาลที่บอกว่าที่เก็บข้อมูลของพวกเขาเกี่ยวข้องกับวัตถุยกเว้นการอ้างอิงที่เก็บไว้ในรหัสผู้ใช้ เมื่อการอ้างอิงดังกล่าวถูกเขียนทับรูปแบบบิตในหน่วยความจำจะหยุดทันทีที่จะรับรู้เป็นวัตถุไม่ว่าอะไรก็ตามในจักรวาลจะรับรู้ได้หรือไม่

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

  1. ทำให้การอ้างอิงที่ไม่รัดกุมทำให้ระบุวัตถุที่ไม่มีการอ้างอิงที่เข้าถึงได้ง่ายซึ่งเชื่อมโยงกับวัตถุเหล่านั้น

  2. ค้นหารายการวัตถุของระบบด้วย finalizers เพื่อดูว่าวัตถุใดไม่มีการอ้างอิงที่เข้าถึงได้อย่างมาก

  3. ระบุและรวมภูมิภาคของที่เก็บข้อมูลซึ่งไม่ได้ถูกใช้โดยวัตถุใด ๆ

โปรดทราบว่าเป้าหมายหลักของ GC คือ # 3 และยิ่งรอนานกว่านั้นก่อนที่จะมีโอกาสมากขึ้นที่การรวมบัญชีจะมีโอกาสมากขึ้น มันสมเหตุสมผลที่จะทำ # 3 ในกรณีที่ใครจะมีการใช้งานทันทีสำหรับการจัดเก็บ แต่อย่างอื่นมันทำให้รู้สึกมากกว่าที่จะเลื่อนมัน


5
ที่จริงแล้ว gc มีเป้าหมายเดียวเท่านั้น: จำลองหน่วยความจำที่ไม่มีที่สิ้นสุด ทุกสิ่งที่คุณตั้งชื่อว่าเป็นเป้าหมายนั้นไม่สมบูรณ์ในสิ่งที่เป็นนามธรรมหรือการนำไปปฏิบัติอย่างละเอียด
Deduplicator

@Dupuplicator: การอ้างอิงที่อ่อนแอนำเสนอซีแมนทิกส์ที่มีประโยชน์ซึ่งไม่สามารถทำได้หากไม่ได้รับความช่วยเหลือจาก GC
supercat

แน่นอนว่าการอ้างอิงที่อ่อนแอนั้นมีความหมายที่เป็นประโยชน์ แต่ความหมายเหล่านั้นจะต้องใช้ถ้าการจำลองนั้นดีกว่าหรือไม่
Deduplicator

@Deduplicator: ใช่ พิจารณาคอลเล็กชันที่กำหนดว่าการอัพเดตจะโต้ตอบกับการแจงนับอย่างไร คอลเลกชันดังกล่าวอาจจำเป็นต้องมีการอ้างอิงที่อ่อนแอไปยัง enumerators สดใด ๆ ในระบบหน่วยความจำไม่ จำกัด คอลเลกชันที่มีการทำซ้ำหลาย ๆ ครั้งจะทำให้รายการของตัวแจงนับที่สนใจเติบโตขึ้นอย่างไม่มีขอบเขต หน่วยความจำที่จำเป็นสำหรับรายการนั้นจะไม่มีปัญหา แต่เวลาที่ใช้ในการวนซ้ำจะทำให้ประสิทธิภาพของระบบลดลง การเพิ่ม GC อาจหมายถึงความแตกต่างระหว่างอัลกอริทึม O (N) และ O (N ^ 2)
supercat

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

4

ให้ฉันแนะนำการเขียนใหม่และการวางคำถามทั่วไปของคุณ:

เหตุใด Java จึงไม่รับประกันที่แข็งแกร่งเกี่ยวกับกระบวนการ GC

เมื่อคำนึงถึงเรื่องนี้แล้วให้เลื่อนดูคำตอบอย่างรวดเร็วที่นี่ จนถึงตอนนี้มีเจ็ด (ไม่นับนี้) มีกระทู้ความคิดเห็นค่อนข้างน้อย

นั่นคือคำตอบของคุณ

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

แน่นอนว่ามีข้อเสียเปรียบแม้ในการตัดสินใจนั้นแน่นอน: โดยการรักษาสัญญาให้หลวม Java ส่วนใหญ่ * จะกำจัดความสามารถของโปรแกรมเมอร์ในการพึ่งพา destructors นี่คือสิ่งที่โปรแกรมเมอร์ C ++ โดยเฉพาะมักจะพลาด ([อ้างอิงที่จำเป็น];)) ดังนั้นจึงไม่ใช่การแลกเปลี่ยนที่ไม่มีนัยสำคัญ ฉันไม่ได้เห็นการอภิปรายของการตัดสินใจ meta นั้น แต่สันนิษฐานว่าคน Java ตัดสินใจว่าประโยชน์ของการมีตัวเลือก GC มากขึ้นเมื่อเทียบกับประโยชน์ของความสามารถในการบอกโปรแกรมเมอร์เมื่อวัตถุจะถูกทำลาย


* มีfinalizeวิธีการ แต่ด้วยเหตุผลต่าง ๆ ที่อยู่นอกขอบเขตสำหรับคำตอบนี้มันเป็นเรื่องยากและไม่ใช่ความคิดที่ดีที่จะพึ่งพา


3

มีกลยุทธ์ที่แตกต่างกันสองวิธีในการจัดการหน่วยความจำโดยไม่ต้องมีรหัสที่ชัดเจนซึ่งเขียนโดยผู้พัฒนา: การรวบรวมขยะและการนับการอ้างอิง

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

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

Speedwise การรวบรวมขยะจะเร็วขึ้นหากคุณเชื่อว่าแฟน ๆ ของการรวบรวมขยะและการนับการอ้างอิงนั้นเร็วขึ้นหากคุณเชื่อว่าแฟน ๆ ของการอ้างอิงอ้างอิง

มันเป็นเพียงสองวิธีที่แตกต่างกันเพื่อให้บรรลุเป้าหมายเดียวกัน Java เลือกหนึ่งวิธี Objective-C เลือกอีกวิธีหนึ่ง (และเพิ่มการสนับสนุนคอมไพเลอร์จำนวนมากเพื่อเปลี่ยนจากความเจ็บปวดในตัวเป็นสิ่งที่ใช้งานได้น้อยสำหรับนักพัฒนา)

การเปลี่ยน Java จากการรวบรวมขยะเป็นการนับการอ้างอิงจะเป็นภารกิจหลักเนื่องจากจำเป็นต้องมีการเปลี่ยนแปลงรหัสจำนวนมาก

ในทางทฤษฎี Java สามารถนำส่วนผสมของการรวบรวมขยะและการนับการอ้างอิง: ถ้านับการอ้างอิงเป็น 0 แล้ววัตถุไม่สามารถเข้าถึงได้ แต่ไม่จำเป็นต้องเป็นวิธีอื่น ๆ ดังนั้นคุณสามารถเก็บจำนวนการอ้างอิงและลบวัตถุได้เมื่อจำนวนการอ้างอิงของพวกเขาเป็นศูนย์ (จากนั้นเรียกใช้การรวบรวมขยะเป็นครั้งคราวเพื่อจับวัตถุภายในรอบการอ้างอิงที่ไม่สามารถเข้าถึงได้) ฉันคิดว่าโลกแบ่ง 50/50 ในคนที่คิดว่าการเพิ่มการอ้างอิงการนับไปยังการเก็บขยะเป็นความคิดที่ไม่ดีและผู้ที่คิดว่าการเพิ่มการรวบรวมขยะไปยังการนับการอ้างอิงเป็นความคิดที่ไม่ดี ดังนั้นนี่จะไม่เกิดขึ้น

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


ด้วยการนับการอ้างอิงการทำให้เป็นเรื่องเล็กน้อยในขณะที่โปรแกรมเมอร์ทำหน้าที่ดูแลวงจร เมื่อใช้ gc รอบจะไม่สำคัญ แต่โปรแกรมเมอร์จะต้องระมัดระวังในการจบ
Deduplicator

@Dupuplicator ใน Java มันเป็นไปได้ที่จะสร้างการอ้างอิงที่รัดกุมเพื่อวัตถุที่ถูกสรุป ... ใน Objective-C และ Swift เมื่อจำนวนการอ้างอิงเป็นศูนย์วัตถุจะหายไป
gnasher729

เพิ่งสังเกตเห็นตัวตรวจสอบการสะกดคำโง่แทนที่ deinit ด้วย deist ...
gnasher729

1
มีเหตุผลที่โปรแกรมเมอร์ส่วนใหญ่เกลียดการแก้ไขตัวสะกดอัตโนมัติ ... ;-)
Deduplicator

ฮ่า ๆ ... ฉันคิดว่าโลกแบ่ง 0.1 / 0.1 / 99.8 ระหว่างคนที่คิดว่าการเพิ่มการอ้างอิงการนับไปยังการรวบรวมขยะเป็นความคิดที่ไม่ดีและผู้ที่คิดว่าการเพิ่มการรวบรวมขยะเพื่อการอ้างอิงนับเป็นความคิดที่ไม่ดี คอยนับวันเรื่อย ๆ จนกว่าขยะจะมาถึงเพราะตันนั้นจะได้รับส่งกลิ่นอีกครั้ง ...
leftaroundabout

1

ข้อโต้แย้งด้านประสิทธิภาพอื่น ๆ ทั้งหมดและการอภิปรายเกี่ยวกับความยากลำบากในการทำความเข้าใจเมื่อไม่มีการอ้างอิงถึงวัตถุนั้นถูกต้องอีกต่อไปแม้ว่าความคิดอีกอย่างหนึ่งที่ฉันคิดว่าน่าพูดถึงก็คือ JVM (azul) ที่พิจารณาสิ่งนี้ ในนั้นมันใช้ gc แบบขนานที่เป็นหลักมีเธรด vm ตรวจสอบการอ้างอิงอย่างต่อเนื่องเพื่อพยายามลบมันซึ่งจะทำหน้าที่ไม่เหมือนกันทั้งหมดจากสิ่งที่คุณกำลังพูดถึง โดยทั่วไปมันจะดูรอบ ๆ ฮีปและพยายามเรียกคืนหน่วยความจำที่ไม่ได้อ้างอิง สิ่งนี้มีค่าใช้จ่ายประสิทธิภาพเล็กน้อย แต่นำไปสู่การเป็นศูนย์หรือเวลา GC สั้นมาก (นั่นคือถ้าขนาดฮีปที่ขยายอย่างต่อเนื่องเกินขนาดระบบ RAM และจากนั้น Azul ก็สับสนและมีมังกร)

TLDRบางอย่างเช่นนี้มีอยู่สำหรับ JVM มันเป็นเพียง jvm พิเศษและมีข้อเสียเปรียบเช่นการประนีประนอมทางวิศวกรรมอื่น ๆ

ข้อจำกัดความรับผิดชอบ: ฉันไม่มีความผูกพันกับ Azul เราเพิ่งใช้มันในงานก่อนหน้านี้


1

การเพิ่มทรูพุตที่ยั่งยืนหรือการลดความหน่วงแฝงของ gc ให้น้อยที่สุดนั้นเป็นความตึงเครียดแบบไดนามิกซึ่งอาจเป็นสาเหตุที่พบได้บ่อยที่สุดว่าทำไม GC ถึงไม่เกิดขึ้นทันที ในบางระบบเช่นแอพฉุกเฉิน 911 การไม่ผ่านเกณฑ์เวลาในการตอบสนองที่เฉพาะเจาะจงสามารถเริ่มทำให้กระบวนการทำงานล้มเหลวของไซต์ ในอื่น ๆ เช่นไซต์ธนาคารและ / หรืออนุญาโตตุลาการมันสำคัญยิ่งกว่าการเพิ่มปริมาณงานให้มากที่สุด


0

ความเร็ว

ทำไมสิ่งทั้งหมดนี้เกิดขึ้นในที่สุดเพราะความเร็ว 1,000,000,000,000,000,000,000,000,000,000,000 ต่อวินาทีจากนั้นคุณสามารถมีสิ่งที่ยาวและซับซ้อนอย่างไม่น่าเชื่อเกิดขึ้นระหว่างตัวดำเนินการแต่ละตัวเช่นทำให้แน่ใจว่าวัตถุที่ถูกอ้างอิงถูกลบออกไปแล้ว เนื่องจากจำนวนการดำเนินการต่อวินาทีนั้นไม่เป็นความจริงในขณะที่คำตอบอื่น ๆ ส่วนใหญ่อธิบายว่าจริง ๆ แล้วซับซ้อนและมีทรัพยากรจำนวนมากในการคิดสิ่งนี้การรวบรวมขยะมีอยู่เพื่อให้โปรแกรมสามารถมุ่งเน้นไปที่สิ่งที่พวกเขาพยายาม ลักษณะที่รวดเร็ว


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