8 คะแนน โดย GN⁺ 2025-04-14 | 2 ความคิดเห็น | แชร์ทาง WhatsApp
  • กรณีศึกษาการ ปรับโครงสร้างใหม่ทั้งหมด ของ UI สำหรับอุปกรณ์ห้องนั่งเล่น โดยอิงกับ Rust และ WebAssembly
  • ออกแบบสถาปัตยกรรมเพื่อให้ได้ทั้ง ประสิทธิภาพสูงและความหน่วงอินพุตต่ำ แม้บนอุปกรณ์ที่มีระดับสมรรถนะแตกต่างกัน
  • เลิกใช้แนวทางที่อิงกับ React แล้ว พัฒนา UI SDK เฉพาะบน Rust ขึ้นเอง เพื่อรักษาผลิตภาพในระดับสูง
  • ใช้สถาปัตยกรรมแบบ Entity-Component-System (ECS) เพื่อจัดการทั้งความซับซ้อนของโค้ดและประสิทธิภาพ
  • วิเคราะห์อย่างตรงไปตรงมาถึง ข้อดี ข้อเสีย และปัญหา จากการใช้ WebAssembly และ Rust

เหตุผลที่ Prime Video ปรับโครงสร้าง UI ใหม่ด้วย Rust และ WebAssembly

  • Amazon ต้องรับมือกับโจทย์ที่แอป Prime Video เดียวกันต้องทำงานบน อุปกรณ์ห้องนั่งเล่นหลากหลายประเภท (คอนโซล กล่องเซ็ตท็อป สตรีมมิงสติก ทีวี ฯลฯ)
  • หากต้องการมอบ ประสบการณ์ผู้ใช้ที่สม่ำเสมอ บนอุปกรณ์ที่มีสมรรถนะต่างกันมาก จำเป็นต้องมี UI engine ที่มีประสิทธิภาพสูง
  • เดิมทีใช้ เทคโนโลยีสแต็กแบบผสม ได้แก่ React(TypeScript), JavaScript, C++, WebAssembly และ Rust
  • จากปัญหาความเร็วในการรันของ JavaScript ที่ช้าและความยากในการอัปเดต จึงตัดสินใจย้ายมาสู่ Rust แบบเต็มรูปแบบ
  • การใช้ WebAssembly ช่วยให้อัปเดตแอปได้ง่ายขึ้น และ Rust ก็เหมาะกับ การปรับแต่งประสิทธิภาพ

ความท้าทายหลักในการพัฒนาบนอุปกรณ์ห้องนั่งเล่น

  • ต้องรองรับ สเปกประสิทธิภาพ ที่หลากหลาย ตั้งแต่อุปกรณ์แรงสูงอย่าง PS5 ไปจนถึง USB stick พลังต่ำ
  • ต้องพัฒนาโดยใช้ โค้ดเบสเดียว โดยไม่แยกทีมเฉพาะตามแต่ละอุปกรณ์
  • อุปกรณ์ส่วนใหญ่ ไม่มี app store และอัปเดตได้ผ่านเฟิร์มแวร์เท่านั้น จึงอัปเดต native code ได้ยาก
  • หากต้องการอัปเดต UI บ่อย ๆ การใช้โค้ดที่อิงกับ JavaScript และ WebAssembly จะได้เปรียบ
  • จึงเลือกชุดผสม Rust + WebAssembly เป็นจุดสมดุลระหว่างความต้องการด้านประสิทธิภาพสูงกับรอบการอัปเดตที่รวดเร็ว

เปรียบเทียบสถาปัตยกรรมเดิมกับสถาปัตยกรรม UI ใหม่บน Rust

  • สถาปัตยกรรมเดิมมีโครงสร้างดังนี้:
    • เขียนตรรกะ UI ด้วย React ส่วน Rust(WebAssembly) รับผิดชอบ UI engine ระดับล่าง
    • React → message bus → WebAssembly UI engine → C++ rendering backend
  • เพื่อแก้ปัญหาความหน่วงอินพุต จึงย้าย business logic ทั้งหมดไปยัง Rust UI SDK
  • สถาปัตยกรรมใหม่:
    • ตั้งแต่ UI SDK ไปจนถึงการเรนเดอร์ สร้างด้วย Rust ทั้งหมด
    • ตัด message bus ออก และรันทุกกระบวนการภายใน WebAssembly
    • โค้ดถูกคอมไพล์เป็น WebAssembly แล้วส่งไปยังทีวี ทำให้ อัปเดตได้เร็วขึ้นและตอบสนองได้ดีขึ้น เมื่อเทียบกับเดิม

