- Firefox के HTTP ट्रैफ़िक का लगभग 20% HTTP/3 का उपयोग करता है, जो QUIC और UDP के ऊपर काम करता है
- मौजूदा नेटवर्क I/O लेयर NSPR को Rust-आधारित quinn-udp से बदलते हुए परफ़ॉर्मेंस और मेमोरी सेफ़्टी को मज़बूत किया गया
- हर operating system के लिए नवीनतम system calls (multi-message, segmentation offloading आदि) का सक्रिय उपयोग कर परफ़ॉर्मेंस optimization लागू किया गया
- Windows और MacOS में compatibility, driver issues आदि के कारण कुछ features सीमित रहे, लेकिन Linux में सर्वोत्तम परफ़ॉर्मेंस की पुष्टि हुई
- QUIC ECN support और UDP I/O से जुड़ी विभिन्न platform-specific कोशिशें और bug fixes का अनुभव भविष्य की projects और open source ecosystem के लिए भी उपयोगी होने की संभावना है
प्रेरणा
- Firefox HTTP ट्रैफ़िक का लगभग 20% HTTP/3 का उपयोग करता है, जो QUIC के ज़रिए चलता है, और आगे UDP पर लागू होता है
- Firefox ने ऐतिहासिक रूप से नेटवर्क I/O के लिए NSPR library का उपयोग किया, लेकिन UDP I/O से जुड़ी इसकी सुविधाएँ पुरानी और सीमित हैं (मुख्य functions हैं
PR_SendTo, PR_RecvFrom)
- operating systems ने हाल के वर्षों में multi-message system calls (जैसे
sendmmsg, recvmmsg) और segmentation offload (GSO, GRO) जैसी network optimizations उपलब्ध कराई हैं
- ये तकनीकें UDP I/O की परफ़ॉर्मेंस को काफ़ी बढ़ा सकती हैं
- Firefox ने यह खोजा कि क्या मौजूदा UDP I/O stack को modern system calls से बदलकर इनका लाभ लिया जा सकता है
अवलोकन
- यह project 2024 के मध्य में शुरू हुआ, और लक्ष्य था Firefox के QUIC UDP I/O stack को सभी supported OS पर modern system calls के साथ फिर से बनाना
- परफ़ॉर्मेंस सुधार के साथ-साथ, UDP I/O में memory safety देने वाले Rust का उपयोग कर security भी बेहतर करने की कोशिश की गई
- QUIC स्वयं पहले से Rust में implement था, इसलिए विकास Rust-आधारित quinn-udp library पर किया गया
- OS के बीच system call differences ने development को कठिन बनाया, लेकिन quinn-udp की वजह से development speed काफ़ी बेहतर रही
- 2025 के मध्य तक, यह बदलाव अधिकांश Firefox users तक पहुँचाया जा रहा है, और performance benchmarks में अधिकतम 4Gbit/s तक बड़ी बढ़त देखी गई
UDP I/O संरचना और आधुनिक optimization तरीके
single datagram ट्रांसमिशन
- पुराना तरीका
sendto और recvfrom का उपयोग करता था, जिसमें एक बार में सिर्फ एक UDP datagram भेजा या प्राप्त किया जाता था
- user space और kernel space के बीच switching cost हर datagram पर चुकानी पड़ती थी, इसलिए high-volume traffic environments में यह अप्रभावी था
- उदाहरण: 1500 bytes से छोटे packets को प्रति सेकंड सैकड़ों Mbit से अधिक गति पर भेजने में काफ़ी overhead पैदा होता है
multiple datagram batch ट्रांसमिशन
- Linux जैसे कुछ OS में
sendmmsg और recvmmsg जैसे multi-message system calls का समर्थन है
- कई datagrams को एक साथ भेजने/पाने से overhead को काफ़ी कम किया जा सकता है
single large segmented datagram
- GSO (transmit), GRO (receive) जैसी offload technologies के ज़रिए बड़े UDP datagram को OS या NIC पर अपने-आप विभाजित करके भेजा जा सकता है
- network interface packet स्तर पर अलगाव, checksum calculation और header attachment संभालता है
- इससे application layer सिर्फ एक system call से कई वास्तविक packets प्रोसेस कर सकती है
- GSO enabled होने पर Wireshark जैसे कुछ network tools में packet analysis support पर्याप्त नहीं होता
Firefox में NSPR replacement प्रक्रिया
- सबसे पहले single datagram send/receive संरचना में quinn-udp से NSPR को बदला गया
- QUIC implementation की datagram processing pipeline को batch send/receive और segmentation support के लिए refactor किया गया
- multi-message calls और segmentation offload calls दोनों का स्थिति के अनुसार उपयोग किया गया
- platform-specific exception handling और कई I/O improvements जोड़े गए
platform-specific विवरण
Windows
- Windows
WSASendMsg/WSARecvMsg देता है, जो पारंपरिक MTU-size datagram या बड़े segmented datagram का समर्थन करते हैं
- Linux के GSO/GRO के समकक्ष Windows में USO (transmit) / URO (receive) हैं
- शुरुआत में सिर्फ single datagram calls उपयोग करने पर कोई समस्या नहीं थी, लेकिन URO enable होने पर कुछ environments (जैसे Windows on ARM + WSL) में QUIC packet length का पता न लग पाने से page loading failure bug सामने आया
- USO/transmit भी उपयोग किया गया, लेकिन Firefox Windows install environments में packet loss बढ़ना और network driver crashes जैसी समस्याएँ मिलीं
- फिलहाल Firefox में URO/USO disabled रखे गए हैं और आगे debugging जारी है
MacOS
- MacOS पर मौजूदा
sendto/recvfrom की जगह sendmsg/recvmsg के साथ quinn-udp अपनाया गया
- segmentation offload feature enable नहीं है
- इसके बजाय, आधिकारिक रूप से documented न होने वाले
sendmsg_x/recvmsg_x से batch transmission का समर्थन मिला, जिसे quinn-udp में अनौपचारिक रूप से लागू किया गया
- Apple भविष्य में इन calls को हटा सकता है, इसलिए default enablement के बिना केवल testing की गई और वास्तविक release में इसे शामिल नहीं किया गया
Linux
- sendmmsg/recvmmsg और GSO/GRO दोनों supported हैं, और quinn-udp transmit के समय GSO को default preference देता है
- Firefox हर connection के लिए अलग UDP socket का उपयोग करता है ताकि privacy बेहतर हो सके (4-tuple distinction)
- इस संरचना में segmentation offload का लाभ अधिकतम हो जाता है, जबकि sendmmsg/recvmmsg के cross-transmission benefits सीमित रहते हैं
- network sandbox, runtime GSO support checks जैसे छोटे बदलावों के अलावा बिना विशेष कठिनाई के adoption सफल रहा
Android
- Android, Linux से अलग, system call processing path और security filters (जैसे seccomp) में भिन्न है
- x86-आधारित Android 5 जैसे बहुत पुराने platforms के support,
socketcall bypass, error handling आदि से जुड़े कई compatibility issues मौजूद थे
- कुछ environments में ECN bit enabled transmit calls पर error (
EINVAL) आया, जिस पर quinn-udp ने retry और option disable strategy लागू की
- Quinn community में हुए कई improvements का लाभ Firefox को भी अपने-आप मिल सका
ECN (Explicit Congestion Notification) support
- modern system calls अपनाने से ancillary data के send/receive का समर्थन मिला, जिससे QUIC ECN support संभव हुआ
- कुछ छोटे bugs थे, लेकिन Firefox Nightly में आधे से अधिक QUIC connections ECN outbound path पर काम कर रहे हैं
- L4S जैसी नई technologies पर ध्यान बढ़ने के साथ ECN support की अहमियत और उपयोगिता भी बढ़ रही है
निष्कर्ष सारांश
- Firefox के QUIC UDP I/O layer को quinn-udp-आधारित Rust implementation से बदलकर परफ़ॉर्मेंस और security दोनों हासिल किए गए
- पुराने system calls की जगह हर OS के आधुनिक I/O system calls का उपयोग कर throughput बढ़ा और ECN support संभव हुआ
- Windows जैसी कुछ optimizations को compatibility issues के कारण और सुधार की ज़रूरत है
- QUIC का उपयोग लगातार बढ़ने के साथ, आगे भी OS/driver स्तर के support में विकास जारी रहने की संभावना है
1 टिप्पणियां
Hacker News राय
लेख का मुख्य बिंदु बीच में छिपा हुआ है
यहाँ दिखाया गया सुधार असली ultra-high speed (100Gb/s से ऊपर) के लिए ज़रूरी तो है, लेकिन 4Gb/s वास्तव में कोई बहुत तेज़ गति नहीं है
500MB/s का मतलब है कि कहीं न कहीं कोई गंभीर धीमा bottleneck है
kernel context switch का 1us के स्तर पर होना, system call के हिसाब से भी काफ़ी ज़्यादा है
लेकिन अगर प्रति packet औसत केवल लगभग 500 byte भी हो, तो 500MB/s यानी 4Gb/s हासिल किया जा सकता है
पहले वाला 1Gb/s तब था जब packet size और छोटे थे, और UDP packet को बस NIC buffer में डालना memory copy speed से भी आसानी से हो सकता है
encryption धीमा है, यह बात भी व्यवहार में पूरी तरह सही नहीं है
उदाहरण के लिए, Intel i5-6500 ने 1729MB/s AES-128 GCM speed दिखाई थी
आज के CPU per-core 3-5GB/s, यानी 25-40Gb/s तक कर सकते हैं, इसलिए यहाँ बताए गए 4Gb/s का आँकड़ा बहुत कम लगता है
(AES-128 GCM performance संदर्भ लिंक)
system call latency ज़्यादा होने की बात कही गई, लेकिन इसका कारण spectre & meltdown mitigation हो सकता है
TCP में path binding होती है, लेकिन UDP में नहीं, इसलिए path setup में बड़ा फ़र्क पड़ता है
encryption धीमा है, यह छोटी PDU (protocol data unit) के मामले में सही बात है
ज़्यादातर optimization और benchmarking बड़े TCP frame के आधार पर की जाती है, इसलिए छोटे packet में state setup cost ज़्यादा उभरकर आती है
tight loop में microbenchmark चलाने पर numbers अच्छे दिखते हैं, लेकिन असली random environment में cache utilization भी कम हो जाता है, और 1KB से छोटे packet पर efficiency बहुत गिर जाती है
इसके ऊपर अतिरिक्त framing overhead, out-of-band data validation जैसी चीज़ें भी काफ़ी महँगी पड़ती हैं
UDP buffer memory की default value भी कम है, इसलिए practical use में कई समस्याएँ आती हैं
TCP चलाते समय buffer size लगातार बढ़ाए गए, लेकिन UDP अब भी 90~00 के दशक के conservative values पर अटका हुआ है
असल में जिस API की ज़रूरत है, वह है fd fork करके connect(2) और route binding का पूरा support, और उसके बाद submission queue आधारित तरीका (uring, rio आदि)
encryption के लिहाज़ से KDF approach state cost को काफ़ी घटा सकती है
PSP approach को कुछ vendor मानते हैं, लेकिन IETF जैसी संस्थाओं में इसे काफ़ी अस्वीकार किया गया, इसलिए यह व्यापक रूप से नहीं फैला
vendor के large-scale concurrency test में यह मौजूदा TLS-प्रकार के तरीकों की तुलना में कहीं बेहतर scaling दिखाता है
benchmark किए गए CPU का स्तर क्या था, इसका ज़रा भी ज़िक्र नहीं है
और encryption overhead, QUIC protocol की अपनी processing cost है
QUIC में encryption offload (hardware processing) TCP की तुलना में कमज़ोर है, जबकि TCP में kTLS offload के ज़रिए कुछ हद तक NIC processing संभव है
इस तरह का technical content वाकई बहुत संतोषजनक था
काश Mozilla की सारी technical material इसी तरह field engineer द्वारा ठीक से लिखी गई, गहराई वाली होती
बिना किसी optimism (alegria) के भी, यह पढ़ने लायक़ है
समझ नहीं आता कि Android 5 को अब तक क्यों support किया जा रहा है
उसे आए 10 साल से ज़्यादा हो चुके हैं, और जो लोग वे device इस्तेमाल कर रहे हैं, वे खुद और भी पुराने legacy user हैं
आज का web इतना भारी हो चुका है कि ऐसे पुराने device पर ठीक से browsing करना भी मुश्किल होगा, इसलिए इसे support करने की वजह समझ नहीं आती
शायद सिर्फ़ वे hacker जो पुराने OnePlus जैसे device को मरम्मत करके charger से लगाए रखते हैं, LineageOS जैसी आम ROM भी नहीं डालते, और alternative app store से Firefox चलाते हैं
व्यवहारिक रूप से यह केवल पूरी development speed को धीमा करने की लागत है
Factorio dev blog में "The map download struggle" नाम की पोस्ट में भी इससे जुड़ा एक दिलचस्प किस्सा है, इसलिए उसे भी पढ़ने की सिफ़ारिश है
(संबंधित blog post)
जिसने भी कभी असली network problem संभाली है, वह mysterious packet runts की वजह से इससे और ज़्यादा जुड़ाव महसूस करेगा
ज़्यादातर network equipment ऐसे packet को ठीक से handle नहीं कर पाते
UDP या QUIC आधारित ट्रैफिक किसी बड़े cloud environment के स्तर से कम पर बहुत आसानी से attack के असर में आ जाता है
इसी वजह से छोटे या self-hosted hosting provider के लिए संचालन लगातार कठिन होता जा रहा है, और अंत में वही बचते हैं जिनके पास बड़े traffic को संभालने की क्षमता है
इसलिए ज़्यादातर LAN environment में UDP traffic का बड़ा हिस्सा drop कर दिया जाता है और सिर्फ़ ज़रूरी हिस्से को rate limit के साथ process किया जाता है
Mozilla bug tracker
macOS और Fedora पर Cloudflare-hosted site को Firefox से खोलते समय अब भी वही समस्या आ रही है
आज पता चला कि Windows और MacOS में भी GSO/GRO (large network packet processing) जैसी सुविधाएँ हैं
लेकिन अफ़सोस है कि व्यवहार में उनमें काफ़ी bugs बताए जाते हैं
लगता है bug सिर्फ़ GSO/GRO तक सीमित नहीं होंगे
क्या कोई समझा सकता है कि UDP GSO/GRO संरचनात्मक रूप से कैसे काम करता है?
UDP में ordered packet नहीं होते, तो जब एक QUIC packet कई UDP packet में बँट जाता है और header में sequence information भी नहीं होती, तब receiver side पर उन्हें क्रम में जोड़कर कैसे संभाला जाता है, यह जानना चाहता हूँ
kernel कई datagram को एक structure में रखकर, हर layer के बीच boundary (जैसे sk_buff में data fragments) बनाए रखते हुए आगे भेजता है
मैं इस विषय का सटीक विशेषज्ञ नहीं हूँ, लेकिन यह कैसे काम करता है यह खोजते समय मुझे यह लेख मिला
यह कहा गया कि "हमने Quinn project की UDP I/O library, quinn-udp, के ऊपर development शुरू किया, और इससे development speed बहुत बढ़ गई"
तो यह जानने की जिज्ञासा है कि क्या Quinn project को funding भी दी गई थी
(Quinn funding लिंक)
funding support के बारे में सीधे पूछने पर Mozilla के एक Senior Principal Software Engineer ने जवाब दिया, "Mozilla के पास पैसे नहीं हैं"
लेकिन उन्होंने code में बहुत बड़ा योगदान दिया है, जिसके लिए हम वास्तव में आभारी हैं
(मैं Quinn का maintainer हूँ)
"क्या funding दी गई?" इस सवाल पर यह राय भी आई कि open source funding न करके CEO salary पर कुछ और million dollar खर्च करना ही Mozilla का तरीका है
जबकि उनका flagship product (Firefox) तक गिरावट में है
अगर code आदि के रूप में किसी और तरीके से योगदान दिया गया है, तो उसके बारे में जानना चाहूँगा
sendmmsg/recvmmsg को “modern” कहा जाना चौंकाने वाला है
ये दरअसल काफ़ी लंबे समय से मौजूद system call हैं
Linux से जुड़े इस विषय में io_uring का भी ज़िक्र होगा, यह उम्मीद थी, लेकिन वह नहीं था, इसलिए कमी महसूस हुई
ज़्यादा से ज़्यादा यह sendmsg, recvmsg के कई request एक साथ करने जैसा है
GSO/GRO ही सही जवाब है
sendmmsg/recvmmsg पहले से ही बहुत पुरानी तकनीक हैं, और kernel developer में से कुछ तो अब इन्हें हटाना भी चाहते हैं
(संबंधित GitHub discussion)