10 पॉइंट द्वारा GN⁺ 2025-10-16 | 2 टिप्पणियां | WhatsApp पर शेयर करें
  • SQLite को performance, compatibility, कम dependencies और stability की वजह से शुरुआत (2000) से ही C भाषा में विकसित किया गया
  • C लगभग हर OS और language में इस्तेमाल की जा सकती है, और खासकर low-level library के रूप में तेज़ execution को support करती है
  • object-oriented languages की बजाय C चुनने का कारण extensibility, अलग-अलग languages से call किए जाने की सुविधा, और development के समय C++ और Java की अपरिपक्वता था
  • SQLite की लगभग dependency-free single-file structure है, और यह C standard library के केवल न्यूनतम functions का इस्तेमाल करती है
  • Rust और Go जैसी "safe languages" में rewrite करने पर चर्चा होती रही है, लेकिन quality control, performance, और library callability जैसे पहलुओं में अब भी C आगे है

1. C सबसे अच्छा विकल्प क्यों है

  • SQLite को 29 मई 2000 को पहली बार विकसित किए जाने के बाद से अब तक C भाषा में ही बनाए रखा गया है
    • फिलहाल इसे किसी दूसरी language में rewrite करने की कोई योजना नहीं है
  • C में hardware के क़रीब नियंत्रण मिलता है और साथ ही portability भी बहुत अच्छी है, इसलिए इसे “portable assembly language” कहा जाता है
  • दूसरी languages यह दावा कर सकती हैं कि वे “C जितनी तेज़” हैं, लेकिन C से तेज़ होने का दावा कोई language नहीं करती

1.1. Performance

  • SQLite जैसी low-level library को बार-बार call किया जाता है, इसलिए इसका बहुत तेज़ चलना ज़रूरी है
  • C भाषा तेज़ code लिखने के लिए उपयुक्त है, और portability के साथ hardware तक क़रीबी access भी देती है
  • दूसरी modern languages भी ‘C जितनी तेज़’ होने का दावा करती हैं, लेकिन general-purpose programming में C से तेज़ होने को लेकर कोई language पूरी तरह आश्वस्त नहीं है
  • C memory और CPU resources पर बारीक नियंत्रण देती है, इसलिए कभी-कभी यह file system से 35% तेज़ performance भी दिखाती है

1.2. Compatibility

  • लगभग हर system C में लिखी गई libraries को call कर सकता है
  • उदाहरण के लिए, Android (Java-आधारित) में भी adaptor के ज़रिए SQLite का उपयोग किया जा सकता है
  • अगर SQLite को Java में लिखा गया होता, तो iPhone (Objective-C, Swift) पर उसका उपयोग संभव नहीं होता और उसकी सार्वभौमिक उपयोगिता काफ़ी घट जाती

1.3. कम dependencies

  • C library के रूप में विकसित होने के कारण इसकी runtime dependencies बहुत कम हैं
  • न्यूनतम configuration में यह standard C library के केवल बहुत बुनियादी functions (memcmp(), memcpy(), memmove(), memset(), strcmp(), strlen(), strncmp()) का ही उपयोग करती है
  • ज़्यादा पूर्ण build में भी malloc(), free(), file I/O जैसी कुछ ही dependencies होती हैं
  • modern languages में अक्सर कई बड़े runtimes और हज़ारों interfaces की आवश्यकता होती है

1.4. Stability

  • C एक पुरानी और कम बदलने वाली, कुछ हद तक नीरस language है, लेकिन यही बात predictability और stability भी देती है
  • SQLite जैसे छोटे, तेज़ और भरोसेमंद database engine के लिए ऐसी language उपयुक्त है जिसकी specification बार-बार न बदले
  • अगर language की spec या implementation बार-बार बदलती रहे, तो वह SQLite की stability के लिए ठीक नहीं है