องค์ประกอบหลักของ Rust UI SDK ใหม่

  • นำแนวคิด Composable ที่คล้าย React มาใช้ → เป็นหน่วยประกอบ UI ที่นำกลับมาใช้ซ้ำได้
  • ระบบ reactive UI ที่อิงกับ Signal และ Effect
    • Signal: เมื่อค่าเปลี่ยน จะ trigger Effect ที่เกี่ยวข้อง
    • Memo: จะตอบสนองเฉพาะเมื่อค่าต่างจากก่อนหน้าเท่านั้น
  • โครงสร้างลำดับชั้นของ UI ถูกกำหนดผ่านแมโคร compose!
  • องค์ประกอบ UI ประกอบด้วย Widget (คอมโพเนนต์ที่มีมาให้) และ Composables (โครงสร้างที่ผู้ใช้กำหนดเอง)
  • ใช้สถาปัตยกรรมแบบ Entity-Component-System(ECS):
    • Entity: ID
    • Component: ข้อมูลคุณสมบัติ (เช่น Layout, RenderInfo, Text)
    • System: ฟังก์ชันที่ทำงานตามชุดของ Component ที่กำหนด

โครงสร้างและวิธีทำงานของระบบ ECS

  • แต่ละระบบต้องการชุดคอมโพเนนต์เฉพาะ และใช้สิ่งนั้นเป็นพื้นฐานในการจัดการการอัปเดต UI
  • ตัวอย่าง:
    • Resource Management System: คอมโพเนนต์ภาพ → อัปโหลดขึ้น GPU → อัปเดต RenderInfo
    • Layout System: คำนวณคอมโพเนนต์ที่เกี่ยวข้องกับเลย์เอาต์หลากหลายแบบ
    • Rendering System: แสดงผลหน้าจอจริงตาม RenderInfo
  • โครงสร้างนี้ช่วยให้สามารถ ย้ายเพจจาก React มาสู่ Rust แบบค่อยเป็นค่อยไป
  • การ อยู่ร่วมกันและสลับใช้งาน ระหว่างเพจที่อิงกับ JavaScript และเพจที่อิงกับ Rust ทำได้อย่างราบรื่น

ผลลัพธ์ที่ดีและประโยชน์ที่ได้รับ

  • แม้นักพัฒนา JavaScript/React ก็สามารถย้ายมาใช้ Rust UI SDK ได้ โดยไม่สูญเสียผลิตภาพ
  • ด้วยโครงสร้างของ UI SDK ที่คุ้นเคย ผู้เริ่มต้นใช้ Rust ก็ปรับตัวได้รวดเร็ว
  • สามารถสร้าง layout animation, การสลับหน้าจอที่รวดเร็ว และ ความสามารถที่ก่อนหน้านี้ทำไม่ได้
  • เครื่องมือพัฒนาภายใน (เช่น resource manager, layout inspector) ก็สามารถสร้างบน Rust ได้ อย่างรวดเร็ว
  • ลดความหน่วงอินพุตจาก 250ms เหลือเพียง 33ms อย่างมาก (บนอุปกรณ์สเปกต่ำ)

จุดที่ยากและข้อจำกัดทางเทคนิค

  • WebAssembly System Interface(WASI) ยังเป็นอีโคซิสเต็มที่กำลังพัฒนา จึงมีโอกาสที่โค้ดเดิมจะพังเมื่ออัปเดต Rust
  • ใน WebAssembly หากเกิด panic แอปจะปิดทั้งตัวทันที → ทำให้การรักษาเสถียรภาพเป็นเรื่องยาก
    • ต่างจาก JavaScript ที่รองรับการจัดการข้อยกเว้นได้ดีกว่า จึงจำเป็นต้องใช้ชนิด Result อย่างจริงจัง
    • เมื่อต้องพึ่งพาไลบรารีภายนอก ก็ต้องผลักดันให้มีการออกแบบแบบ panic-free
  • ในสภาพแวดล้อมเบราว์เซอร์นั้น WebAssembly และ rendering API บางอย่างยังไม่รองรับ จึงยังไม่ได้นำไปใช้กับเว็บไคลเอนต์

