- recall adalah layanan yang menyediakan bot rapat untuk ratusan perusahaan dan mengoperasikan infrastruktur berskala besar di AWS
- Demi layanan yang efisien dari sisi biaya, mereka berupaya memanfaatkan performa hardware semaksimal mungkin
- Selama beberapa tahun terakhir, karena ketersediaan GPU dari penyedia cloud tidak stabil, pemrosesan video dilakukan di CPU, bukan GPU
- Hasil profiling pada bot yang menggunakan Chromium headless menunjukkan bahwa sebagian besar waktu CPU bukan dihabiskan untuk pemrosesan video (encoding/decoding), melainkan pada fungsi penyalinan memori
__memmove_avx_unaligned_erms dan __memcpy_avx_unaligned_erms
memmove dan memcpy adalah fungsi penyalinan blok memori di pustaka standar C (glibc)
memmove menangani beberapa kasus pengecualian yang berkaitan dengan penyalinan memori pada rentang yang saling tumpang tindih, tetapi keduanya dapat diklasifikasikan sebagai fungsi "penyalinan memori"
- Sufiks
avx_unaligned_erms berarti implementasi tersebut dioptimalkan untuk sistem yang mendukung Advanced Vector Extensions (AVX), serta untuk akses memori yang tidak selaras
erms adalah singkatan dari Enhanced REP MOVSB/STOSB, sebuah optimisasi untuk perpindahan memori cepat pada prosesor Intel modern. Ini bisa dipahami sebagai "implementasi yang lebih cepat untuk prosesor tertentu"
- Dari hasil profiling, pemanggil paling banyak dari fungsi-fungsi ini adalah klien WebSocket Python yang menerima data
- Setelah itu, implementasi WebSocket Chromium yang mengirim data juga banyak memanggilnya
Masalah pada WebSocket
- Mereka menggunakan server WebSocket lokal untuk mengirim data video mentah dari lingkungan JS Chromium ke encoder
- Stream video mentah 1080p 30fps membutuhkan bandwidth tinggi, lebih dari 93MB per detik
- Penggunaan WebSocket menimbulkan biaya komputasi yang besar, dengan penyebab utama berupa fragmentasi dan masking
- Fragmentasi: implementasi WebSocket Chromium memecah pesan di atas 131KB menjadi beberapa frame. Frame video mentah berukuran lebih dari 3MB akhirnya dikirim dalam 24 frame terpisah atau lebih
- Masking: demi keamanan, WebSocket mem-mask semua frame yang dikirim dari klien ke server. Pada data berukuran besar lebih dari 100MB per detik, ini menjadi overhead yang signifikan
Mencari alternatif
- Dengan API browser, sulit membuat sesuatu yang jauh lebih cepat daripada WebSocket, sehingga mereka memutuskan untuk mem-fork Chromium dan mengimplementasikan fitur kustom
- Mereka mempertimbangkan 3 alternatif: raw TCP/IP, Unix Domain Socket, Shared Memory
- TCP/IP: bisa menghindari masalah fragmentasi/masking pada WebSocket, tetapi ukuran paket maksimum kecil sehingga masalah fragmentasi tetap ada. Ada juga overhead penyalinan ke ruang kernel
- Unix Domain Socket: dapat sepenuhnya melewati network stack, tetapi tetap memerlukan penyalinan data antara ruang pengguna dan ruang kernel
- Shared Memory: memori yang dapat diakses beberapa proses secara bersamaan. Chromium bisa langsung menulis ke memori bersama tanpa penyalinan perantara, dan encoder bisa langsung membacanya
Implementasi transfer berbasis shared memory
- Untuk membaca dan menulis data secara berurutan di memori bersama, mereka mengimplementasikannya dalam bentuk ring buffer
- Persyaratan: lock-free, multi-producer/single-consumer, ukuran frame variabel, pembacaan zero-copy, ramah sandbox, signaling latensi rendah
- Mereka mengevaluasi implementasi ring buffer yang sudah ada, tetapi tidak ada yang memenuhi semua persyaratan sehingga akhirnya memutuskan untuk membuatnya sendiri
- Untuk mendukung pembacaan zero-copy, pointer dibagi menjadi tiga: write, peek, dan read
- Demi thread safety, mereka menggunakan operasi atomik, dan memakai named semaphore untuk memberi tahu saat ada data baru/ruang telah tersedia
- Melalui implementasi ring buffer berbasis shared memory dan optimisasi lainnya, mereka dapat mengurangi penggunaan CPU bot hingga 50%. Pada akhirnya, biaya AWS berkurang lebih dari satu juta dolar per tahun.
3 komentar
Komentar Hacker News
Ini adalah kisah khas tentang sebuah startup yang memilih jalan pintas yang "cukup baik" lalu mengoptimalkannya belakangan.
Ada pendapat bahwa bandwidth tinggi dari data video mentah itu mengejutkan.
Ada pendapat bahwa ini bukan masalah AWS, melainkan masalah pemborosan siklus CPU.
Ditunjukkan bahwa MTU dan MSS pada jaringan TCP/IP kecil dibandingkan ukuran frame video.
Ada pendapat bahwa dengan menggunakan Mojo milik Chromium, tidak perlu khawatir soal kode spesifik platform.
Ada pendapat bahwa masalahnya bukan pada jaringan, melainkan kurangnya pemahaman tentang codec video.
Transparansinya dipuji, dan diharapkan ada transparansi juga soal harga produk.
Dijelaskan bahwa masking pada protokol WebSocket adalah upaya untuk menyelesaikan masalah man-in-the-middle.
Ditunjukkan bahwa cara mengirim data video tanpa kompresi itu aneh.
Disebutkan bahwa pendekatan awal mengirim video mentah lewat WebSocket itu mengejutkan.
Dari awal pengembangannya memang sudah salah..
"Pendekatan awal yang mengirim video mentah lewat WebSocket memang terdengar mengejutkan." Setuju dengan komentar itu.