2 पॉइंट द्वारा GN⁺ 2025-10-28 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • लेखक ने Zig भाषा सीखते हुए AcoustID index rewrite प्रोजेक्ट पर काम किया और नेटवर्क प्रोग्रामिंग की सीमाओं के कारण एक नया approach आज़माया
  • C++ और Go में इस्तेमाल किए गए asynchronous I/O और concurrency model को Zig में भी लागू करने के लिए उन्होंने अपनी खुद की library बनाने का फैसला किया
  • इसके परिणामस्वरूप, Zig के लिए Go-style concurrency model को अनुकूलित करके बनाई गई Zio library तैयार हुई, जिससे callback के बिना synchronous जैसा दिखने वाला asynchronous code लिखा जा सकता है
  • Zio asynchronous network·file I/O, channels, synchronization primitives, signal monitoring आदि को support करती है, और single-thread mode में Go या Rust के Tokio से तेज़ performance दिखाती है
  • यह प्रोजेक्ट Zig के system-level performance और modern concurrency model के संयोजन की संभावना को दिखाता है, और Zig ecosystem के विस्तार में एक महत्वपूर्ण मोड़ माना जाता है

Zig भाषा और शुरुआती प्रेरणा

  • लेखक पहले से Zig पर नज़र रखे हुए थे, जिसे मूल रूप से audio software के लिए low-level language के रूप में डिज़ाइन किया गया था, लेकिन उन्हें इसकी कोई ठोस ज़रूरत महसूस नहीं हुई थी
    • Zig के creator Andrew Kelley ने लेखक के Chromaprint algorithm को Zig में reimplement किया था, और इसी से उनकी रुचि बढ़ी
  • AcoustID के reverse index rewrite project को उन्होंने Zig सीखने के अवसर के रूप में लिया, और परिणामस्वरूप C++ version की तुलना में ज़्यादा तेज़ और अधिक scalable implementation हासिल की
  • लेकिन server interface जोड़ने के चरण में उन्हें asynchronous networking support की कमी की समस्या का सामना करना पड़ा

मौजूदा approach और सीमाएँ

  • पहले के C++ version में Qt framework का उपयोग करके asynchronous I/O संभाला जाता था; यह callback-based था, लेकिन समृद्ध support के कारण उपयोगी था
  • बाद के prototype में Go भाषा की networking और concurrency की सुविधा का लाभ उठाया गया, लेकिन Zig में उसी स्तर का abstraction मौजूद नहीं था
  • Zig में TCP server और cluster layer लागू करने के लिए कई thread बनाने पड़ते, जो अप्रभावी था
    • इसे हल करने के लिए उन्होंने NATS messaging system के लिए Zig client (nats.zig) खुद लिखा और Zig की networking capabilities का गहराई से अध्ययन किया

Zio library का आगमन

  • इन अनुभवों के आधार पर उन्होंने Zio: Zig के लिए asynchronous I/O और concurrency library जारी की
  • Zio का लक्ष्य callback के बिना asynchronous code लिखना है; अंदरूनी रूप से asynchronous I/O चलता है, लेकिन बाहर से इसकी संरचना synchronous जैसी दिखती है
  • इसमें Go-style concurrency model को Zig के अनुरूप सीमित रूप में लागू किया गया है
    • Zio के task fixed-size stack वाले stackful coroutine के रूप में होते हैं
    • stream.read() call पर I/O काम background में चलता है, और पूरा होने पर task फिर से resume होकर result लौटाता है
  • यह तरीका state management को सरल बनाता है और code readability भी बेहतर करता है

फीचर संरचना और runtime architecture

  • Zio पूर्ण asynchronous network और file I/O, synchronization primitives (mutex, condition variable आदि), Go-style channels, OS signal monitoring आदि को support करती है
  • Task को single-thread या multi-thread mode में चलाया जा सकता है
    • multi-thread mode में task thread के बीच move हो सकते हैं, जिससे latency कम होती है और load balancing बेहतर होती है
  • यह standard Reader/Writer interface लागू करती है, जिससे external libraries के साथ compatibility सुनिश्चित होती है

performance और तुलना

  • लेखक ने अभी तक कोई official benchmark जारी नहीं किया है, लेकिन उनका कहना है कि single-thread mode में performance Go और Rust के Tokio से तेज़ है
  • context switching की लागत function call के स्तर तक कम है, यानी switching speed लगभग मुफ्त जैसी है
  • multi-thread mode अभी Go/Tokio जितना robust नहीं है, लेकिन मिलती-जुलती या थोड़ी बेहतर performance दिखाता है
    • भविष्य में fairness feature जुड़ने पर performance कुछ कम हो सकती है

उदाहरण code और उपयोग

  • दस्तावेज़ में Zio-आधारित HTTP server example code शामिल है
    • zio.net.Stream का उपयोग करके connection accept किए जाते हैं, और हर connection को अलग task में संभाला जाता है
    • zio.Runtime task execution और I/O scheduling को manage करता है
  • यह संरचना asynchronous I/O को synchronous code की तरह लिखने की सुविधा देती है, और स्पष्ट flow control तथा resource cleanup management को संभव बनाती है