การมีส่วนร่วมกับ Bytecode Alliance และอีโคซิสเต็ม

  • Amazon ในฐานะสมาชิกของ Bytecode Alliance มีส่วนร่วมอย่างแข็งขันในการ มาตรฐาน WASI และการปรับปรุงความสามารถที่เกี่ยวข้อง
  • WebAssembly Micro Runtime ที่ใช้งานอยู่พัฒนาด้วย C และก็มีการพิจารณา Wasmtime ซึ่งพัฒนาด้วย Rust ควบคู่กันไป
  • เพื่อพัฒนาอีโคซิสเต็มของ WebAssembly ให้เติบโต Amazon กำลัง ให้ feedback ทางเทคนิคและเข้าร่วมพัฒนาโดยตรง

Q&A อื่น ๆ

  • ทำงานบนเว็บเบราว์เซอร์ได้ด้วยหรือไม่? → เบราว์เซอร์ WebKit บางตัวไม่รองรับ WASM อีกทั้งยังมีปัญหาด้านประสิทธิภาพและความซับซ้อนในการพัฒนา จึงยังอยู่ระหว่างการพิจารณา
  • สามารถทำด้วย WebGL ได้ แต่ในตอนนี้มองว่ายังไม่คุ้มกับการลงทุน จึงชะลอไว้ก่อน

สรุป

  • UI ของ Prime Video ที่สร้างบน Rust+WebAssembly ตอบโจทย์ทั้ง ประสิทธิภาพสูง ความหน่วงอินพุตต่ำ และการอัปเดตที่รวดเร็ว
  • UI SDK ที่พัฒนาขึ้นเองและสถาปัตยกรรม ECS ช่วย จัดการพฤติกรรม UI ที่ซับซ้อนได้อย่างมีประสิทธิภาพ
  • แม้การนำ Rust มาใช้จะไม่ง่าย แต่ด้วยการออกแบบอย่างเป็นระบบและวัฒนธรรมการพัฒนา ก็สามารถ บรรลุทั้งผลิตภาพและเสถียรภาพได้พร้อมกัน
  • แม้อีโคซิสเต็มของ WebAssembly ยังอยู่ระหว่างการพัฒนา แต่ก็ พร้อมใช้งานจริงในบริการระดับโปรดักชันได้เพียงพอ
  • ความสำเร็จในการนำมาใช้เกิดจากการทำต้นแบบอย่างรอบคอบและ กลยุทธ์การย้ายระบบแบบค่อยเป็นค่อยไป

2 ความคิดเห็น

 
seunggi 2025-04-14

เมื่อเทียบกับฝั่งฟรอนต์เอนด์ที่มักมีไลบรารีจัดการสถานะมาให้เป็นพื้นฐาน ผมกลับมองว่าเกมนี่แหละที่ทุกสถานะไปแตะต้องทุกสถานะได้ เลยเหมือนทำกันแบบลูกผู้ชายล้วน ๆ? อยู่แล้ว แต่ในทางกลับกัน การใช้ ECS ในแอปพลิเคชันทั่วไปก็คงคล้ายกับการที่นักพัฒนาแต่ละคนใช้การจัดการสถานะแบบเป็นแพตเทิร์น หรือใช้ไลบรารีภายในของตัวเอง เลยอยากรู้ว่าจัดการส่วนนี้กันอย่างไรครับ

 
y15un 2025-04-14

การนำ ECS ที่ปกติเห็นกันในเอนจินเกมมาปรับใช้กับ UI นี่เป็นไอเดียที่แปลกใหม่พอสมควรเลยครับ วันนี้ก็ได้เรียนรู้อะไรเพิ่มอีกอย่างแล้ว