- recall सैकड़ों कंपनियों को मीटिंग बॉट उपलब्ध कराने वाली एक सेवा है और AWS पर बड़े पैमाने का इन्फ्रास्ट्रक्चर चलाती है
- लागत-कुशल सेवा के लिए हार्डवेयर प्रदर्शन का अधिकतम उपयोग करने की कोशिश की गई
- पिछले कुछ वर्षों में cloud provider की GPU उपलब्धता अस्थिर रही, इसलिए वीडियो प्रोसेसिंग GPU के बजाय CPU पर की गई
- headless Chromium का उपयोग करने वाले बॉट्स की profiling के नतीजे में पता चला कि अधिकांश CPU समय वीडियो प्रोसेसिंग (encoding/decoding) में नहीं, बल्कि मेमोरी कॉपी फ़ंक्शन
__memmove_avx_unaligned_erms और __memcpy_avx_unaligned_erms में खर्च हो रहा था
memmove और memcpy C standard library (glibc) में मौजूद मेमोरी ब्लॉक कॉपी फ़ंक्शन हैं
memmove ओवरलैप होने वाली memory range की कॉपी से जुड़े कुछ exceptional case संभालता है, लेकिन दोनों फ़ंक्शन को "मेमोरी कॉपी" फ़ंक्शन कहा जा सकता है
avx_unaligned_erms suffix का मतलब है कि यह Advanced Vector Extensions (AVX) को सपोर्ट करने वाले सिस्टम के लिए optimize किया गया है, और unaligned memory access के लिए भी optimize है
erms का अर्थ Enhanced REP MOVSB/STOSB है, जो आधुनिक Intel processor में तेज़ memory move के लिए optimization है। इसे "किसी खास processor के लिए तेज़ implementation" के रूप में समझा जा सकता है
- profiling के अनुसार, इन फ़ंक्शनों को सबसे ज़्यादा कॉल करने वाला डेटा रिसीव करने वाला Python WebSocket client था
- उसके बाद डेटा भेजने वाला Chromium का WebSocket implementation सबसे अधिक कॉल कर रहा था
WebSocket की समस्या
- raw वीडियो डेटा को Chromium के JS environment से encoder तक भेजने के लिए local WebSocket server का उपयोग किया गया
- raw 1080p 30fps वीडियो स्ट्रीम के लिए प्रति सेकंड 93MB से अधिक की बहुत ऊंची bandwidth चाहिए
- WebSocket के उपयोग से बड़ा compute overhead पैदा हुआ, और इसके मुख्य कारण fragmentation और masking थे
- fragmentation: Chromium का WebSocket implementation 131KB से बड़े message को कई frame में fragment कर देता है। 3MB से बड़े raw वीडियो frame को 24 या उससे अधिक अलग-अलग frame में बांटकर भेजा जाता था
- masking: सुरक्षा कारणों से WebSocket client से server को भेजे जाने वाले सभी frame को mask करता है। प्रति सेकंड 100MB से अधिक के बड़े डेटा में यह एक meaningful overhead बन जाता है
विकल्पों की तलाश
- browser API के भीतर WebSocket से कहीं बेहतर performance वाली चीज़ बनाना मुश्किल था, इसलिए Chromium को fork करके custom functionality लागू करने का फैसला किया गया
- 3 विकल्पों पर विचार किया गया: raw TCP/IP, Unix Domain Socket, Shared Memory
- TCP/IP: WebSocket की fragmentation/masking समस्या से बचा जा सकता है, लेकिन maximum packet size छोटा होने के कारण fragmentation की समस्या फिर भी रहती है। kernel space में कॉपी का overhead भी होता है
- Unix Domain Socket: network stack को पूरी तरह bypass किया जा सकता है, लेकिन user space और kernel space के बीच डेटा कॉपी अभी भी ज़रूरी है
- Shared Memory: ऐसी मेमोरी जिस तक कई process एक साथ पहुंच सकते हैं। बीच में कॉपी किए बिना Chromium सीधे shared memory में लिख सकता है और encoder वहीं से तुरंत पढ़ सकता है
shared memory आधारित ट्रांसफर का implementation
- shared memory में डेटा को लगातार पढ़ने-लिखने के लिए इसे ring buffer के रूप में implement किया गया
- आवश्यकताएं: lock-free, multi-producer/single-consumer, variable frame size, zero-copy read, sandbox friendliness, low-latency signaling
- तैयार ring buffer implementation का मूल्यांकन किया गया, लेकिन कोई भी सभी आवश्यकताएं पूरी नहीं कर पाया, इसलिए इसे खुद implement करने का निर्णय लिया गया
- zero-copy read को सपोर्ट करने के लिए pointer को write, peek, और read — इन तीन हिस्सों में बांटा गया
- thread safety के लिए atomic operation का उपयोग किया गया, और नया डेटा आने/स्पेस खाली होने की सूचना देने के लिए named semaphore का उपयोग किया गया
- shared memory आधारित ring buffer implementation और अन्य optimization की मदद से बॉट्स का CPU उपयोग अधिकतम 50% तक घटाया जा सका। अंततः AWS लागत में सालाना $1M से अधिक की बचत हुई।
3 टिप्पणियां
Hacker News प्रतिक्रियाएँ
यह एक startup की क्लासिक कहानी है, जहाँ उसने "काफ़ी ठीक" शॉर्टकट चुना और बाद में optimize किया।
raw video data की ऊँची bandwidth पर हैरानी जताई गई।
कुछ लोगों का कहना है कि यह AWS की नहीं, बल्कि CPU cycles बर्बाद करने की समस्या थी।
TCP/IP network के MTU और MSS के video frame size की तुलना में छोटे होने की बात उठाई गई।
कुछ लोगों ने कहा कि Chromium के Mojo का उपयोग करने से platform-specific code की चिंता नहीं करनी पड़ती।
कुछ का मानना है कि समस्या network नहीं, बल्कि video codec की समझ की कमी थी।
पारदर्शिता की सराहना की गई, और कहा गया कि product pricing में भी ऐसी ही transparency चाहिए।
समझाया गया कि WebSocket protocol में masking, man-in-the-middle जैसी समस्या को हल करने की एक कोशिश थी।
यह भी कहा गया कि video data को compress किए बिना भेजने का तरीका अजीब है।
raw video को WebSocket से भेजने वाला शुरुआती approach हैरान करने वाला बताया गया।
शुरू से ही डेवलपमेंट गलत किया गया था..
"raw video को WebSocket से भेजने वाला शुरुआती approach चौंकाने वाला था।" इस बात से सहमत हूँ।