DOOM ที่ทำงานด้วย type ของ TypeScript [วิดีโอ]
(youtube.com)- นี่คือการทดลองที่บูตเกม DOOM ปี 1993 และแสดงเฟรมแรกออกมาโดยไม่ใช้รันไทม์โค้ด แต่ใช้ ระบบ type ของ TypeScript เพียงอย่างเดียว
- กว่าจะแสดงเฟรมแรกได้ ตัวตรวจสอบ type ของ TypeScript ต้องประมวลผล 3.5 ล้านล้านบรรทัด รวมขนาดทั้งหมด 177TB ตลอด 12 วัน โดยเดิมทีประเมินไว้ว่าจะต้องใช้ 1.25PB และใช้เวลามากกว่า 3 เดือน
- แกนหลักของการสร้างคือ เครื่องเสมือน WebAssembly ที่สร้างขึ้นด้วย type โดยนำคำสั่ง 116 รายการที่ DOOM ต้องใช้มาสร้างเป็นตรรกะระดับ type และประเมินคำสั่งทั้งหมด 18 ล้านรายการ
- ระหว่างพัฒนา ได้ถอดข้อจำกัดของคอมไพเลอร์เกี่ยวกับการเรียกซ้ำ ยูเนียน ทูเพิล และการ instantiate type แบบลึกออกไป แต่ผลลัพธ์สุดท้ายยังคงอยู่ในรูป TypeScript มาตรฐาน ที่ผู้ใช้สามารถรันได้
- เพราะเป็นงานที่ใหญ่กว่าการตรวจ type ของแอปทั่วไปมาก เครื่องมือพัฒนาเดิมแทบใช้งานไม่ได้เลย และต้องสร้างชุดทดสอบ 12,364 รายการกับเครื่องมือเฉพาะขึ้นมาเอง
คอมพิวเตอร์ที่สร้างไว้ในระบบ type ของ TypeScript
- DOOM ทำงานไม่ได้ผ่านการรัน JavaScript ปกติ แต่ทำงานอยู่ภายใน ระบบ type ของ TypeScript เท่านั้น
- เป้าหมายคือการสร้าง เครื่องเสมือน WebAssembly ที่สามารถรันโปรแกรมอื่นได้ด้วย type เพียงอย่างเดียว โดยไม่ใช้กลลวงหรือภาษาอื่นมาช่วยรัน
- คอมพิวเตอร์ระดับ type นี้มีองค์ประกอบพื้นฐานที่จำเป็นต่อการทำงานอยู่ในรูป type
- RAM
- พื้นที่ดิสก์
- คอลล์สแตก
- ซับรูทีน
- ตัวชี้หน่วยความจำ
- บริบทรันไทม์
- เครื่องมือพัฒนาแบบกำหนดเอง
- คำสั่ง WebAssembly 116 รายการ ที่จำเป็นต่อการรัน DOOM ถูกสร้างเป็นตรรกะด้วย type ของ TypeScript
- เพียงตรรกะชุดนี้ก็ทำให้ตัวตรวจสอบ type ต้องประเมินคำสั่ง 18 ล้านรายการ ทีละรายการ โดยแต่ละคำสั่งแสดงถึงสถานะเครื่องเฉพาะของระบบ
ขนาดงานกว่าจะถึงเฟรมแรก
- การได้เฟรมแรกของ DOOM ต้องใช้ type ถึง 3.5 ล้านล้านบรรทัด และมีขนาดรวม 177TB
- มีการรันคอมไพเลอร์ TypeScript
TSCต่อเนื่องเป็นเวลา 12 วันเพื่อบูตเกมและให้ได้เฟรมแรก - จากการคำนวณเบื้องต้น คอมพิวเตอร์จะต้องประมวลผล type ของ TypeScript ถึง 1.25PB และคาดว่าจะใช้เวลามากกว่า 3 เดือน
- หลังการปรับแต่งอย่างสุดขั้ว จึงลดลงมาเหลือ 177TB และ 12 วัน
- โดยปกติการตรวจ type ของ
TSCในแอปทั่วไปอยู่ที่ระดับ การ instantiate type 200,000~500,000 ครั้ง แต่โปรเจกต์นี้รักษาระดับ 20 ล้านครั้งต่อวินาที ตลอด 12 วัน - ผลลัพธ์สุดท้ายเป็นอ็อบเจ็กต์ TypeScript ซึ่งแต่ละค่าจะแทนพิกเซลหนึ่งบรรทัด
- เฟรมเอาต์พุตมีขนาด 320×200
- เป็นเฟรม ASCII รวม 128,000 พิกเซล
- ยังมีวิธีควบคุมเกมผ่านอินพุตจากคีย์บอร์ดด้วย
กลไกป้องกันของ TypeScript ที่ถอดออกระหว่างพัฒนา
- ผลลัพธ์สุดท้ายคือ TypeScript มาตรฐาน ที่ผู้ใช้สามารถรันได้ด้วยตัวเอง
- เพื่อให้การทดลองนี้เป็นไปได้ จึงมีการแก้ไขคอมไพเลอร์ TypeScript และถอดข้อจำกัดหลายอย่างออก
- ถอดข้อจำกัดความลึกของสแตกที่มากเกินไปขณะเปรียบเทียบ type
- ถอดข้อจำกัดการ instantiate type ที่ลึกเกินไปหรืออาจไม่สิ้นสุด
- ตั้งขนาดสูงสุดของยูเนียนและทูเพิลเป็น Infinity
- ถอดข้อจำกัดการตัดทอนเอาต์พุต
- ถอด ข้อจำกัดด้านการเรียกซ้ำ อันเลื่องชื่อของ TypeScript
- ยังเพิ่มข้อจำกัดสแตกของตัวคอมพิวเตอร์เองด้วย
- เมื่อเอากลไกป้องกันเหล่านี้ออก ตัวตรวจสอบ type ก็สามารถใช้หน่วยความจำ 100GB ได้อย่างง่ายดาย
- แต่ราคาที่ต้องจ่ายก็สูงมาก
- ปัญหาเล็กน้อยอย่างการพิมพ์
importผิด ก็อาจทำให้เกิดลูปไม่รู้จบได้ - การจัดสรรฮีปอาจกินหน่วยความจำทั้งหมดจนทั้งระบบล่มได้
- สแตกเทรซมีขนาดมหาศาล และส่วนใหญ่จะล้มเหลวแบบหยุดนิ่งไปเฉยๆ
- ปัญหาเล็กน้อยอย่างการพิมพ์
สิ่งที่ต้องสร้างเพิ่มเพื่อให้ DOOM รันได้
- หลังทำงานมา 6 เดือน สามารถรันโปรแกรม C ขนาดเล็กได้แล้ว แต่การ รัน DOOM ต้องมีการสร้างเพิ่มอีกมาก
- ต้องเข้ารหัสองค์ประกอบทั้งหมดของ DOOM ให้อยู่ในรูป type
- แผนที่เกม
- เท็กซ์เจอร์
- สไปรต์
- เสียง
- AI ของศัตรู
- อาวุธ
- ไอเท็ม
- เอนจินฟิสิกส์
- ซับซิสเต็มเสียง
- ข้อความภายในเกม
- ยังสร้างฟังก์ชันที่ใกล้เคียงรันไทม์ในระดับ type อีกด้วย
- ตัวเก็บกวาดหน่วยความจำ
- แคช CPU ระดับ L1
- runtime dead code elimination
- ตัวบีบอัดหน่วยความจำแบบเรียลไทม์
- global value stack ที่มีการนับความลึกเพื่อป้องกัน stack underflow
- ตาราง dynamic dispatch
- ตัวแปร global ระดับโมดูล
- labeled
goto - การจัดการข้อยกเว้นระดับ type
- การติดตามสแตกขณะรันไทม์
- core dump แบบเต็ม
- RAM แบบเชิงเส้นถูกแทนด้วยอ็อบเจ็กต์ขนาดมหึมาที่ไม่สามารถจัดเรียงได้ ซึ่งมี คีย์แอดเดรส 32 บิต และค่าเป็นไบต์
- มีการค้นพบวิธีหยุดการประเมิน type ชั่วคราวในพื้นที่ผู้ใช้ของ type จึงทำให้ core dump การจัดการข้อยกเว้น และการติดตามสแตกเป็นไปได้
ข้อจำกัดของเครื่องมือและข้อจำกัดในการสร้าง
- ขนาดไฟล์อาจต้องใหญ่ถึง 1GB ซึ่งเกินขอบเขตที่ Prettier จะจัดการได้
- การเชื่อมต่อกับ language server หรือตัวลินต์จะล่มทันที และในทางปฏิบัติแทบจะเหลือแค่ syntax highlighting ที่ยังพอทำงานได้
- ภายในเอนจินถูกสร้างด้วย เลขฐานสองแบบ two's complement ที่เก็บไว้ใน string literal
- TypeScript สามารถไล่ string ได้จากฝั่งซ้ายเท่านั้น จึงต้องสร้างอัลกอริทึมไบนารีทั้งหมดแบบย้อนทิศ
- ภายในเอนจินไม่มีอาร์เรย์ อ็อบเจ็กต์ สตริง หรือบูลีน ใช้เพียง เลขฐานสอง เท่านั้น
- DOOM ใช้แค่ จำนวนเต็ม 64 บิตและ 32 บิต และจำนวนเต็มเหล่านั้นก็ไม่ใช่ทั้ง signed หรือ unsigned ซึ่งใช้เวลาหนึ่งวันกว่าจะทำความเข้าใจได้
- ผู้สร้างยอมรับว่าตอนเริ่มต้นยังไม่รู้แม้แต่ 10% ของความรู้ที่จำเป็น และต้องสร้างเครื่องมือเอง เขียนชุดทดสอบ 12,364 รายการ ด้วยมือ พร้อมเรียนรู้ภาษาโปรแกรมใหม่หลายภาษา
ยังไม่มีความคิดเห็น