8 điểm bởi GN⁺ 2025-04-14 | 2 bình luận | Chia sẻ qua WhatsApp
  • Trường hợp tái cấu trúc toàn diện UI cho thiết bị phòng khách dựa trên Rust và WebAssembly
  • Thiết kế kiến trúc để đạt hiệu năng cao và độ trễ đầu vào thấp ngay cả trên các thiết bị có nhiều mức hiệu năng khác nhau
  • Rời khỏi nền tảng React, tự phát triển UI SDK chuyên biệt bằng Rust để đảm bảo năng suất cao
  • Quản lý độ phức tạp mã nguồn và hiệu năng thông qua kiến trúc dựa trên Entity-Component-System (ECS)
  • Phân tích thẳng thắn về ưu điểm, nhược điểm và các vấn đề phát sinh khi sử dụng WebAssembly và Rust

Vì sao Prime Video tái cấu trúc UI bằng Rust và WebAssembly

  • Amazon phải giải quyết bài toán chạy cùng một ứng dụng Prime Video trên nhiều thiết bị phòng khách khác nhau (console, set-top box, streaming stick, TV, v.v.)
  • Để cung cấp trải nghiệm người dùng nhất quán trên các thiết bị có hiệu năng khác nhau, một UI engine hiệu năng cao là điều bắt buộc
  • Trước đây, hệ thống sử dụng stack công nghệ pha trộn gồm React(TypeScript), JavaScript, C++, WebAssembly và Rust
  • Do tốc độ thực thi chậm của JavaScript và khó khăn trong cập nhật, Amazon quyết định chuyển toàn bộ sang Rust
  • Tận dụng WebAssembly giúp việc cập nhật ứng dụng dễ hơn, còn Rust có lợi thế về tối ưu hiệu năng

Những thách thức chính khi phát triển cho thiết bị phòng khách

  • Cần hỗ trợ nhiều mức cấu hình hiệu năng khác nhau, từ thiết bị mạnh như PS5 đến USB stick công suất thấp
  • Phải phát triển trên một codebase duy nhất thay vì duy trì đội ngũ riêng cho từng thiết bị
  • Trên đa số thiết bị, không có app store mà chỉ cập nhật firmware, nên rất khó cập nhật native code
  • Nếu muốn cập nhật UI thường xuyên thì dùng mã dựa trên JavaScript và WebAssembly sẽ có lợi hơn
  • Tổ hợp Rust + WebAssembly được chọn như điểm cân bằng giữa yêu cầu hiệu năng caochu kỳ cập nhật nhanh

So sánh kiến trúc cũ với kiến trúc UI mới dựa trên Rust

  • Kiến trúc cũ có cấu trúc như sau:
    • Viết logic UI bằng React, còn Rust(WebAssembly) xử lý UI engine ở mức thấp
    • React → message bus → WebAssembly UI engine → C++ rendering backend
  • Để giải quyết vấn đề độ trễ đầu vào, toàn bộ business logic được migrate sang Rust UI SDK
  • Kiến trúc mới:
    • Từ UI SDK đến rendering đều được xây dựng hoàn toàn bằng Rust
    • Loại bỏ message bus, toàn bộ quá trình xử lý chạy bên trong WebAssembly
    • Mã được biên dịch thành WebAssembly rồi phân phối tới TV, giúp tăng tốc cập nhật và cải thiện độ phản hồi so với trước

Các thành phần chính của Rust UI SDK mới

  • Áp dụng khái niệm Composable tương tự React → đơn vị cấu thành UI có thể tái sử dụng
  • Hệ thống UI phản ứng dựa trên SignalEffect
    • Signal: khi giá trị thay đổi sẽ kích hoạt các Effect liên quan
    • Memo: chỉ phản ứng khi khác với giá trị trước đó
  • Cấu trúc phân cấp UI được định nghĩa thông qua macro compose!
  • Các phần tử UI gồm Widget (component dựng sẵn) và Composables (cấu trúc tự định nghĩa)
  • Sử dụng kiến trúc Entity-Component-System(ECS):
    • Entity: ID
    • Component: dữ liệu thuộc tính (ví dụ: Layout, RenderInfo, Text)
    • System: hàm thực thi logic cho một tổ hợp Component cụ thể

