แนวทางปฏิบัติที่ดีที่สุดในการสร้างวัตถุชั่วคราวขนาดเล็กหลายล้านชิ้น


109

"แนวทางปฏิบัติที่ดีที่สุด" สำหรับการสร้าง (และปล่อย) วัตถุขนาดเล็กหลายล้านชิ้นคืออะไร

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

  1. ลดค่าใช้จ่ายในการจัดเก็บขยะและ
  2. ลดการใช้หน่วยความจำสูงสุดสำหรับระบบระดับล่าง

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

ฉันไม่ได้คาดหวังโค้ดตัวอย่างที่สมบูรณ์ แต่ฉันขอขอบคุณสำหรับคำแนะนำสำหรับการอ่าน / การค้นคว้าเพิ่มเติมหรือตัวอย่างโอเพนซอร์สที่มีลักษณะคล้ายกัน


11
รูปแบบฟลายเวทเหมาะกับกรณีของคุณหรือไม่? en.wikipedia.org/wiki/Flyweight_pattern
Roger Rowland

4
คุณจำเป็นต้องห่อหุ้มไว้ในวัตถุหรือไม่?
nhahtdh

1
รูปแบบฟลายเวทไม่เหมาะสมเนื่องจากวัตถุไม่แบ่งปันข้อมูลทั่วไปที่สำคัญ สำหรับการห่อหุ้มข้อมูลในออบเจ็กต์นั้นมีขนาดใหญ่เกินไปที่จะบรรจุลงในแบบดั้งเดิมซึ่งเป็นสาเหตุที่ฉันกำลังมองหาทางเลือกอื่นสำหรับ POJO
Humble Programmer

2
ขอแนะนำให้อ่าน: cs.virginia.edu/kim/publicity/pldi09tutorials/…
rkj

คำตอบ:


47

เรียกใช้แอปพลิเคชันด้วยการรวบรวมขยะแบบละเอียด:

java -verbose:gc

และจะแจ้งให้คุณทราบเมื่อรวบรวม การกวาดจะมีสองประเภทคือการกวาดแบบเร็วและแบบเต็ม

[GC 325407K->83000K(776768K), 0.2300771 secs]
[GC 325816K->83372K(776768K), 0.2454258 secs]
[Full GC 267628K->83769K(776768K), 1.8479984 secs]

ลูกศรอยู่ก่อนและหลังขนาด

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

การอ่านJava SE 6 HotSpot Virtual Machine Garbage Collection Tuningน่าจะเป็นประโยชน์


ทดลองกับขนาดฮีป Java เพื่อหาจุดที่การเก็บขยะเต็มหายาก ใน Java 7 G1 GC ใหม่เร็วกว่าในบางกรณี (และช้ากว่าในรุ่นอื่น ๆ )
Michael Shopsin

21

ตั้งแต่เวอร์ชัน 6 เป็นต้นมาโหมดเซิร์ฟเวอร์ของ JVM ใช้เทคนิคการวิเคราะห์การหลบหนี ใช้มันคุณสามารถหลีกเลี่ยง GC ทั้งหมดด้วยกัน


1
การวิเคราะห์การหลบหนีมักจะทำให้ผิดหวังคุณควรตรวจสอบว่า JVM ได้ทราบสิ่งที่คุณกำลังทำอยู่หรือไม่
Nitsan Wakart

2
หากคุณมีประสบการณ์ในการใช้ตัวเลือกเหล่านี้: -XX: + PrintEscapeAnalysis และ -XX: + PrintEliminateAllocations จะเป็นการดีที่จะแบ่งปัน เพราะฉันไม่พูดตรงๆ
Mikhail

ดูstackoverflow.com/questions/9032519/…คุณจะต้องได้รับการสร้างดีบักสำหรับ JDK 7 ฉันยอมรับว่าฉันไม่ได้ทำอย่างนั้น แต่ด้วย JDK 6 มันประสบความสำเร็จ
Nitsan Wakart

19

มีคำถามหลายข้ออยู่ที่นี่!

