มีวิธีที่ดีกว่าในการตั้งค่าระบบเหตุการณ์หรือไม่?


9

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

ขณะนี้ฉันมีสองวิธี:

  1. ง่ายที่สุด:วัตถุทั้งหมดจะถูกเพิ่มลงในเวกเตอร์เมื่อมีการส่งเหตุการณ์วัตถุทั้งหมดจะถูกส่งเหตุการณ์ผ่านมันเป็นวิธี handle_event ()

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

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

มีวิธีที่เร็วกว่า (ใช้เวลาฉลาด) หรือไม่? มีวิธีที่เร็วกว่าในการค้นหา int จากชนิดสตริงหรือไม่ (เริ่มแรกฉันมี enum แต่มันไม่อนุญาตให้ใช้ประเภทแบบกำหนดเองซึ่งมีความจำเป็นเนื่องจากระดับพลวัตที่ต้องการ)


1
นี่คือประเภทของแผนที่ Hash (หรือตารางแฮช) สำหรับสตริงจะได้รับการคำนวณลงไปที่หมายเลขแฮชซึ่งจะถูกใช้เพื่อค้นหาโดยตรงในอาร์เรย์ en.wikipedia.org/wiki/Hash_table
Patrick Hughes

คำถามที่ดีคือ: นี่เป็นปัญหาคอขวดของการแสดงหรือคุณแค่กังวลก่อนเวลาอันควรหรือไม่?
Jari Komppa

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

วัตถุ 100K ฟังดูยอดเยี่ยมมากสำหรับเกม นี่เป็นเซิร์ฟเวอร์หรือแอปพลิเคชันไคลเอนต์ผู้ใช้ปลายทางหรือไม่
Patrick Hughes

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

คำตอบ:


5

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

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


คอขวดนั้นไม่ใหญ่มาก (สำหรับวัตถุ 100,000 ชิ้นมันเสีย. 0000076 ms / วัตถุ) แต่ฉันคิดว่าความคิดของคุณเป็นความคิดที่ยอดเยี่ยม! ฉันคิดว่าฉันจะทำการค้นหา ID เพียงครั้งเดียวและเก็บ eventID ไว้เป็น int แทนที่จะเป็นข้อมูลสตริงดั้งเดิม และฉันไม่เคยนึกถึงรายการที่เชื่อมโยงความคิดที่ดี
ultifinitus

1
+1 สำหรับการประมวลผลรหัสล่วงหน้า นอกจากนี้คุณยังสามารถทำมันได้อย่างเฉื่อยชาโดยมีประเภท EventType EventType takeDamageEvent = EventSystem::CacheEventType("takeDamageEvent");ว่าแต่ละโมดูลจะได้รับผ่านทางบางอย่างเช่น ทำให้มันเป็นสมาชิกแบบคงที่ของคลาสและคุณจะมีเพียงหนึ่งสำเนาที่ลอยอยู่ในแต่ละชั้นที่ต้องการ
michael.bartnett

2
โปรดทราบว่าการจัดเก็บรหัสแทนสตริงจะทำให้การดีบักค่อนข้างยาก เป็นประโยชน์เสมอที่จะสามารถเห็นข้อความที่ระบุว่าวัตถุมาจากไหน คุณสามารถไปได้ครึ่งทางโดยการจัดเก็บทั้ง id และสตริงซึ่งคุณเก็บไว้รอบ ๆ เพื่อวัตถุประสงค์ในการดีบั๊ก (อาจถูกลบออกไปใน build build)
Nicol Bolas

2

เอาของง่าย ๆ ออกไปก่อน คุณมีสิ่งนี้mapระหว่างสตริง (ชื่อของเหตุการณ์น่าจะเป็น) และจำนวนเต็ม (ดัชนีของฟังเหตุการณ์ที่ลงทะเบียน)

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

สมมติว่าคุณกำลังใช้std::stringและoperator<เพื่อการเปรียบเทียบ สิ่งนี้ไม่มีประสิทธิภาพสูง มันเป็นการเปรียบเทียบที่ชาญฉลาด คุณไม่สนใจเกี่ยวกับสตริงจริงน้อยกว่าการเปรียบเทียบ; คุณเพียงแค่ต้องการการเปรียบเทียบบางอย่างที่ให้การสั่งซื้อที่เข้มงวด (เพราะmapไม่ได้ผล)

ดังนั้นคุณควรใช้ 32 std::stringไบต์สตริงความยาวคงแทน ฉันใช้สิ่งเหล่านี้เป็นตัวระบุ การทดสอบเปรียบเทียบสำหรับสตริงคงที่เหล่านี้ไม่ได้ทำการเปรียบเทียบแบบไบต์ พวกเขาทำการเปรียบเทียบแบบ 32- บิต (หรือ 64- บิต) แทน มันจะใช้เวลาทุก 4 ไบต์เป็นจำนวนเต็มไม่ได้ลงนามและเปรียบเทียบกับ 4 ไบต์ที่สอดคล้องกันของสายอื่น ๆ ด้วยวิธีนี้การเปรียบเทียบจะใช้การเปรียบเทียบสูงสุด 8 รายการเท่านั้น มันช่วยให้มั่นใจการสั่งซื้อที่เข้มงวดอ่อนแอแม้ว่าการสั่งซื้อไม่มีอะไรเกี่ยวข้องกับข้อมูลเป็นตัวละคร

การจัดเก็บสตริงที่ยาวกว่า 31 ไบต์ (ต้องการอักขระ NULL) ตัดปลายสตริง (แต่จากตรงกลางแทนที่จะเป็นส่วนท้ายฉันพบว่าเอนโทรปีมีแนวโน้มที่จะยิ่งใหญ่ที่สุดในตอนต้นและตอนท้าย) \0และสตริงสั้นกว่าแผ่นที่ออกตัวอักษรที่เหลือด้วย

ตอนนี้คุณสามารถทิ้งmapทั้งหมดและใช้ตารางแฮช หากคุณมีประเภทเหตุการณ์มากกว่า 100,000 ประเภทจริง ๆ นี่อาจเป็นความคิดที่ดี แต่ฉันไม่รู้เกมที่จะเป็นสิ่งที่สมเหตุสมผลจากระยะไกล


ดังนั้นคุณควรใช้สตริงที่มีความยาวคงที่ 32 ไบต์แทนที่จะเป็นสตริง std :: Fantastic! ฉันไม่คิดว่าจะเปลี่ยนประเภทสตริง
ultifinitus

0

ในการตอบคำถามทั่วไป:

วิธีที่ดีกว่าในการตั้งค่าระบบเหตุการณ์

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

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

วิธีที่ดีที่สุดคือการศึกษาระบบเหตุการณ์ประเภทต่างๆจากนั้นคุณจะมีข้อมูลว่าควรใช้ระบบใด

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

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