14 điểm bởi GN⁺ 2024-11-08 | 3 bình luận | Chia sẻ qua WhatsApp
  • recall là dịch vụ cung cấp bot họp cho hàng trăm công ty và đang vận hành hạ tầng quy mô lớn trên AWS
  • Công ty muốn tận dụng tối đa hiệu năng phần cứng để cung cấp dịch vụ hiệu quả về chi phí
  • Trong vài năm qua, do khả năng sẵn có của GPU từ các nhà cung cấp cloud không ổn định, nên xử lý video được thực hiện trên CPU thay vì GPU
  • Khi profiling các bot dùng headless Chromium, họ phát hiện phần lớn thời gian CPU không được dùng cho xử lý video (mã hóa/giải mã), mà lại tiêu tốn trong các hàm sao chép bộ nhớ __memmove_avx_unaligned_erms__memcpy_avx_unaligned_erms
    • memmovememcpy là các hàm sao chép khối bộ nhớ trong thư viện chuẩn C (glibc)
    • memmove xử lý một số trường hợp ngoại lệ liên quan đến sao chép bộ nhớ ở các vùng chồng lấn, nhưng cả hai đều có thể được xếp vào nhóm hàm "sao chép bộ nhớ"
    • Hậu tố avx_unaligned_erms cho biết chúng được tối ưu cho hệ thống hỗ trợ Advanced Vector Extensions (AVX), đồng thời tối ưu cho cả truy cập bộ nhớ không căn chỉnh
    • erms là viết tắt của Enhanced REP MOVSB/STOSB, một tối ưu cho việc di chuyển bộ nhớ nhanh trên các bộ xử lý Intel hiện đại. Có thể hiểu là "triển khai nhanh hơn cho một số bộ xử lý cụ thể"
  • Kết quả profiling cho thấy thành phần gọi các hàm này nhiều nhất là Python WebSocket client nhận dữ liệu
    • Đứng sau đó là implementation WebSocket của Chromium dùng để gửi dữ liệu, cũng gọi chúng rất nhiều

Vấn đề của WebSocket

  • Họ sử dụng một máy chủ WebSocket cục bộ để truyền dữ liệu video thô từ môi trường JS của Chromium sang encoder
  • Một luồng video thô 1080p 30fps đòi hỏi băng thông cao hơn 93MB mỗi giây
  • Việc dùng WebSocket gây ra chi phí tính toán lớn, mà nguyên nhân chính là fragmentation và masking
    • Fragmentation: implementation WebSocket của Chromium sẽ chia nhỏ các message lớn hơn 131KB thành nhiều frame. Một frame video thô lớn hơn 3MB sẽ bị tách thành hơn 24 frame riêng biệt để truyền đi
    • Masking: vì lý do bảo mật, WebSocket sẽ mask mọi frame truyền từ client lên server. Với dữ liệu khối lượng lớn vượt 100MB mỗi giây, đây trở thành một overhead đáng kể

Tìm giải pháp thay thế

  • Với các API trình duyệt hiện có, rất khó để triển khai thứ gì đó có hiệu năng tốt hơn nhiều so với WebSocket, nên họ quyết định fork Chromium để tự thêm chức năng tùy biến
  • Họ cân nhắc 3 phương án thay thế: raw TCP/IP, Unix Domain Socket, Shared Memory
    • TCP/IP: có thể tránh được vấn đề fragmentation/masking của WebSocket, nhưng kích thước packet tối đa vẫn nhỏ nên vẫn còn vấn đề phân mảnh. Ngoài ra còn có overhead sao chép vào kernel space
    • Unix Domain Socket: có thể bỏ qua hoàn toàn network stack, nhưng vẫn cần sao chép dữ liệu giữa user space và kernel space
    • Shared Memory: là bộ nhớ mà nhiều process có thể cùng truy cập. Chromium có thể ghi trực tiếp vào vùng nhớ chia sẻ mà không cần sao chép trung gian, và encoder có thể đọc ngay từ đó

