परिचय
हमारे 0.5.0 रिलीज ब्लॉग पोस्ट में, हमने घोषणा की कि थ्रेड-प्रति-कोर, साझा कुछ भी नहीं डिजाइन के साथ io_uring का उपयोग करके अपाचे इग्गी के कोर आर्किटेक्चर के पूर्ण पुनर्लेखन पर काम चल रहा था। इस आर्किटेक्चरल रीडिज़ाइन का उद्देश्य प्रदर्शन को और बेहतर बनाना, विलंब को कम करना और संसाधन के उपयोग को कम करना है io_ureing के पूर्णता आधारित I/O मॉडल का लाभ उठाना.
इस पुनर्लेखन के भाग के रूप में, हम टोकियो से कॉम्पियो में चले गए, एक पूर्णता-आधारित एसिंक रनटाइम जो हमें io_ureing क्षमताओं का बेहतर उपयोग करने की अनुमति देता है। हालाँकि, व्यापक रस्ट पारिस्थितिकी तंत्र के साथ एकीकरण करते समय यह विभिन्न चुनौतियाँ भी प्रस्तुत करता है।
हमें ऐसी ही एक चुनौती का सामना करना पड़ा जब हमें Iggy सर्वर में WebSocket समर्थन जोड़ने की आवश्यकता पड़ी। वेबसॉकेट ब्राउज़र क्लाइंट और स्ट्रीमिंग डैशबोर्ड के लिए उपयोगी हैं। रस्ट इकोसिस्टम में टंगस्टनाइट और टोकियो-टंगस्टनाइट जैसी उत्कृष्ट वेबसॉकेट लाइब्रेरी हैं, लेकिन वे तब बनाई गई हैं जब पोल-आधारित आईओ प्रमुख आईओ प्रतिमान था। वे साझा बफ़र्स और तत्परता-आधारित I/O की अपेक्षा करते हैं, जो मूल रूप से कंपियो के पूर्णता-आधारित मॉडल के साथ असंगत है जिसके लिए स्वामित्व वाले बफ़र्स की आवश्यकता होती है।
यहां हम कंपियो-डब्ल्यूएस के निर्माण की हमारी यात्रा, कंपियो एसिंक रनटाइम के लिए एक वेबसॉकेट कार्यान्वयन और दो मौलिक रूप से भिन्न I/O मॉडल को पाटने में हमारे सामने आने वाली इंजीनियरिंग चुनौतियों का वर्णन करते हैं और अंततः यह हमें योगदान देने के लिए प्रेरित करती है। compio.
वास्तुशिल्प विभाजन को समझना (मतदान बनाम पूर्णता)।
आइए देखें कि कंपियो, टंगस्टनाइट के लक्षणों की जांच करके पोल-आधारित लाइब्रेरी आसानी से पूर्णता आधारित रनटाइम के साथ काम क्यों नहीं कर सकती हैं।
pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
}
pub trait AsyncRead {
async fn read<B: IoBufMut>(&mut self, buf: B) -> BufResult<usize, B>;
}
पढ़ें विशेषता मानती है कि आप एक बफर उधार लेते हैं। Compio के AsyncRead को बफ़र का स्वामित्व लेने, इसे कर्नेल में सबमिट करने और बाद में इसे वापस करने की आवश्यकता है।
pub struct WebSocket<Stream> {
socket: Stream,
}
impl<Stream: Read + Write> WebSocket<Stream> {
pub fn read(&mut self) -> Result<Message> {
}
}
कंपियो के स्वामित्व-बफर मॉडल के साथ सीधे इस काम को करने का कोई तरीका नहीं है। अमूर्तताएँ मौलिक रूप से असंगत हैं।
जब हमें WebSocket समर्थन जोड़ने की आवश्यकता होती है, तो हम केवल टोकियो-टंगस्टेनाइट को नहीं छोड़ सकते हैं, जो इसका उपयोग करता है future_util::io::AsyncRead प्रवृत्ति। हमें एक एडॉप्टर की आवश्यकता है जो:
- कंपियो के स्वामित्व वाले बफर एसिंक I/O के साथ काम करता है
- टंगस्टनाईट के समकालिक पढ़ने/लिखने के लक्षण प्रस्तुत करता है
- सिंक और एसिंक दुनिया को कुशलतापूर्वक पाटता है
टंगस्टेनाइट के साथ चुनौती
टंगस्टेनाइट वास्तव में रस्ट वेबसॉकेट प्रोटोकॉल कार्यान्वयन है। यह सभी WebSocket प्रोटोकॉल तर्क को संभालता है:
- फ़्रेम पार्सिंग और जेनरेशन
- संदेश विखंडन
- नियंत्रण फ़्रेम (पिंग, पोंग, बंद करें)
- प्रोटोकॉल उल्लंघन और त्रुटि प्रबंधन
- पाठ एन्कोडिंग सत्यापन
हमारा प्रारंभिक विचार एसिंक-टंगस्टेनाइट में योगदान करना था, जो रनटाइम-अज्ञेयवादी वेबसॉकेट समर्थन प्रदान करता है। इसमें विशेषता-आधारित अमूर्तन के माध्यम से एकाधिक एसिंक रनटाइम के लिए एडाप्टर हैं। लेकिन जैसे-जैसे हमने कंपियो के लिए इसे अनुकूलित करने में गहराई से काम किया, हमें एक बुनियादी असंगति का एहसास हुआ
अहसास: एसिंक-टंगस्टनाइट पोल-आधारित आईओ के साथ मजबूती से जुड़ा हुआ है
असंगति तब स्पष्ट हो जाती है जब हम कंपियो और फ्यूचर के AsyncRead के AsyncRead लक्षणों की जांच करते हैं
async fn read<B: IoBufMut>(&mut self, buf: B) -> BufResult<usize, B>;
fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<io::Result<usize>>;
ये मौलिक रूप से अलग-अलग प्रोग्रामिंग मॉडल हैं जो साफ-सुथरे ढंग से रचना नहीं करते हैं।
निर्णय: एक अलग टोकरा
असंगति का एहसास होने के बाद, हमने बनाने का निर्णय लिया है compio-ws एक स्टैंडअलोन टोकरे के रूप में. वास्तुकला होगी:
┌────────────────────────────┐
│ Application Code │
└──────────────┬─────────────┘
│
┌──────────────▼──────────────┐
│ compio-ws │
│ WebSocket handshake / API │
└──────────────┬──────────────┘
│
┌──────────▼──────────┐
│ Tungstenite │
│ (Protocol) │
└──────────┬──────────┘
│
┌──────────────────▼────────────────────┐
│ Bridge Layer │
│ (GrowableSyncStream) │
│ Sync Read/Write ↕ Async Buffer I/O │
└──────────────────┬────────────────────┘
│
┌──────────▼──────────┐
│ Compio Runtime │
│ (io_uring I/O) │
└─────────────────────┘
मुख्य अंतर्दृष्टि: हमें एक ब्रिज परत की आवश्यकता है जो आंतरिक रूप से कंपियो के एसिंक्स स्वामित्व-बफर I/O का उपयोग करते हुए टंगस्टनाइट को सिंक्रोनस रीड/राइट गुण प्रदान करती है।
पहला प्रयास: SyncStream
Compio पहले से ही प्रदान करता है SyncStream में compio-io::compat मॉड्यूल विशेष रूप से पुस्तकालयों के साथ इंटरऑपरेटिंग के लिए जो सिंक्रोनस I/O लक्षणों की अपेक्षा करता है। यह एक चतुर संरचना है जो एसिंक/सिंक सीमा को पाटने के लिए आंतरिक बफ़र्स को बनाए रखती है:
pub struct SyncStream<S> {
stream: S,
eof: bool,
read_buffer: Buffer,
write_buffer: Buffer,
}
impl<S> SyncStream<S> {
pub fn new(stream: S) -> Self {
Self::with_capacity(DEFAULT_BUF_SIZE, stream)
}
}
डिफ़ॉल्ट DEFAULT_BUF_SIZE 8KB है, लेकिन आप अपनी इच्छानुसार कोई भी क्षमता निर्दिष्ट कर सकते हैं। एक बार बन जाने के बाद, बफ़र क्षमता निश्चित हो जाती है। यह कभी नहीं बढ़ता. यह एक समस्या हो सकती है, जिस पर हम नीचे चर्चा करेंगे, साथ पढ़ें।
यह ऐसे काम करता है:
पढ़ना (async से सिंक):
impl<S> Read for SyncStream<S> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let available = self.read_buffer.slice();
if available.is_empty() && !self.eof {
return Err(io::Error::new(
io::ErrorKind::WouldBlock,
"need to fill the read buffer"
));
}
let to_read = available.len().min(buf.len());
buf[..to_read].copy_from_slice(&available[..to_read]);
self.read_buffer.advance(to_read);
Ok(to_read)
}
}
impl<S: AsyncRead> SyncStream<S> {
pub async fn fill_read_buf(&mut self) -> io::Result<usize> {
let len = self.read_buffer
.with(|b| async move {
let len = b.buf_len();
let b = b.slice(len..);
self.stream.read(b).await.into_inner()
})
.await?;
if len == 0 {
self.eof = true;
}
Ok(len)
}
}
लेखन (async से सिंक):
impl<S> Write for SyncStream<S> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
if self.write_buffer.need_flush() {
return Err(io::Error::new(
io::ErrorKind::WouldBlock,
"need to flush the write buffer"
));
}
let len = buf.len().min(self.write_buffer.remaining_capacity());
Ok(len)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl<S: AsyncWrite> SyncStream<S> {
pub async fn flush_write_buf(&mut self) -> io::Result<usize> {
let len = self.write_buffer.flush_to(&mut self.stream).await?;
self.stream.flush().await?;
Ok(len)
}
}
पैटर्न है:
- साथ-साथ करना
read()/write()आंतरिक बफ़र्स पर कार्य करें - वापस करना
WouldBlockजब बफ़र खाली/भरा हो - एसिंक्स को कॉल करें
fill_read_buf()/flush_write_buf()सेवा बफ़र्स के लिए - सिंक ऑपरेशन पुनः प्रयास करें
यह टंगस्टेनाइट को कंपियो स्ट्रीम के साथ काम करने की अनुमति देता है:
let stream = TcpStream::connect("127.0.0.1:8080").await?;
let sync_stream = SyncStream::new(stream);
let mut websocket = WebSocket::from_raw_socket(sync_stream, Role::Client);
loop {
match websocket.read() {
Ok(msg) => process(msg),
Err(Error::Io(e)) if e.kind() == ErrorKind::WouldBlock => {
websocket.get_mut().fill_read_buf().await?;
continue;
}
Err(e) => return Err(e),
}
}
निश्चित बफ़र आकार के साथ समस्या SyncStream
प्रारंभिक कार्यान्वयन ने बफ़र से छोटे संदेशों के लिए पूरी तरह से काम किया। वेबसॉकेट हैंडशेक पूरा हुआ, पिंग/पोंग फ्रेम का आदान-प्रदान हुआ, टेक्स्ट संदेश प्रवाहित हुए। सब कुछ ठीक लग रहा था.
फिर हमने बड़े संदेशों के साथ परीक्षण किया और प्रदर्शन ध्वस्त हो गया।
समस्या परिदृश्य: डिफ़ॉल्ट 8KB सिंकस्ट्रीम बफर के साथ WebSocket के माध्यम से 16MB बाइनरी संदेश भेजना:
यहाँ अंदर क्या होता है:
Message: 16MB
↓
Tungstenite frames it
↓
Calls write() on SyncStream with chunks
↓
SyncStream buffer: 8KB capacity (fixed!)
Round 1: Write 8KB → Buffer full → WouldBlock
→ flush_write_buf() → 8KB to kernel
Round 2: Write 8KB → Buffer full → WouldBlock
→ flush_write_buf() → 8KB to kernel
...
Total: 2048 round trips (16MB / 8KB = 2048)
माप ख़राब थे:
- समय: 16 एमबी भेजने में 100 सेकंड से अधिक
- मेमोरी: बार-बार बफर हैंडलिंग से अत्यधिक आवंटन। कभी-कभी इसके कारण ओएस द्वारा वेबसोकेट प्रक्रिया OOM को ख़त्म कर देती है।
प्रत्येक WouldBlock -> एसिंक कॉल -> पुनः प्रयास चक्र शामिल:
- टंगस्टनाइट में राज्य की बचत
- सिंक कॉल को निलंबित किया जा रहा है
- एसिंक फ्लश निष्पादित करना
- सिंक कॉल फिर से शुरू हो रही है
सिंक विशेषता अनुबंध को तत्काल सफलता की आवश्यकता है या WouldBlock. यह कहने का कोई तरीका नहीं है कि “मुझे एक बड़े बफ़र की आवश्यकता है” या “बफ़र बढ़ाते समय मुझे आंशिक प्रगति दें।” प्रत्येक WouldBlock संपूर्ण एसिंक राउंड ट्रिप को बाध्य करता है।
हमने इसे बढ़ाने का स्पष्ट समाधान आज़माया SyncStream बफ़र आकार 1एमबी तक। जिसने पूरी तरह से काम किया और कंपियो-डब्ल्यूएस ने मानक ऑटोबान टेस्टसूट में सभी परीक्षण पास कर लिए। लेकिन यह समाधान तब भी नाजुक होता है जब उपयोगकर्ता को अपने कार्यभार के चरम मेमोरी उपयोग का पता नहीं होता है और इससे सर्वर संसाधनों की अधिकता और बर्बादी हो सकती है।
समाधान: GrowableSyncStream
डिज़ाइन लक्ष्य:
- गतिशील वृद्धि: बफ़र्स छोटे से शुरू होते हैं और आवश्यकतानुसार बढ़ते हैं
- सीमाबद्ध अधिकतम: विन्यास योग्य सीमाओं के साथ स्मृति थकावट को रोकें
- स्वचालित सिकुड़न: सीमा के आधार पर आधार क्षमता पर लौटें
- न्यूनतम राउंड ट्रिप: बिना किसी स्थिरता के बड़े संदेशों को संभालें
WouldBlock
वास्तुकला अवलोकन:
pub struct GrowableSyncStream<S> {
inner: S,
read_buf: Vec<u8>,
read_pos: usize,
write_buf: Vec<u8>,
eof: bool,
base_capacity: usize,
max_buffer_size: usize,
}
बफर विकास रणनीति:
- छोटे आकार के बफ़र से प्रारंभ करें (128 KB मिलान टंगस्टनाइट डिफ़ॉल्ट बफ़र आकार)
- की अनुमानित वृद्धि में वृद्धि करें
base_capacityआकार के टुकड़े - उचित सीमा पर कैप वृद्धि (64एमबी डिफ़ॉल्ट)
- वापस सिकोड़ें
base_capacityजब सारा डेटा खपत हो जाए और वर्तमान आकार > 4x आधार_क्षमता
प्रमुख संचालन:
पथ पढ़ें:
- आवश्यकता पड़ने पर बफर को संकुचित करता है (अपठित डेटा को सामने ले जाता है)
- में बढ़ता है
base_capacityके दौरान वेतन वृद्धिfill_read_buf() - जब सभी डेटा का उपभोग हो जाता है और बफर > 4× आधार हो जाता है तो यह वापस आधार पर सिकुड़ जाता है
पथ लिखें:
Vec::extend_from_sliceतक विकास को स्वचालित रूप से संभालता हैmax_buffer_size- रिटर्न
WouldBlockकेवल अधिकतम सीमा के करीब पहुंचने पर flush_write_buf()प्रगतिशील फ्लशिंग को संभालता है और वापस बेस तक सिकुड़ जाता है
इन परिवर्तनों के साथ कंपियो-डब्ल्यूएस सभी परीक्षणों को सफलतापूर्वक पास कर लेता है autobahn-testsuite वह tokio-tungstenite गुजरता है.
बेंचमार्क
बेंचमार्क पद्धति
कंपियो-डब्ल्यूएस की वास्तविक दुनिया की प्रदर्शन विशेषताओं को समझने के लिए, हमने अपाचे इग्गी के पिन किए गए निर्माता बेंचमार्क और पिन किए गए उपभोक्ता बेंचमार्क को चलाया।
निम्नलिखित बेंचमार्क 24.04 Ubuntu OS का उपयोग करके AWS i3en.3xlarge इंस्टेंस का उपयोग करके चलाए जाते हैं।
हार्डवेयर विशिष्टताएँ:
- CPU: Intel Xeon प्लैटिनम 8259CL @ 2.50GHz (कैस्केड लेक)
- कोर: हाइपरथ्रेडिंग के साथ 6 भौतिक कोर (कुल 12 वीसीपीयू)
- कैश: 36 एमबी एल3 कैश
- याद: 96 जीबी रैम
- भंडारण: स्थानीय एनवीएमई एसएसडी
सामान्य बेंचमार्क सेटिंग का उपयोग किया जाता है:
- हर एक संदेश में fsync और fsync सक्षम करें (
export IGGY_SYSTEM_PARTITION_ENFORCE_FSYNC=trueऔरexport IGGY_SYSTEM_PARTITION_MESSAGES_REQUIRED_TO_SAVE=1) - लिनक्स में बड़े पेजों का उपयोग करें।
sudo sysctl -w vm.swappiness=10
sudo sysctl -w vm.dirty_background_ratio=10
sudo sysctl -w vm.dirty_ratio=30
sudo sysctl -w vm.nr_hugepages=2048
export MIMALLOC_ALLOW_LARGE_OS_PAGES=1
export MIMALLOC_RESERVE_HUGE_OS_PAGES=2048
कार्यभार विशेषताएँ:
- 4 निर्माता (प्रति सीपीयू कोर एक)
- 4 स्ट्रीम, 1 विषय प्रति स्ट्रीम, 1 विभाजन प्रति विषय
- प्रति बैच 1000 संदेश
- 40,000 बैच
- प्रति संदेश 1000 बाइट्स
- कुल: 40M संदेश, 40GB डेटा
हमने दो परिदृश्यों की तुलना की:
- टीसीपी: डायरेक्ट टीसीपी कनेक्शन (बेसलाइन)
- WebSocket: GrowableSyncStream के साथ कंपियो-डब्ल्यूएस
परिणाम: टीसीपी बनाम वेबसॉकेट
| प्रतिशतता | टीसीपी | वेबसॉकेट | अंतर |
|---|---|---|---|
| औसत | 2.61 एमएस | 3.43 एमएस | +0.82 एमएस (31.4% अधिक) |
| माध्यिका (P50) | 2.58 एमएस | 3.34 एमएस | +0.76 एमएस (29.5% अधिक) |
| पी95 | 2.94 एमएस | 4.00 मि.से | +1.06 एमएस (36.1% अधिक) |
| पी99 | 3.63 एमएस | 4.56 एमएस | +0.93 एमएस (25.6% अधिक) |
| पी999 | 3.84 एमएस | 5.27 एमएस | +1.43 एमएस (37.2% अधिक) |
| पी9999 | 5.27 एमएस | 9.48 मि.से | +4.21 एमएस (79.9% अधिक) |
| अधिकतम | 11.63 एमएस | 16.88 एमएस | +5.25 एमएस (45.1% अधिक) |
| मिन | 1.93 एमएस | 2.60 एमएस | +0.67 एमएस (34.7% अधिक) |
बेंचमार्क ग्राफ़:
टी.सी.पी