1 - วัตถุอายุสั้นมีการจัดการอย่างไร?

ตามที่ระบุไว้ก่อนหน้านี้ JVM ได้อย่างสมบูรณ์แบบสามารถจัดการกับจำนวนมากของวัตถุอายุสั้นเพราะมันเป็นไปตามที่อ่อนแอ Generational สมมติฐาน

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

for(int i=0, i<max, i++) {
  // stuff that implies i
}

อย่าคิดเกี่ยวกับการคลายการวนซ้ำ (การเพิ่มประสิทธิภาพที่ JVM ดำเนินการอย่างมากกับโค้ดของคุณ) ถ้าmaxเท่ากับInteger.MAX_VALUEคุณวนซ้ำอาจใช้เวลาสักครู่ในการดำเนินการ อย่างไรก็ตามiตัวแปรจะไม่หนีจากลูปบล็อก ดังนั้น JVM จะใส่ตัวแปรนั้นในทะเบียน CPU โดยเพิ่มขึ้นเป็นประจำ แต่จะไม่ส่งกลับไปยังหน่วยความจำหลัก

ดังนั้นการสร้างวัตถุหลายล้านชิ้นจึงไม่ใช่เรื่องใหญ่หากใช้เฉพาะในพื้นที่เท่านั้น พวกมันจะตายก่อนที่จะถูกเก็บไว้ในสวนอีเดนดังนั้น GC จะไม่สังเกตเห็นพวกมันด้วยซ้ำ

2 - การลดค่าใช้จ่ายของ GC มีประโยชน์หรือไม่?

ตามปกติมันขึ้นอยู่กับ

ขั้นแรกคุณควรเปิดใช้งานการบันทึก GC เพื่อให้มีมุมมองที่ชัดเจนเกี่ยวกับสิ่งที่เกิดขึ้น คุณสามารถเปิดใช้งานได้ด้วย-Xloggc:gc.log -XX:+PrintGCDetailsไฟล์.

หากแอปพลิเคชันของคุณใช้เวลาส่วนใหญ่ในวงจร GC ใช่ให้ปรับ GC มิฉะนั้นอาจไม่คุ้มค่าจริงๆ

ตัวอย่างเช่นหากคุณมี GC รุ่นเยาว์ทุกๆ 100 มิลลิวินาทีที่ใช้เวลา 10 มิลลิวินาทีคุณใช้เวลา 10% ใน GC และคุณมี 10 คอลเลคชันต่อวินาที (ซึ่งก็คือ huuuuge) ในกรณีเช่นนี้ฉันจะไม่ใช้เวลาในการปรับ GC เลยเพราะ 10 GC / s เหล่านั้นจะยังคงอยู่ที่นั่น

3 - ประสบการณ์บางอย่าง

ฉันมีปัญหาคล้าย ๆ กันกับแอปพลิเคชันที่กำลังสร้างชั้นเรียนจำนวนมาก ในบันทึก GC ฉันสังเกตเห็นว่าอัตราการสร้างแอปพลิเคชันอยู่ที่ประมาณ 3 GB / s ซึ่งมากเกินไป (มีข้อมูล ... 3 กิกะไบต์ต่อวินาที?!)

ปัญหา: GC บ่อยเกินไปที่เกิดจากการสร้างวัตถุมากเกินไป

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

  • ทำอัลกอริทึมใหม่เพื่อที่ฉันจะไม่ส่งคืนบูลีนคู่หนึ่ง แต่ฉันมีสองวิธีที่ส่งคืนแต่ละบูลีนแยกกัน

  • แคชวัตถุโดยทราบว่ามีเพียง 4 อินสแตนซ์ที่แตกต่างกัน

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

อัตราการจัดสรรลดลงเหลือ 1 GB / s และความถี่ของ Young GC ก็เช่นกัน (หารด้วย 3)

หวังว่าจะช่วยได้!


11

