• นี่คือการทดลองที่บูตเกม 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 รายการ ด้วยมือ พร้อมเรียนรู้ภาษาโปรแกรมใหม่หลายภาษา

ยังไม่มีความคิดเห็น

ยังไม่มีความคิดเห็น