Cấu trúc và cách vận hành của hệ thống ECS

  • Mỗi system yêu cầu một tổ hợp component nhất định, và xử lý cập nhật UI dựa trên đó
  • Ví dụ:
    • Resource Management System: component hình ảnh → upload lên GPU → cập nhật RenderInfo
    • Layout System: tính toán nhiều component liên quan đến layout
    • Rendering System: hiển thị thực tế lên màn hình dựa trên RenderInfo
  • Cấu trúc này cho phép migrate dần dần nhiều trang từ React sang Rust
  • Việc cùng tồn tại và chuyển đổi giữa các trang dựa trên JavaScript và Rust diễn ra mượt mà

Kết quả tích cực và lợi ích

  • Ngay cả các lập trình viên JavaScript/React cũng chuyển sang Rust UI SDK thành công mà không mất năng suất
  • Nhờ cấu trúc quen thuộc của UI SDK, người mới với Rust cũng có thể thích nghi nhanh
  • Có thể triển khai layout animation, chuyển màn hình nhanh và các tính năng trước đây không thể làm được
  • Các công cụ phát triển nội bộ (resource manager, layout inspector, v.v.) cũng có thể được xây dựng nhanh bằng Rust
  • Độ trễ đầu vào từ 250ms đã giảm mạnh xuống còn 33ms (trên thiết bị cấu hình thấp)

Những điểm khó và giới hạn kỹ thuật

  • WebAssembly System Interface(WASI) vẫn là một hệ sinh thái đang phát triển, nên khi cập nhật Rust có thể khiến mã hiện có bị hỏng
  • Trong WebAssembly, nếu xảy ra panic thì toàn bộ ứng dụng sẽ thoát → gây khó khăn cho việc đảm bảo ổn định
    • Khác với JavaScript, khả năng xử lý ngoại lệ còn hạn chế → cần tích cực sử dụng kiểu Result
    • Khi phụ thuộc vào thư viện bên ngoài, cần thúc đẩy cách triển khai không gây panic
  • Trong môi trường trình duyệt, WebAssembly và một số rendering API cụ thể chưa được hỗ trợ, nên chưa áp dụng cho web client

Bytecode Alliance và đóng góp cho hệ sinh thái

  • Amazon là thành viên của Bytecode Alliance và tham gia tích cực vào việc chuẩn hóa WASI cũng như cải thiện các tính năng liên quan
  • WebAssembly Micro Runtime đang dùng được xây dựng bằng C, đồng thời Wasmtime viết bằng Rust cũng đang được xem xét song song
  • Để thúc đẩy hệ sinh thái WebAssembly, Amazon đang trực tiếp đóng góp phản hồi kỹ thuật và tham gia phát triển

Hỏi & đáp khác

  • Có thể áp dụng trên trình duyệt web không? → Một số trình duyệt WebKit chưa hỗ trợ WASM, hiệu năng bị suy giảm và độ phức tạp triển khai cao, nên hiện vẫn đang cân nhắc
  • Có thể triển khai bằng WebGL, nhưng hiện tại hiệu quả so với chi phí đầu tư còn thấp nên tạm hoãn

Tóm tắt

  • UI dựa trên Rust+WebAssembly của Prime Video đáp ứng đồng thời 3 yếu tố: hiệu năng cao, độ trễ đầu vào thấp và cập nhật nhanh
  • UI SDK tự phát triển cùng kiến trúc ECS giúp quản lý hiệu quả các hành vi UI phức tạp
  • Việc áp dụng Rust không hề dễ, nhưng với thiết kế bài bản và văn hóa phát triển phù hợp, Amazon đã đạt được cả năng suất lẫn độ ổn định
  • Hệ sinh thái WebAssembly vẫn đang phát triển, nhưng hoàn toàn khả thi để triển khai trong dịch vụ thực tế
  • Việc áp dụng thành công dựa trên quá trình tạo prototype kỹ lưỡng và chiến lược chuyển đổi dần từng bước

2 bình luận

 
seunggi 2025-04-14

So với frontend vốn mặc định đi kèm thư viện quản lý trạng thái, tôi vẫn nghĩ game mới là nơi mọi trạng thái đều tác động lẫn nhau nên thường cứ làm theo kiểu rất trực diện thôi? Nhưng ngược lại, việc dùng ECS trong ứng dụng có lẽ sẽ khá giống với việc mỗi lập trình viên tự dùng các mẫu quản lý trạng thái đã được khuôn mẫu hóa hoặc dùng thư viện riêng, nên tôi khá tò mò họ đã xử lý những phần này như thế nào.

 
y15un 2025-04-14

Thật thú vị khi áp dụng ECS, thứ thường chỉ thấy trong game engine, vào UI. Hôm nay lại học thêm được một điều.