ถ้าคุณมีแค่ออบเจ็กต์ที่มีค่า (นั่นคือไม่มีการอ้างอิงถึงอ็อบเจกต์อื่น ๆ ) และจริงๆ แต่ฉันหมายถึงตันและตันจริงๆคุณสามารถใช้โดยตรงByteBuffersกับการเรียงลำดับไบต์เนทีฟ [อันหลังมีความสำคัญ] และคุณต้องมีสองสามร้อยบรรทัด รหัสเพื่อจัดสรร / ใช้ซ้ำ + getter / setters Getters มีลักษณะคล้ายกับlong getQuantity(int tupleIndex){return buffer.getLong(tupleInex+QUANTITY_OFFSSET);}

นั่นจะช่วยแก้ปัญหา GC ได้เกือบทั้งหมดตราบเท่าที่คุณจัดสรรเพียงครั้งเดียวนั่นคือก้อนใหญ่แล้วจัดการวัตถุด้วยตัวเอง แทนที่จะอ้างอิงคุณจะมีเพียงดัชนี (นั่นคือint) ลงในสิ่งByteBufferที่จะต้องส่งต่อไป คุณอาจต้องทำการจัดตำแหน่งหน่วยความจำด้วยตัวเองเช่นกัน

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

นอกเหนือจากนั้นเป็นไปได้ว่าคุณไม่ต้องการแนวทางเช่นนี้เนื่องจากคนรุ่นใหม่ของ JVM เกือบทั้งหมดเสียชีวิตเล็กน้อยและต้นทุนการจัดสรรเป็นเพียงตัวชี้ ค่าใช้จ่ายในการจัดสรรอาจสูงขึ้นเล็กน้อยหากคุณใช้finalฟิลด์เนื่องจากต้องใช้รั้วหน่วยความจำในบางแพลตฟอร์ม (เช่น ARM / Power) บน x86 ฟรี


8

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

  • มัลติเธรด: การใช้เธรดโลคัลพูลอาจใช้ได้กับกรณีของคุณ
  • โครงสร้างข้อมูลสำรอง: พิจารณาใช้ ArrayDeque เนื่องจากทำงานได้ดีในการลบและไม่มีค่าใช้จ่ายในการจัดสรร
  • จำกัด ขนาดสระของคุณ :)

วัดก่อน / หลัง ฯลฯ ฯลฯ


6

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

ตัวอย่างเช่น MouseEvent มีการอ้างอิงถึงคลาส Point เราแคชคะแนนและอ้างอิงถึงจุดเหล่านี้แทนที่จะสร้างอินสแตนซ์ใหม่ เช่นเดียวกับตัวอย่างเช่นสตริงว่าง

อีกแหล่งหนึ่งคือบูลีนหลายตัวซึ่งถูกแทนที่ด้วยหนึ่ง int และสำหรับแต่ละบูลีนเราใช้ int เพียงหนึ่งไบต์


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

@Axel วัตถุใช้หน่วยความจำน้อยกว่ามากดังนั้น GC จึงไม่ถูกเรียกบ่อยนัก แน่นอนว่าเราทำโปรไฟล์แอปของเรา แต่ยังมีเอฟเฟกต์ภาพของความเร็วที่ดีขึ้น
StanislavL

6

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

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

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


2

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

หากคุณต้องการพลังที่แสดงออกให้ใช้วัตถุ หากคุณต้องการความเร็ว (ในกรณีนี้) ไปที่เนทีฟ


1

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

หากไม่สามารถทำได้ด้วยเหตุผลบางประการและคุณต้องการลดการใช้หน่วยความจำสูงสุดบทความดีๆเกี่ยวกับประสิทธิภาพของหน่วยความจำอยู่ที่นี่: http://www.cs.virginia.edu/kim/publicity/pldi09tutorials/memory-efficient-java- tutorial.pdf


ลิงค์ตาย. มีแหล่งอื่นสำหรับบทความนั้นหรือไม่?
dnault

0

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


1
ขอโทษเพื่อนฉันไม่เห็นด้วยกับแนวทางของคุณ ... Java ก็เหมือนกับภาษาโปรแกรมใด ๆ ที่เกี่ยวกับการแก้ปัญหาภายในข้อ จำกัด ถ้า OP ถูก จำกัด โดย GC คุณจะช่วยเขาอย่างไร
Nitsan Wakart

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

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

