- zig build के अंदरूनी हिस्से अब configurer और maker प्रोसेस में बंट गए हैं, और
build.zig द्वारा बनाया गया build graph एक binary configuration file के रूप में serialize किया जाता है
- parent process configuration file को cache करता है और maker को Release mode में asynchronous compile करता है, जबकि maker हर Zig version के लिए global cache में केवल एक बार compile होता है
- यूज़र के
build.zig में बदलाव होने पर अब पूरा build system साथ में compile नहीं करना पड़ता, जिससे --watch, --fuzz, --webui जैसे फीचर जोड़ने की time cost कम होती है
zig build --help का औसत execution time 150ms से 14.3ms तक घट गया है, और CPU cycles, instruction count, cache references भी 94~96% तक कम हुए हैं
- ज़्यादातर API compatible हैं, लेकिन
b.args को सीधे observe करना अब addPassthruArgs() से बदला जाएगा, और Zig 0.17.0 कुछ हफ्तों में आने वाला है
बिल्ड सिस्टम आर्किटेक्चर में बदलाव
- बड़ी branch merge होने के साथ
zig build के अंदरूनी हिस्से configurer process और maker process में विभाजित हो गए हैं
- पुराने ढांचे में
build.zig फ़ाइल और build system का पूरा implementation एक बड़े Debug mode process के रूप में compile होता था, और build.zig memory में build graph बनाकर उसे “build runner” से चलाता था
- नए ढांचे में
build.zig एक छोटे Debug mode configurer process के रूप में compile होता है, और build graph को binary configuration file के रूप में serialize किया जाता है
- parent
zig build process configuration file को पहचानकर अगली run के लिए cache करता है, और build graph execute करने वाले maker को Release mode में asynchronous compile करता है
- configuration file और maker compile तैयार होने के बाद maker उस configuration file को लेकर execute होता है, और global cache की वजह से maker को हर
zig version पर सिर्फ एक बार compile करना होता है
स्पीड सुधार का असर
- मुख्य लक्ष्य
zig build की speed improve करना है, और यूज़र के build.zig में बदलाव होने पर अब पूरा build system साथ में compile नहीं होता
--watch, --fuzz, --webui के आने के बाद build system की functionality बढ़ने पर भी zig build का समय साथ में न बढ़े, इस लिहाज़ से यह बदलाव महत्वपूर्ण है
- अगर सिस्टम तय करे कि कोई बदलाव नहीं है, तो
build.zig logic को फिर से चलाए बिना पुरानी configuration reuse की जा सकती है
- उदाहरण के लिए,
zig build command line में -freference-trace जोड़ने पर भी build.zig logic को बेवजह दोबारा run नहीं किया जाता
- क्योंकि असली build graph execute करने वाला process optimization enabled state में compile होता है, इसलिए execution phase भी तेज़ हो जाता है
बेंचमार्क नतीजे
zig build --help का औसत execution time पुराने ढांचे के 150ms से घटकर नए ढांचे में 14.3ms हो गया
- wall-clock time
150ms से 14.3ms तक 90.4% कम हुआ, और CPU cycles 593M से 24.1M तक 95.9% कम हुए
- instruction count
995M से 43.7M तक 95.6% कम हुआ, और cache references 25.8M से 1.46M तक 94.3% कम हुए
- peak RSS
84.8MB से 78.5MB तक 7.4% कम हुआ
- सबसे बड़ा फर्क इस बदलाव से आया कि अब हर
zig build command पर build.zig logic चलाने के बजाय cached serialized configuration को reuse किया जाता है
टूल्स और compatibility पर असर
- ZLS जैसे third-party tools build runner को fork करके बनाए रखने के बजाय serialized configuration file को consume करके फायदा उठा सकते हैं
- internal mechanism में बड़े बदलाव हुए हैं, लेकिन API के नज़रिए से ज़्यादातर चीज़ें compatible बनी हुई हैं
- exceptions merged PR में संकलित बदलावों से संबंधित हैं
मुख्य breaking changes
- वह बदलाव जिससे कई users का सामना होने की संभावना है,
b.args को सीधे observe करने वाले pattern का हटना है
- पुराना code:
if (b.args) |args| {
run_cmd.addArgs(args);
}
run_cmd.addPassthruArgs();
- इस बदलाव के बाद build script अब उन arguments को observe नहीं कर पाएगी, यानी एक functionality हटा दी गई है
- बदले में, उन arguments को बदलने पर build script को source से फिर से build करने की ज़रूरत नहीं पड़ेगी
टेस्टिंग और रिलीज़ शेड्यूल
- जो users Zig की दिशा पर असर डालना चाहते हैं, वे अपने project को development version पर अपग्रेड करके इन नए बदलावों को आज़मा सकते हैं और feedback दे सकते हैं
- Zig
0.17.0 कुछ हफ्तों में रिलीज़ होने वाला है
- समय की कमी के कारण पहले से testing नहीं हो सकी, लेकिन अगर
0.17.0 में build टूट भी जाए, तब भी 0.17.1 tag में fixes शामिल होने का पर्याप्त मौका रहेगा
1 टिप्पणियां
Hacker News की राय
मैंने कुछ कोड को Zig 0.16.0 पर माइग्रेट करके देखा, और नतीजे काफ़ी संतोषजनक थे
जिन हिस्सों पर असर पड़ा वे काफ़ी ज़्यादा थे, लेकिन बदलाव अपने आप में अच्छे लगे और भाषा के भविष्य को उज्ज्वल बनाने वाली दिशा में दिखे
ख़ासकर नया इनपुट/आउटपुट मेकैनिज़्म single-thread, multi-thread, और event loop implementation—तीनों में साफ़-सुथरे ढंग से efficient code संभव बनाता है
अगर आपने 0.16.0 के बाद अभी तक Zig नहीं आज़माया है, तो ज़रूर देखें। इस बार के release notes बहुत लंबे थे
https://ziglang.org/download/0.16.0/release-notes.html
जहाँ तक मुझे पता है, यह पहले से धीमा है
उम्मीद है कि अगली releases में उस समस्या को हल किया जाएगा जहाँ “dispatch target compile time पर पता है, लेकिन फिर भी dynamic है”, ताकि efficiency loss कम हो सके
मैंने मान लिया कि event loop आधारित IO implementation में
io.asyncकॉल करने पर अंदर ही अंदर किसी “task” जैसी चीज़ की शुरुआत होती है, और future उसका handle होता हैजो बात समझ नहीं आती, वह
future.await(io)कॉल करते समय है। क्या IO implementation किसी तरह current function को suspend करके future resolve होने पर फिर resume करता है? अगर हाँ, तो क्या इसका मतलब है कि Zig के सारे functions stackless coroutine हैं?.use_llvm = trueइस्तेमाल करना पड़ता हैकुछ महीनों तक Zig इस्तेमाल करने के बाद मुझे यक़ीन हो गया कि यह tools के लिए एक शानदार भाषा है
जब किसी idea को आज़ादी से जल्दी-जल्दी बनाकर देखना हो, तब इसे उठाना अच्छा लगता है, और जहाँ-जहाँ अटकते हैं वहाँ इसके निर्माताओं ने पहले से ही काफ़ी सोचे-समझे आरामदायक solutions रख छोड़े हैं
फिर भी यह आप पर भाषा को “सही” तरीके से इस्तेमाल करने का दबाव नहीं डालती
अब यह मेरे लिए “garage में tinkering” करने की default language बन गई है
मेरे लिए यह productivity का काफ़ी बड़ा मुद्दा है
मेरी “garage में tinkering” वाली default language Python है। हल्का syntax, बिना दखल के इस्तेमाल का अनुभव, समृद्ध standard library, और जो नहीं है उसके लिए packages मौजूद हैं
Zig का फ़ायदा क्या है?
Andrew Kelley का interview वीडियो देखकर मेरा मन Zig सीखने का हुआ: https://www.youtube.com/watch?v=iqddnwKF8HQ
Andrew के जवाब ठीक थे, लेकिन पूरा माहौल बहुत चापलूसी भरा लगा
मैं Zig इस्तेमाल करना चाहता था, लेकिन भाषा अभी भी बहुत तेज़ी से बदल रही है
हर release में API टूट जाती हैं, इसलिए भाषा सीखना, build system debug करना, और जो चीज़ें सच में बनानी हैं उन्हें implement करना—इन सबके साथ कदम मिलाना मुश्किल था
JetBrains interview देखकर फिर से कोशिश करने का मन तो है, लेकिन शायद मैं 1.0 आने तक इंतज़ार करूँगा
मैं बहुत पहले से एक ऐसे विचार के बारे में सोचता आया हूँ जिसे मैं dual programming कहता हूँ
इसका मतलब है stack को ठीक दो भाषाओं से बनाना: एक high-level भाषा और एक low-level भाषा
जितना संभव हो उतना high-level भाषा में लिखो, और ज़रूरत पड़ने पर ही low-level भाषा में नीचे उतरो
समस्या यह है कि अगर low-level भाषा पहले से बहुत अच्छी तरह न आती हो, तो low-level काम करने से पहले फिर से उस भाषा में हाथ जमाना पड़ सकता है
इसी वजह से C++ या Rust, C की तुलना में लिखने में कठिन हो जाते हैं, और मेरे लिए C default choice बनती है। लेकिन C की अपनी अच्छी तरह जानी-पहचानी समस्याएँ हैं
Zig शायद उस सही संतुलन को भर सके, क्योंकि यह इतना सरल लगता है कि लंबे अंतराल के बाद भी आसानी से वापस पकड़ा जा सके, और साथ ही इसमें programming को आसान बनाने वाले modern tools भी हैं
जितना संभव हो उतना low-level भाषा में करो, और केवल तब high-level भाषा में जाओ जब उसकी सुविधा उसकी लागत के लायक हो
Roc इसे संभव बनाता है। हर program के पास low-level भाषा में लिखा हुआ एक platform होता है, और Roc program उसी platform द्वारा expose की गई APIs का इस्तेमाल करता है
https://www.roc-lang.org/
बेशक high-level और low-level के बीच संतुलन कैसे रखना है, यह हर किसी की अपनी पसंद है
models Cython में implement किए जाते हैं, और user-facing API Python में दी जाती है
मैं अभी हर चीज़ Rust में कर रहा हूँ, और ख़ासकर OCaml-जैसे type system की वजह से, अब तक मुझे ऐसा कुछ नहीं मिला जो मैं इसमें न कर सकूँ
Lua को embedded language के तौर पर बनाया गया था, इसलिए यह interoperability के लिए अच्छा है, और साथ ही इतना high-level भी है कि इस्तेमाल करना आसान रहे
Factorio scripting language के रूप में Lua इस्तेमाल करता है, इसके पीछे वजह है
Zig development में मुझे जो बात पसंद है, वह यह है कि भाषा में features जोड़ने से ज़्यादा यह tools और developer feedback loop पर हैरान कर देने जितनी मेहनत करता है
कोई नई भाषा कुछ समय तक एक feature की कमी के बावजूद चल सकती है
लेकिन अगर compilation, linking, और dependency updates हर बार धीमे लगें, तो उसके टिके रहने की संभावना बहुत कम हो जाती है
development cycle को seconds नहीं बल्कि milliseconds के स्तर तक लाने पर यह फोकस लंबे समय में अच्छा दांव लगता है
यह देखकर हैरानी हुई कि “कुछ हफ़्तों में 0.17.0 release करने की योजना है”
क्या 0.16 को एक साल से ज़्यादा नहीं लगा था?
इतनी जल्दी 0.17 release की उम्मीद नहीं थी, इसलिए आज यह जानकर बहुत अच्छा लगा
यह अच्छी खबर लगती है। Zig का compile time पहले से ही शानदार है, और इस बदलाव से यह और बेहतर होगा ऐसा लगता है
यह निश्चित रूप से एक महत्वपूर्ण लक्ष्य है, और इसे हासिल करने के milestones भी स्पष्ट हैं, लेकिन व्यवहार में खाली project का पहला compile या
direnv allowके बाद ZLS के फिर से build होने पर होने वाले तकलीफ़देह इंतज़ार को “शानदार” कहना मुश्किल हैzig test file.zig -OReleaseSafeचलाऊँ, तो मेरे कंप्यूटर पर इसमें कुछ सेकंड लगते हैंfile को हर बार बदलने पर फिर उतना ही समय लगता है। मैं 0.16 या master इस्तेमाल कर रहा हूँ, इसलिए toolchain पुराना भी नहीं है, और environment Linux है
Zig भाषा खुद लिखने में वाकई बहुत अच्छी है, लेकिन compiler और standard library का development मेरी नज़र में पर्याप्त रूप से conservative नहीं है
hello world से शुरू करते समय शायद ये समस्याएँ न दिखें, लेकिन fuzz testing या benchmark करते समय आप optimized binary चलाना चाहते हैं
तब अपेक्षाकृत कम code compile करने में भी बहुत झुंझलाहट होती है
तुलना के लिए, मुझे लगता है कि भाषा के रूप में Zig, Rust/C++/C से काफ़ी बेहतर है, लेकिन Rust/C++/C में इस तरह की समस्या लगभग कभी नहीं आती। C/C++ में यह मानकर चल रहा हूँ कि clang/gcc/ninja वगैरह इस्तेमाल हो रहे हैं
उसी कंप्यूटर पर Ninja/Python/clang के साथ लगभग 10 हज़ार lines वाले C++ project को configure, build (-O2 या -O3), और test तक 200ms में किया जा सकता है
अगर Zig में Linux library stubs export करने का official mechanism आ जाए, तो वह वाकई बहुत अच्छा होगा
Zig की cross-compilation और मनचाहे glibc version को target करने की क्षमता बिल्कुल जादुई है
मैं इस जादू का इस्तेमाल एक अलग C++ build system में कर रहा हूँ, लेकिन Zig से उन library stubs को पाने के लिए workaround करना पड़ता है
अच्छा होगा अगर यह official output के रूप में उपलब्ध हो
आख़िर Node.js और TypeScript की जगह इसे इस्तेमाल करने का कारण क्या होगा?
अगर आपको performance की आख़िरी बूंद, memory layout और control की ज़रूरत नहीं है, तो Zig इस्तेमाल करने में नुकसान ज़्यादा हैं
CRUD, “enterprise” काम, या websites में Zig के फ़ायदे लगभग नहीं के बराबर हैं
compiled Zig program बिना dependencies के सिर्फ़ कुछ KB का हो सकता है
low-level language में लिखे array access को SIMD और parallelization से optimize किया जा सकता है, और वही काम JavaScript में करने की तुलना में यह कई orders of magnitude तेज़ हो सकता है
text processing, image manipulation, video processing, hashing आदि में फ़र्क बहुत बड़ा है
JavaScript का इस्तेमाल न करने के कारण तो practically अनगिनत हैं