Data-Oriented สายเกมส์

สายเกมส์เขามีข้อจำกัดที่ไม่เหมือนสาย web backend ทำนองว่าถ้าเกมส์ frame rate ต่ำเกินไป ซื้อ PS5 มาเพิ่มอีกแปดสิบเครื่องก็ช่วยอะไรไม่ได้ แต่ถ้าเป็นงาน web backend ก็อาจจะพอช่วยได้ ก่อนหน้านี้ผมได้ยิน Data Driven Programming มากจากทางชุมชน Clojure ที่ Yehonathan Sharvit บอกว่าพยายามแก้ปัญหาความซับซ้อนของระบบและสรุปหลักการมา 3 ข้อว่า

  1. แยกระหว่าง code กับ data
  2. ใช้ data structure ที่มัน generic ไปเลย
  3. ไม่ mutate data

นอกจากนั้น Clojure History ก็ว่าถึงเรื่อง Concurrency ด้วย

ซึ่งจากทั้งสองแหล่งไม่ได้เน้นเรื่องว่าโปรแกรมจะรันเร็ว

ส่วน Data-Oriented Design ของสายเกมส์ ส่วนต่างที่ผมเห็นก็คือเรื่องความเร็วในการรัน ในวิดีโอนี้เขา claim ว่าโปรแกรมเขารันเร็วขึ้นหกเท่า ด้วยการไปจัดการเรื่อง Cache utiliztion ส่วนหลักการอื่น ๆ ผมมองว่าก็คล้าย ๆ Data Driven Programming ล่ะกระทั่งเรื่อง Parallelization ก็เป็นหลักการแบบที่คล้าย ๆ กัน

Cache utilization มันสำคัญกับเกมส์เดี๋ยวนี้มากเพราะว่าคนส่วนมากก็ไม่ค่อยได้เขียนเกมส์ขายบน Commodore 64 ที่ใช้ MOS Technology 6510 อีกต่อไปแล้ว ส่วนมากน่าจะใช้ AMD Ryzen ไม่ก็ Qualcomm Snapdragon ซึ่งทำงานเร็วกว่า RAM มาก ๆ ทำให้ต้องมี cache memory ขึ้นมาซึ่งเร็วมากแต่มีน้อย ดังนั้นถ้าเราเอา data ที่ไม่จำเป็นมาอยู่ใน cache เยอะ ๆ ก็จะทำให้ต้องโหลดข้อมูลขึ้น cache ใหม่บ่อย ๆ ใน วิดีโอนี้ Mike Acton ยกตัวอย่าง struct ของ key value เวลาเราค้นหาข้อมูลส่วนมากเราก็วิ่งไล่ค้นตาม key ส่วน value ก็นาน ๆ จะได้ใช้ที แต่การที่เอามาใส่ struct เดียวกันก็หลายเป็นว่า value โดนโหลดใส่ cache ไปด้วย อีกกรณีหนึ่งจาก วิดีโอนี้ โดย Stoyan Nikolov พวก status flag ใน object ที่ถูก if บ่อย ๆ อันนี้ก็อาจจะทำให้ต้องโหลด object ขึ้น cache แล้วแค่ไปตรวจ flag แล้วก็ไปโหลดอีก object นึงมาก็ใช้ได้ ซึ่งแก้ได้โดยการแยก object ให้ไปอยู่ใน vector คนละตัวกันไปเลย

ส่วนต่างอีกอย่างหนึ่งที่ปรากฎใน code คือทาง Clojure มักจะใช้ Persistent map มาเก็บข้อมูลส่วนทางสายเกมส์ที่ใช้ C++ มักจะใช้ struct เวลาที่ต้องการให้ immutable ก็คือ copy struct นั้นเอาเลย

ส่วนที่เหมือนกันของทั้งค่าย Data-Driven Programming กับ Data-Oriented Design คือมองว่า code เป็นตัว transform (xform) data จากตัวหนึ่งไปอีกตัวหนึ่ง ผมก็นึกขึ้นมาเลยว่าแบบนี้ก็เข้าทาง Rust ที่โปรแกรมประกอบขึ้นมาจาก Expression ที่ทุกอย่าง return ค่าออกมาหมดเลยหนิ แล้วก็เจอจริง ๆ game engine ที่เขียนด้วย Rust แบบ data driven มีสองตัวเลยคือ Bevy และ Amethyst สังเกตว่าใช้ทั้ง Data-Driven และ Data-Oriented เลยครับ ก็เลยไม่แน่ใจว่าเป็นคำที่ใช้แทนกันได้เลยหรือเปล่า