वेबसॉकेट

आगे हम पिन किए गए उपभोक्ता बेंचमार्क को देखते हैं।
कार्यभार विशेषताएँ:
- 4 उपभोक्ता (प्रति सीपीयू कोर एक)
- 4 स्ट्रीम, 1 विषय प्रति स्ट्रीम, 1 विभाजन प्रति विषय
- प्रति बैच 1000 संदेश
- 40,000 बैच
- प्रति संदेश 1000 बाइट्स
- कुल: 40M संदेश, 40GB डेटा
| प्रतिशतता | टीसीपी | वेबसॉकेट | अंतर |
|---|---|---|---|
| औसत | 0.70 एमएस | 1.44 मि.से | +0.74 एमएस (105.7% अधिक) |
| माध्यिका (P50) | 0.68 एमएस | 1.41 एमएस | +0.73 एमएस (107.4% अधिक) |
| पी95 | 0.85 एमएस | 1.73 एमएस | +0.88 एमएस (103.5% अधिक) |
| पी99 | 1.00 मि | 1.95 एमएस | +0.95 एमएस (95.0% अधिक) |
| पी999 | 1.32 एमएस | 2.26 एमएस | +0.94 एमएस (71.2% अधिक) |
| पी9999 | 1.54 मि.से | 2.52 एमएस | +0.98 एमएस (63.6% अधिक) |
| अधिकतम | 2.02 एमएस | 10.44 मि.से | +8.42 एमएस (416.8% अधिक) |
| मिन | 0.55 एमएस | 1.14 मि.से | +0.59 एमएस (107.3% अधिक) |
बेंचमार्क ग्राफ़:
टी.सी.पी