0

ฉันคิดว่าคุณควรอ่านเกี่ยวกับการจัดสรรสแต็กใน Java และการวิเคราะห์ Escape

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

มีคำอธิบายวิกิพีเดียเกี่ยวกับการวิเคราะห์การหลบหนีพร้อมตัวอย่างวิธีการทำงานใน Java:

http://en.wikipedia.org/wiki/Escape_analysis


0

ฉันไม่ใช่แฟนตัวยงของ GC ดังนั้นฉันจึงพยายามหาวิธีต่างๆอยู่เสมอ ในกรณีนี้ฉันขอแนะนำให้ใช้รูปแบบ Object Pool :

แนวคิดคือหลีกเลี่ยงการสร้างวัตถุใหม่โดยเก็บไว้ในกองซ้อนเพื่อให้คุณสามารถนำมาใช้ซ้ำได้ในภายหลัง

Class MyPool
{
   LinkedList<Objects> stack;

   Object getObject(); // takes from stack, if it's empty creates new one
   Object returnObject(); // adds to stack
}

3
การใช้พูลสำหรับอ็อบเจ็กต์ขนาดเล็กนั้นค่อนข้างเป็นความคิดที่ไม่ดีคุณต้องมีพูลต่อเธรดเพื่อบูต (หรือการเข้าถึงแบบแชร์จะทำลายประสิทธิภาพใด ๆ ) สระว่ายน้ำดังกล่าวยังทำงานได้แย่กว่าคนเก็บขยะที่ดี สุดท้าย: GC เป็นสิ่งที่มาจากสวรรค์เมื่อต้องจัดการกับรหัส / โครงสร้างพร้อมกัน - อัลกอริทึมจำนวนมากใช้งานได้ง่ายกว่าอย่างมากเนื่องจากเป็นธรรมชาติไม่มีปัญหา ABA อ้างอิง การนับในสภาพแวดล้อมพร้อมกันต้องใช้การดำเนินการของอะตอม + รั้วหน่วยความจำเป็นอย่างน้อย (LOCK ADD หรือ CAS บน x86)
ที่สุด

1
ผู้จัดการของวัตถุในสระว่ายน้ำที่อาจจะมากขึ้นแพงกว่าการปล่อยให้วิ่งเก็บขยะ
Thorbjørn Ravn Andersen

@ ThorbjørnRavnAndersenโดยทั่วไปฉันเห็นด้วยกับคุณ แต่โปรดทราบว่าการตรวจจับความแตกต่างดังกล่าวค่อนข้างเป็นเรื่องท้าทายและเมื่อคุณสรุปได้ว่า GC ทำงานได้ดีกว่าในกรณีของคุณมันจะต้องเป็นกรณีที่ไม่เหมือนใครมากหากความแตกต่างนั้นมีความสำคัญ ในทางกลับกันอาจเป็นไปได้ว่า Object pool จะบันทึกแอปของคุณ
Ilya Gazman

1
ฉันไม่ได้รับการโต้แย้งของคุณ? มันยากมากที่จะตรวจพบว่า GC เร็วกว่าการรวมวัตถุหรือไม่? ดังนั้นคุณควรใช้ object pooling? JVM เหมาะสำหรับการเข้ารหัสที่สะอาดและวัตถุที่มีอายุสั้น หากคำถามเหล่านี้เป็นคำถามเกี่ยวกับ (ซึ่งฉันหวังว่าถ้า OP สร้างหนึ่งล้านครั้งต่อวินาที) ควรเป็นก็ต่อเมื่อมีข้อได้เปรียบที่พิสูจน์ได้ในการเปลี่ยนไปใช้รูปแบบที่ซับซ้อนและมีแนวโน้มที่จะเกิดข้อผิดพลาดตามที่คุณแนะนำ ถ้าเรื่องนี้ยากเกินไปที่จะพิสูจน์แล้วจะรำคาญทำไม
Thorbjørn Ravn Andersen

0

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

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