आगे की योजना और महत्व

  • लेखक ने Zio के माध्यम से पुष्टि की कि Zig सिर्फ high-performance system code के लिए भाषा नहीं है, बल्कि पूर्ण network application development language के रूप में भी विकसित हो सकती है
  • अगले चरण में वे NATS client को Zio-आधारित रूप में फिर से लिखने और Zio-आधारित HTTP client/server library विकसित करने की योजना बना रहे हैं
  • यह प्रोजेक्ट Zig ecosystem की networking·concurrency infrastructure के विस्तार को आगे बढ़ाता है, और Go या Rust के समकक्ष modern runtime model बनाने के प्रयास के रूप में देखा जाता है

1 टिप्पणियां

 
GN⁺ 2025-10-28
Hacker News राय
  • कहा जाता है कि context switching function call स्तर पर लगभग मुफ्त है, लेकिन व्यवहार में branch predictor टूटने जैसी सूक्ष्म लागतें होती हैं
    यह स्पष्ट नहीं है कि Zig का async डिज़ाइन hardware call/return जोड़ों का उपयोग करता है, या indirect jump आधारित रूप में translate होता है
    सही benchmark करने के लिए, दो tasks के बीच लगातार switching वाले program और पूरी तरह synchronous program के कुल execution time की तुलना करनी होगी। यह काफ़ी पेचीदा काम है
    • stackless coroutine में अगर call stack के सबसे नीचे दो tasks को लगातार switch किया जाए, और stack switching code inline हो, तो call/ret mismatch penalty से ज़्यादातर बचा जा सकता है
      अगर compiler को नियंत्रित किया जा सके, तो I/O code के call/ret को explicit jump में बदलना भी संभव है
      लंबे समय में, उम्मीद है कि CPU stackful coroutine को बेहतर predict करने के लिए meta-predictor जोड़े
    • Zig में फिलहाल async भाषा स्तर से हटा दिया गया है, और OP ने खुद user space में task switching implement किया है
    • जब मैंने simple coroutine ping-pong test किया था, तो दूसरी solutions की तुलना में यक़ीन करना मुश्किल ऐसे numbers मिले थे
    • Zig में जल्द नया async जोड़ा जाएगा, इसलिए गहराई से उतरने से पहले इंतज़ार कर रहा हूँ
      संबंधित लेख: Zig new async I/O
  • Stackful coroutine तब मायने रखते हैं जब RAM पर्याप्त हो
    मैं Zig को embedded (ARM Cortex-M4, 256KB RAM) environment में इस्तेमाल कर रहा हूँ, और C के साथ interop में memory safety सुनिश्चित करने के लिए इसका उपयोग करता हूँ
    मुझे Rust जैसा colored async ज़्यादा पसंद है। synchronous code जैसा दिखने वाला जादुई एहसास अच्छा लगता है, लेकिन बड़े codebase में यह पहचानना मुश्किल हो जाता है कि कौन-सा function blocking है
    • दरअसल हर synchronous code software द्वारा बनाई गई एक illusion है
      CPU वास्तव में I/O पर block नहीं होता, और OS thread खुद OS द्वारा implement किया गया stackful coroutine है
      भाषा स्तर पर इस illusion को अधिक कुशलता से implement किया जा सकता है, लेकिन मूल रूप से बात वही है
    • नया Zig IO, Rust से भी अधिक परिष्कृत तरीके से colored structure होने वाला है
      function I/O करता है या नहीं, उसी आधार पर उसका color तय होगा, और call site पर async होने या न होने को स्पष्ट किया जाएगा
      Zig function call के समय आवश्यक stack size की गणना करने की क्षमता भी लक्ष्य बना रहा है, इसलिए stackful coroutine की RAM बर्बादी की समस्या कम होने की उम्मीद है
    • इसलिए Zig I/O को explicit रूप से व्यक्त करना चाहता है, ताकि यह track किया जा सके कि कौन-सा function blocking है
  • कुछ लोगों की राय है कि अभी Zig अपनाना जल्दबाज़ी होगी। I/O model में बड़े बदलाव चल रहे हैं, इसलिए लगता है इसमें कुछ साल लगेंगे
    • मैं भी 2020 में इसी तरह की वजह से Zig छोड़ चुका था।
      लेकिन project अभी भी सक्रिय है, और तेज़ रिलीज़ से ज़्यादा सही design को प्राथमिकता देना मुझे सकारात्मक लगता है
      अभी मैं Go या C इस्तेमाल कर रहा हूँ और 1.0 का इंतज़ार कर रहा हूँ
    • कुछ साल बहुत जल्दी निकल जाते हैं। Zig पहले से ही काफ़ी उपयोगी भाषा है। जिसे इस्तेमाल करना है वह करेगा, जिसे नहीं करना वह नहीं करेगा
    • वास्तव में अभी समय ख़राब है। 0.16 में बड़े I/O बदलाव आने वाले हैं, और लेखक खुद भी अभी latest features का उपयोग नहीं कर रहा
      मैं भी I/O-केंद्रित काम के लिए 0.16 का इंतज़ार करूँगा
    • लेकिन अगर काम I/O-संबंधित है, तो Zig 0.15 का buffered reader/writer interface इस्तेमाल करने पर शायद कोई बड़ा बदलाव नहीं होगा
    • उल्टा, मुझे लगता है अभी कहना ग़लत है। Zig भाषा खुद तेज़ी से नहीं बदल रही, बल्कि नया शक्तिशाली std.Io API जोड़ा जा रहा है
      मौजूदा code वैसे ही काम करता रहेगा, और नया API अधिक ergonomic और performant है
      मैंने भी अपना मौजूदा project नए Reader/Writer API पर migrate किया, और code काफ़ी साफ़ हो गया
  • callback-आधारित async standard क्यों बन गया, यह अब भी सवाल है
    libtask जैसा approach कहीं ज़्यादा साफ़ लगता है
    Rust ने भी callback-आधारित async अपनाया, लेकिन वजह समझ नहीं आती
    संदर्भ: libtask
    • stackless coroutine भाषा के भीतर implement किए जा सकते हैं, और मौजूदा features के साथ उनकी predictable interaction एक फ़ायदा है
      लेकिन stack को सीधे संभालने पर exception handling, GC, debugger आदि से टकराव हो सकता है
      LLVM स्तर पर ऐसे बदलाव merge करना भी कठिन है, इसलिए भाषा डिज़ाइनर के नज़रिए से व्यावहारिक सीमाएँ बहुत हैं
    • C++ standard के लिए Microsoft द्वारा किए गए शोध में निष्कर्ष निकला कि stackless coroutine में memory overhead बहुत कम होता है, और executor design की स्वतंत्रता अधिक होती है
    • zio या libtask style की कमी यह है कि stack size का खुद अनुमान लगाना पड़ता है
      बहुत छोटा हो तो overflow, बहुत बड़ा हो तो memory waste
      platform के अनुसार ज़रूरी stack size अलग होता है, इसलिए portability की समस्या भी होती है
      Zig issue #157 हल हो जाए तो यह approach बेहतर हो सकता है
    • libtask जैसे मामले में thread stack size अस्पष्ट होता है, और सामान्य async state से काफ़ी बड़ा होता है
    • Rust का async callback नहीं बल्कि polling आधारित है
      यानी async लागू करने के तीन तरीके हैं
      1. callback-आधारित (Node.js, Swift)
      2. stackful-आधारित (Go, libtask)
      3. polling-आधारित (Rust)
        Rust static state machine में बदल जाता है और runtime उसे poll करता है
        stackful approach में memory waste ज़्यादा होती है, और stack size manage करना कठिन होता है
        Rust इससे बचने के लिए stackless structure अपनाता है, और Zig भविष्य में दोनों विकल्प चुनने देगा
        संदर्भ: zio coroutine कोड
  • TCP read एक महीने तक भी block हो सकता है, तो I/O timeout interface कैसा होगा, यह जानने की उत्सुकता है
    • TCP socket में setsockopt से read/write timeout सेट किया जा सकता है
      Zig POSIX API layer देता है
      संदर्भ: setsockopt दस्तावेज़
    • अभी Zig का std.Io.Reader timeout को नहीं समझता
      Python के asyncio.timeout जैसा व्यवहार करने वाली संरचना पर विचार चल रहा है
      उदाहरण code:
      var timeout: zio.Timeout = .init;
      defer timeout.cancel(rt);
      timeout.set(rt, 10);
      const n = try reader.interface.readVec(&data);
      
    • ज़्यादातर async framework timeout और cancellation को नज़रअंदाज़ करते हैं
      जबकि असल में वही सबसे कठिन हिस्सा है
  • Scala में पहले से ही ZIO नाम की concurrency library है
    संदर्भ: zio.dev
  • हाल में Rust के Tokio से प्रभावित हुआ हूँ, और अगर Zig में भी Go-style concurrency बिना GC के implement की जा सके, तो मैं ज़रूर आज़माना चाहूँगा
    • Go, GC की वजह से अनंत तक बढ़ने वाली stack जैसे tricks इस्तेमाल कर सकता है
      लेकिन Zig, low-level language होने के बावजूद high-level API को साफ़-सुथरे ढंग से व्यक्त कर सकता है, यह मुझे प्रभावशाली लगा
  • मुझे पहली बार Zig के बारे में Bun वेबसाइट से पता चला था। आजकल यह वाकई बहुत तेज़ी से आगे बढ़ रहा है
  • पुराने C++ version में मैंने Qt से asynchronous I/O implement किया था, लेकिन इस बार Go पर स्विच किया
    Zig और Go, दोनों के लिए नए Qt bindings आए हैं
    • Go: miqt
    • Zig: libqt6zig
      मुझे Rust के लिए bindings चाहिए। cxx-qt ही एकमात्र maintained project है, लेकिन मैं QML या CMake इस्तेमाल नहीं करना चाहता। मैं केवल Rust + Cargo के साथ Qt इस्तेमाल करना चाहता हूँ
  • Scala में पहले से मशहूर framework ZIO है, इसलिए नाम रखना सच में मुश्किल लगता है