वेबसॉकेट

विश्लेषण:
परिणाम मापने योग्य लेकिन दिखाते हैं उचित WebSocket परत से ओवरहेड:
निर्माता विलंबता: WebSocket अधिकांश प्रतिशत में ~0.8-1.0ms जोड़ता है (TCP से 30-40% अधिक)। यहां तक कि P9999 पर भी, हम 9.48ms विलंबता प्राप्त करते हैं – fsync-प्रति-संदेश सक्षम होने के साथ टिकाऊ कार्यभार के लिए प्रभावशाली।
उपभोक्ता विलंबता: WebSocket ~0.7-1.0ms जोड़कर लगभग 2× कच्चे टीसीपी की विलंबता दिखाता है। 2.52ms का P9999 उच्च प्रतिशत पर भी लगातार प्रदर्शन प्रदर्शित करता है।
स्थायित्व संबंधी बाधाओं के तहत, उत्पादकों के लिए P9999 और उपभोक्ताओं के लिए उप-3ms पर एकल-अंक मिलीसेकंड विलंबता प्राप्त करना काफी अच्छा है।
एडाप्टर परत लागत: वर्तमान कार्यान्वयन सिंक और एसिंक I/O मॉडल के बीच एक सेतु के रूप में GrowableSyncStream का उपयोग करता है। बफ़र रैखिक वृद्धि में बढ़ता है, जो बड़े संदेशों के लिए उप-इष्टतम हो सकता है। हालाँकि, पूर्णता-आधारित रनटाइम में वेबसॉकेट समर्थन को सक्षम करने वाले इस पहले कार्यान्वयन के लिए, प्रदर्शन स्वीकार्य है।
वेबसॉकेट प्रोटोकॉल ओवरहेड:
- वेबसॉकेट फ़्रेमिंग: प्रत्येक संदेश को फ़्रेम हेडर की आवश्यकता होती है।
- मास्किंग: पेलोड पर XOR ऑपरेशन
पूंछ विलंबता संगति: GrowableSyncStream उच्च प्रतिशत पर भी लगभग आनुपातिक ओवरहेड बनाए रखता है। P9999 बड़े निरपेक्ष अंतर दिखाता है लेकिन प्रतिशत-वार कम प्रतिशत के अनुरूप रहता है, जो लोड के तहत पूर्वानुमानित व्यवहार का संकेत देता है।
भविष्य का कार्य
-
होशियार बफर ग्रोथ
- वर्तमान: रैखिक
base_capacityवेतन वृद्धि - बेहतर: घातीय वृद्धि (जैसे
Vec::reserve) - प्रभाव: बड़े संदेशों के लिए पुनर्आवंटन ओवरहेड कम करें
- वर्तमान: रैखिक
-
बफ़र पूलिंग
- वर्तमान: प्रति संदेश आवंटित/हटाएं
- बेहतर: ऑब्जेक्ट पुन: उपयोग के साथ प्रति-कोर बफर पूल
- प्रभाव: आवंटनकर्ता दबाव कम करें
-
मूल स्वामित्व वाले बफ़र्स के साथ वेबसॉकेट कार्यान्वयन
- शुरुआत से ही स्वामित्व वाले बफ़र्स के साथ सीधे WebSocket प्रोटोकॉल लागू करें।
- io_ureing क्षमताओं का उपयोग करने के लिए कंपियो के साथ सीधा एकीकरण।
- प्रदर्शन में उल्लेखनीय वृद्धि हो सकती है.
- पूर्ण आरएफसी अनुपालन के कारण यह एक महत्वपूर्ण उपक्रम है।
हमने योगदान दिया compio-ws को compio और सुधार में रुचि रखने वाला कोई भी compio-ws में योगदान दे सकता है compio.
निष्कर्ष
इग्गी में वर्तमान स्थिति: वेबसॉकेट समर्थन वर्तमान में उपभोक्ता पक्ष पर लंबे मतदान के साथ लागू किया गया है और भविष्य के रिलीज के लिए पुश-आधारित सूचनाओं की योजना बनाई गई है। इसका उत्पादकों और उपभोक्ताओं पर अलग-अलग प्रभाव पड़ता है।
उपभोक्ताओं के लिए (संदेश प्राप्त करना): वर्तमान लंबे मतदान कार्यान्वयन का मतलब है कि उपभोक्ताओं को बार-बार नए संदेशों का अनुरोध करना होगा, भले ही कोई भी उपलब्ध न हो। यह अक्षम है, विशेष रूप से कम-शक्ति वाले एज ग्राहकों के लिए।
निर्माताओं के लिए (संदेश भेजना): WebSocket तत्काल लाभ प्रदान करता है। नए कनेक्शन स्थापित करने या अक्षम लंबे मतदान का उपयोग करने के बजाय, निर्माता लगातार वेबसॉकेट कनेक्शन बनाए रख सकते हैं और संदेशों को सीधे सर्वर पर भेज सकते हैं। यह इनके लिए विशेष रूप से मूल्यवान है:
- ब्राउज़र-आधारित निर्माता ईवेंट या टेलीमेट्री भेज रहे हैं
- एज डिवाइस सेंसर डेटा या मेट्रिक्स की रिपोर्टिंग करते हैं
- डैशबोर्ड एप्लिकेशन कमांड या कॉन्फ़िगरेशन अपडेट भेज रहे हैं
आगे क्या होगा: जबकि GrowableSyncStream के साथ कंपियो-डब्ल्यूएस आज WebSocket समर्थन को सक्षम बनाता है, महत्वपूर्ण अनुकूलन क्षमता बनी हुई है। जमीनी स्तर से स्वामित्व वाले बफ़र्स के लिए डिज़ाइन किया गया एक मूल WebSocket कार्यान्वयन एडाप्टर परत ओवरहेड को समाप्त कर सकता है और io_uring की शून्य-कॉपी क्षमताओं की पूर्ण प्रदर्शन क्षमता को अनलॉक कर सकता है। हम रस्ट समुदाय को योगदान देने के लिए आमंत्रित करते हैं:
- अनुकूलन
GrowableSyncStream: घातीय बफ़र वृद्धि और पूलिंग लागू करें - स्वामित्व वाले बफ़र WS प्रोटोकॉल कार्यान्वयन: स्वामित्व वाले बफ़र्स के साथ शुरुआत से वेबसॉकेट बनाएं
- पुश-आधारित उपभोक्ता: Iggy में सर्वर-पुश नोटिफिकेशन लागू करने में सहायता करें
- एज क्लाइंट लाइब्रेरीज़: संसाधन-बाधित उपकरणों के लिए अनुकूलित WebSocket SDK बनाएं