Triển khai truyền dữ liệu dựa trên shared memory

  • Họ triển khai theo dạng ring buffer để đọc và ghi dữ liệu liên tục trong shared memory
  • Yêu cầu gồm: lock-free, đa producer/đơn consumer, kích thước frame biến đổi, đọc zero-copy, thân thiện với sandbox, signaling độ trễ thấp
  • Họ đã đánh giá các implementation ring buffer có sẵn nhưng không có cái nào đáp ứng toàn bộ yêu cầu, nên quyết định tự xây dựng
  • Để hỗ trợ đọc zero-copy, họ tách con trỏ thành ba loại: write, peek, read
  • Để bảo đảm thread safety, họ dùng atomic operation và dùng named semaphore để báo có dữ liệu mới / có không gian trống
  • Nhờ implementation ring buffer dựa trên shared memory cùng các tối ưu khác, họ có thể giảm mức sử dụng CPU của bot xuống tối đa 50%. Kết quả là tiết kiệm được hơn 1 triệu USD chi phí AWS mỗi năm.

3 bình luận

 
GN⁺ 2024-11-08
Ý kiến Hacker News
  • Đây là một câu chuyện điển hình về việc một startup chọn lối tắt “đủ ổn” rồi tối ưu hóa sau.

    • Ở một công ty, có một cụm VM với mức sử dụng CPU cao, và họ đã dùng profiler để tối ưu hóa.
    • Họ đã xóa dữ liệu cũ và thêm bộ lọc vào truy vấn để giảm mức sử dụng CPU.
  • Có ý kiến cho rằng mức băng thông cao của dữ liệu video thô là điều đáng kinh ngạc.

    • Họ chỉ trích quyết định thiết kế của WebSockets vì đã không lường trước vấn đề sử dụng CPU.
  • Có ý kiến cho rằng đây không phải vấn đề của AWS mà là vấn đề lãng phí chu kỳ CPU.

    • WebSockets liên quan đến việc truyền dữ liệu hoặc chi phí API gateway.
  • Có người chỉ ra rằng MTU và MSS của mạng TCP/IP nhỏ so với kích thước khung hình video.

    • Họ cho rằng đây là dấu hiệu thiếu kiến thức kỹ thuật và cần tuyển các lập trình viên phù hợp.
  • Có ý kiến cho rằng có thể dùng Mojo của Chromium để không phải lo về mã theo từng nền tảng.

    • Họ cũng cho rằng việc tự triển khai ring buffer là chấp nhận được.
  • Có người cho rằng vấn đề không nằm ở mạng mà là ở sự thiếu hiểu biết về codec video.

    • Họ nói không thể hiểu nổi vì sao lại không dùng các giao thức streaming video như RDP.
  • Có người khen ngợi sự minh bạch và nói rằng cũng muốn thấy sự minh bạch về giá sản phẩm.

  • Có người giải thích rằng cơ chế masking của giao thức WebSocket là một nỗ lực nhằm giải quyết vấn đề kẻ trung gian.

    • Họ nói rằng RFC liên quan rất đáng để đọc.
  • Có người chỉ ra rằng việc truyền dữ liệu video mà không nén là điều kỳ lạ.

    • Họ nói không thể hiểu nổi vì sao lại không truyền luồng đã nén.
  • Có người nói cách tiếp cận ban đầu là truyền video thô qua WebSocket thật đáng ngạc nhiên.

    • Họ cho rằng sự kém hiệu quả đó vẫn không cản trở việc phát triển sản phẩm.
    • Họ nói không thể hiểu được cách tiếp cận không hề cân nhắc đến lượng dữ liệu.
 
ahwjdekf 2024-11-09
  • Có vẻ như khi phát triển sản phẩm đã hoàn toàn không hề cân nhắc đến hiệu năng.
  • Rốt cuộc vấn đề này quy về bài toán sẽ IPC dữ liệu khối lượng lớn như thế nào.
  • Điểm khác biệt là không phải IPC thông thường, mà là IPC với trình duyệt Chrome, và
  • Cách thức nội bộ của trình duyệt Chrome có lẽ không hề đơn giản, nhưng vì là mã nguồn mở nên vẫn có thể chỉnh sửa.
  • Vậy cuối cùng vẫn là vấn đề lựa chọn IPC.

Ngay từ đầu đã làm sai cách rồi..

 
ahwjdekf 2024-11-09

"Cách tiếp cận ban đầu là truyền video thô qua WebSocket thật sự khiến người ta ngạc nhiên." Đồng cảm với câu này.