2. इसे object-oriented language में क्यों नहीं लिखा गया

  • कुछ developers मानते हैं कि object-oriented approach के बिना SQLite जैसे complex system को implement करना मुश्किल है, लेकिन C की तुलना में C++ या Java में library बनाने पर उसे दूसरी languages से call करना कठिन हो जाता है
  • Haskell, Java जैसी कई languages के support के लिए C library चुनना उचित था
  • object-oriented एक language नहीं, बल्कि design pattern है, इसलिए यह किसी एक language तक सीमित नहीं है
    • C में भी structs और function pointers से object-oriented patterns लागू किए जा सकते हैं
  • object-oriented हमेशा सबसे अच्छा structure नहीं होता; कई बार procedural code ज़्यादा स्पष्ट, maintain करने में आसान और तेज़ परिणाम देने वाला होता है
  • SQLite development के शुरुआती दौर (लगभग 2000) में
    • Java अपरिपक्व था
    • C++ में compilers के बीच compatibility की गंभीर समस्या थी
      → उस समय C सबसे व्यावहारिक और सुरक्षित विकल्प था
  • आज भी SQLite को rewrite करने लायक़ लाभ पर्याप्त नहीं दिखता

3. इसे "safe language" में क्यों नहीं लिखा गया

  • हाल के वर्षों में Rust, Go जैसी safe programming languages में रुचि बढ़ी है, लेकिन SQLite जब पहली बार विकसित हुई थी (पहले 10 वर्षों तक), तब ये मौजूद ही नहीं थीं
  • Go या Rust में दोबारा लिखने पर bugs बढ़ सकते हैं, या performance घट सकती है
  • ये languages memory checks जैसी अतिरिक्त branch code insert करती हैं, जबकि SQLite की quality strategy में 100% branch coverage बहुत महत्वपूर्ण है और यह पहलू अभी संतोषजनक नहीं है
  • safe languages आमतौर पर out-of-memory स्थिति में program को terminate कर देती हैं, लेकिन SQLite को memory की कमी की स्थिति से भी recover करने के लिए design किया गया है
  • Rust, Go आदि अब भी अपेाकृत नई languages हैं और इनमें लगातार development की आवश्यकता है
  • इसलिए SQLite development team safe languages की प्रगति का समर्थन करती है, लेकिन SQLite implementation में अब भी सिद्ध C की स्थिरता को प्राथमिकता देती है

इसके बावजूद, भविष्य में कभी Rust में rewrite होने की संभावना हो सकती है। Go में assert() को पसंद नहीं किया जाता, इसलिए Go में लिखे जाने की संभावना कम है

  • लेकिन Rust में लिखे जाने के लिए कुछ शर्तें होंगी:
    • Rust और अधिक mature हो, और उसका बदलाव चक्र धीमा होकर वह “पुरानी और नीरस language” बन जाए
    • यह साबित होना चाहिए कि उससे कई languages से call की जा सकने वाली सार्वभौमिक library बनाई जा सकती है
    • embedded जैसे OS-विहीन devices पर चल सकने वाला object code तैयार किया जा सके
    • compiled binary के लिए 100% branch coverage test tools उपलब्ध हों
    • OOM (memory shortage) errors से recovery संभव हो
    • SQLite में C जो कुछ भी करती है, वह सब Rust बिना performance loss के कर सके
  • अगर कोई Rust enthusiast (rustacean) मानता है कि ऊपर की शर्तें पहले से पूरी हो चुकी हैं और SQLite को Rust में फिर से लिखना चाहिए, तो उसे SQLite developers से सीधे संपर्क कर अपनी राय रखने की सलाह दी जाती है

2 टिप्पणियां

 
GN⁺ 2025-10-16
Hacker News राय
  • सुरक्षित प्रोग्रामिंग भाषाएँ अपने शुरुआती 10 वर्षों में मौजूद नहीं थीं, फिर भी मेरा मानना है कि अगर SQLite को Go या Rust में फिर से इम्प्लीमेंट किया जाए, तो संभव है कि जितने बग ठीक हों उससे ज़्यादा नए बग बन जाएँ, और यह धीमा भी हो सकता है। अगर पहले ही बहुत समय और टेस्टिंग के बाद लगभग बग-रहित कोड तैयार हो चुका है, तो कम बदलाव-दर वाली स्थिति में यह किस भाषा में लिखा है, इससे बहुत फ़र्क नहीं पड़ता। यहाँ तक कि assembly में हो, तब भी फ़र्क न पड़ने जैसा है
    • “बदलाव-दर कम हो तो समस्याएँ कम होती हैं” यह बात Google Security Blog में भी समझाई गई है। यहाँ तर्क यह है कि memory safety से जुड़ी ज़्यादातर समस्याएँ नए कोड में होती हैं, और समय के साथ कोड अधिक सुरक्षित होता जाता है संबंधित लिंक
    • Rust पक्ष में Turso जैसे प्रोजेक्ट काफ़ी सक्रिय हैं Turso
    • कुछ लोग यह भी कहते हैं कि Linux की बुनियादी utilities को Rust में फिर से नहीं लिखना चाहिए। उनका मानना है कि दशकों से इस्तेमाल हो रहे और जिनके अधिकांश बग पहले ही हटाए जा चुके हैं, ऐसे software को बेवजह फिर से लिखने की ज़रूरत नहीं है
    • मुझे लगता है कि Zig कुछ C कोड के विकल्प के रूप में अच्छा है। यह Python और मौजूदा C binaries के साथ भी अच्छी तरह काम करता है। Go की philosophy अच्छी है, लेकिन optimization कठिन है और इसके लिए बहुत सक्षम developers चाहिए होते हैं। Rust भी इस्तेमाल किया जा सकता है, लेकिन मौजूदा C को बनाए रखते हुए Zig को धीरे-धीरे अपनाना कहीं आसान था। हम C कोड से बग पूरी तरह हटा नहीं पाए, लेकिन Rust में जाना व्यावहारिक रूप से कठिन लगा
    • SQLite का एक implementation पहले से Go में port किया जा चुका है cznic/sqlite
  • मेरा मानना है कि SQLite के शुरुआती विकास के समय C सबसे अच्छा विकल्प क्यों था, या उसके मौजूदा फ़ायदों से अलग, SQLite को किसी दूसरी भाषा में फिर से लिखने की कोई खास वजह नहीं है। हल्का SQL database implement करना कोई भी कर सकता है, इसलिए Rust, C++, Go, Lisp जैसी किसी भी पसंदीदा भाषा में नई implementation बनाई जा सकती है। जो मौजूदा implementation C में अच्छी तरह काम कर रही है, उसे बेकार में छोड़कर 25 साल से ज़्यादा समय से SQLite को C में बनाए रखने वाले developers को ज़बरदस्ती नई भाषा सीखकर सब कुछ शुरू से बनाने को कहने की ज़रूरत नहीं है
    • कई language fandoms में दूसरों पर अपनी पसंद थोपने की प्रवृत्ति होती है, और language adoption कभी-कभी zero-sum लड़ाई जैसा बन जाता है। अगर कोई project किसी खास भाषा में विकसित हो रहा हो, तो केवल उस भाषा का इस्तेमाल न करना भी दूसरी भाषा की ज़रूरत पर सवाल उठाने जैसा समझ लिया जाता है। जबकि वास्तव में विकल्प बहुत अधिक हैं, और अगर दोबारा लिखा भी जाए तो Rust, Go, D, Lisp, Julia जैसी कई भाषाएँ सामने आती हैं
    • वास्तव में SQLite developers Rust में rewrite के लिए खुले हैं। अगर Rust ज़रूरी पूर्वशर्तें पूरी करे, तो दोबारा बनाने की संभावना भी है। Rust के समर्थकों को SQLite developers से सीधे संपर्क करने की सलाह भी दी गई है
    • rqlite और turso जैसे प्रोजेक्ट पहले से Rust में इम्प्लीमेंट किए जा चुके हैं
    • Go में लिखा एक adapter मौजूद है, जिससे golang में cgo के बिना sqlite इस्तेमाल किया जा सकता है। अब sqlite सिर्फ़ एक C library नहीं, बल्कि एक database file format भी है। आगे चलकर pure Rust implementation आ सकती है, और कभी वह मुख्य implementation भी बन सकती है
    • आजकल 5 साल से पुरानी तकनीक को पुराना कहकर नज़रअंदाज़ करने का चलन निराशाजनक लगता है। लंबे समय तक तराशी गई तकनीकों के प्रति अधिक सम्मान होना चाहिए
  • सुरक्षित भाषाएँ array access के समय boundary check के लिए अतिरिक्त branch बनाती हैं, लेकिन सही कोड में वे branch वास्तव में चलती नहीं हैं। यानी 100% branch testing कठिन हो जाती है, और यह SQLite की quality strategy से जुड़ा हुआ बिंदु है। यह नया तर्क सुनना दिलचस्प लगा
    • अगर पूरा भरोसा है कि वह code branch कभी चलेगी ही नहीं, तो क्या सच में उसे test करने की ज़रूरत है? 100% test coverage के लिए safety की क़ुर्बानी देने जैसा लगता है
    • सुरक्षित भाषाओं में compiler अपने-आप if (i >= array_length) panic("index out of bounds") जैसे रक्षा-कोड जोड़ देता है, और उस कोड की खुद Rust compiler ने अच्छी तरह टेस्टिंग की होती है, इसलिए उसकी चिंता नहीं होनी चाहिए। मैं यह तर्क सही समझ रहा हूँ या नहीं, यही जानना चाहता हूँ
    • Dr Hipp जैसे विशेषज्ञ, और sqlite जैसे project के मामले में, इस तरह के तर्क में कुछ दम लगता है
    • Rust में get_unchecked() जैसी विधि का उपयोग करके bounds check के बिना access भी किया जा सकता है, जिससे safety बनाए रखते हुए performance बढ़ाई जा सकती है get_unchecked दस्तावेज़
    • क्या यह समस्या इस तरह कम की जा सकती है कि जो branch conditionally panic में जाती है, उसे coverage के लिए अनिवार्य न माना जाए?
  • SQLite ने भविष्य में कभी Rust में फिर से लिखे जाने की संभावना खुली रखी है, जबकि Go में assert() से जुड़ी पाबंदियों के कारण संभावना कम है। Rust में जाने के लिए इन पूर्वशर्तों की ज़रूरत मानी गई है: Rust को और लंबे समय तक स्थिर और कम-परिवर्तनशील होना चाहिए, वह general-purpose libraries लिखने के लिए उपयुक्त होना चाहिए, बिना OS वाले embedded सिस्टम पर चलना चाहिए, 100% branch coverage tooling होनी चाहिए, OOM error handling mechanism होना चाहिए, और performance घटे बिना C की भूमिका को बदलना चाहिए
    • Rust 1.0 के बाद से 10 साल से अधिक समय तक compatibility बनाए रखते हुए बदलता आया है। कुछ लोग चाहते हैं कि बदलाव पूरी तरह रुक जाए, जबकि कुछ को बदलाव स्वीकार हैं। general-purpose library development पहले ही साबित हो चुका है, और बिना OS वाले embedded support भी स्पष्ट रूप से संभव है। branch coverage के बारे में मैं विशेषज्ञ नहीं हूँ, लेकिन Ferrocene आदि में इस दिशा में काम चल रहा है। Rust भाषा स्वयं memory allocation नहीं करती, इसलिए OOM handling standard library स्तर पर तय की जा सकती है। performance का प्रश्न इस पर निर्भर करता है कि उसे कैसे परिभाषित किया जा रहा है
    • क्या Go में भी if condition { panic(err) } को assert function की तरह इस्तेमाल नहीं किया जा सकता?
  • ज़्यादातर दावे शुरू में ठीक लगते हैं, लेकिन ध्यान से देखने पर पूरी तरह ठोस नहीं लगते। मेरा मानना है कि अगर बस यह स्पष्ट कर दिया जाए कि 2000 के आसपास C क्यों चुनी गई थी, तो आज के समय में अच्छी तरह तराशे गए codebase को स्वीकार कर लेना चाहिए। बाकी सहायक तर्कों के कुछ हिस्सों का खंडन किया जा सकता है
    • खास तौर पर कौन-से तर्क खंडित किए जा सकते हैं, यह सुनना चाहूँगा
    • दिए गए तर्क पुराने codebase को बनाए रखने के लिए तो काम आ सकते हैं, लेकिन अगर नए developers को अधिक जटिल भाषाओं के बजाय C अपनाने के लिए प्रेरित करना है, तो और मज़बूत कारण चाहिए होंगे
    • (वह दस्तावेज़ 2017 में लिखा गया था)
    • संभवतः यह उन अनेक “इसे X में फिर से क्यों नहीं लिखते?” सवालों के जवाब में एक विस्तारपूर्ण और लंबा दस्तावेज़ था
  • SQLite को automation के ज़रिए Go में ले जाने वाले प्रोजेक्ट कई सालों से सक्रिय रूप से वितरित हो रहे हैं modernc.org/sqlite। वही test suite भी अच्छी तरह पास हो जाता है। हालाँकि Go संस्करण काफ़ी धीमा है, लेकिन कई बार raw speed से ज़्यादा Go native port की सुविधा मायने रखती है। निष्कर्षतः, SQLite को Go, Rust, Zig, Nim, Swift आदि में फिर से लिखने की बजाय C से automatic translation करना अधिक व्यावहारिक लगता है
    • सार्वजनिक test suite पास हो जाता है, लेकिन सुना है कि SQLite के पास इससे कहीं अधिक कठोर internal test suites भी हैं
    • test suite पास होना = बग न होना नहीं है; नए edge cases या performance समस्याएँ फिर भी बची रह सकती हैं
  • “SQLite को C में क्यों विकसित किया गया?” यह आधिकारिक दस्तावेज़ में अच्छी तरह समझाया गया है, लेकिन “Rust क्यों नहीं?” जैसा सवाल सुनते ही पहले दिमाग में “आख़िर Rust ही क्यों होना चाहिए?” आता है
    • एक राय यह है कि ऐसा उस चढ़ाए गए शीर्षक की वजह से हो रहा है
    • ऐसे Rust rewrite projects पहले से मौजूद हैं: tursodatabase/turso और ब्लॉग पोस्ट में Why पर चर्चा भी की गई थी
    • लहजा कुछ ऐसा है जैसे पूछा जाए कि SQLite को BASIC में नहीं, C में क्यों लिखा गया
  • कोड लिखने, software इस्तेमाल करने, और rewrite पर लेख पढ़ने के साथ एक बड़ी समस्या बार-बार दिखती है: अगर rewrite का लक्ष्य सिर्फ़ “functional equivalence” हो, तो समय के साथ जुड़ी अनगिनत exception handlings और patches आसानी से छूट जाते हैं। नतीजा यह होता है कि software फिर टूटने लगता है, या जो चीज़ें पहले ठीक चलती थीं वे खराब हो जाती हैं। इस तरह के rewrite में पर्याप्त ज़ोर और सावधानी की ज़रूरत है, और 100% पुनर्स्थापना कठिन लगती है। SDL जैसी अहम libraries के मामले में भी यही बात लागू होती है। बार-बार खराब releases और user complaints की आशंका रहती है। मेरा मानना है कि Rust के मुख्यधारा में आने के बाद भी C लंबे समय तक जीवित रहेगा। rewrite कोई default विकल्प नहीं होना चाहिए
  • यह ज़्यादा दिलचस्प लगता है कि DuckDB Rust की बजाय C++ में लिखा गया है। DuckDB 2019 का अपेक्षाकृत नया project है, इसलिए वह Rust अपना सकता था, फिर भी उसने C++ चुना। DuckDB नया है, और उसका codebase SQLite से काफ़ी छोटा भी है
    • सुना है कि DuckDB टीम को C++ पर भरोसा था और compiler की autovectorization क्षमता पर भी, इसलिए उन्होंने वही चुना। उस समय (2019) Rust में स्पष्ट high-level SIMD support नहीं था। वे hand-rolled SIMD code maintain नहीं करना चाहते थे
    • अगर लक्ष्य अधिकतम performance हो, तो लगता है कि C++ कम code में अधिक तेज़ binaries दे सकता है। आधुनिक C++ में compile-time safety भी काफ़ी है, इसलिए DB जैसे code के लिए वह उपयुक्त हो सकता है
    • अगर modern C++ में लिखा जाए, तो यह ठीक लगता है
  • SQLite rewrite पर पहले भी कई बहसें हो चुकी हैं 2021, 2018
    • tptacek की टिप्पणी दिलचस्प है: पुराने दस्तावेज़ में security पर एक अनुच्छेद था, लेकिन नए दस्तावेज़ में वह हटा दिया गया। C, SQLite के लिए भी स्पष्ट security vulnerability है। पुराने संस्करण में यह स्पष्टीकरण था कि ‘SQLite कोई बहुत security-sensitive library नहीं है’। तर्क यह था कि untrusted SQL चलाना अपने-आप में बड़ा मुद्दा है, और बाहरी files import करने के मामले में defensive code और मज़बूत testing से समस्याएँ रोकी जाती हैं, साथ ही pre-validation routines भी मौजूद हैं 2021 web archive दस्तावेज़
 
aer0700 2025-10-16

SQLite के लिए भी C एक सुरक्षा जोखिम है — यह बात क्या तब भी लागू होती है, जब टेस्टिंग बहुत अच्छी तरह की गई हो और डेवलपर काफ़ी अनुभवी हों? समस्या logic और development process में हो सकती है, लेकिन भाषा खुद ही security vulnerability है — यह समझना मेरे लिए मुश्किल है। दरअसल, शायद ही कोई ऐसा प्रोग्राम हो जो C में लिखे गए infrastructure पर निर्भर न करता हो।