2 पॉइंट द्वारा GN⁺ 2025-07-07 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Jake Gold ने 16-thread AMD 3700X पर Go + SQLite CGI program चलाकर देखा कि 1990s-स्टाइल CGI modern hardware पर कितना टिक सकता है
  • नतीजे बताते हैं कि साधारण hardware पर भी प्रति सेकंड 2400 से ज़्यादा, यानी एक दिन में 20 करोड़ से ज़्यादा requests process की जा सकती हैं
  • CGI हर request के लिए process शुरू, run और terminate करता है, इसलिए पहले इसका overhead बड़ा था; इसे घटाने के लिए PHP और FastCGI जैसे तरीके आए
  • Simon Willison ने 2020 में datasette-ripgrep में Rust-based ripgrep CLI को call करके search handle किया, जिससे web request के दौरान process execution से बचना चाहिए—इस पुराने विश्वास में बदलाव आया
  • Go और Rust जैसी तेज़ startup वाली languages और multi-CPU environments में CGI-style processing पहले की तुलना में ज़्यादा practical विकल्प हो सकता है, लेकिन यह आम तौर पर recommended तरीका नहीं है

Modern hardware पर CGI performance को फिर से देखना

  • Serving 200 million requests per day with a cgi-bin Jake Gold का लेख है, जिसमें उन्होंने Go + SQLite CGI program से 1990s-स्टाइल CGI की performance test की
  • Test environment 16-thread AMD 3700X based system था
  • मुख्य नतीजा यह है कि CGI के साथ भी साधारण hardware पर प्रति सेकंड 2400 से ज़्यादा, यानी एक दिन में 20 करोड़ से ज़्यादा requests handle की जा सकती हैं
  • CGI हर incoming request के लिए अलग process शुरू करता है, उसे run करता है और फिर terminate करता है
  • शुरुआती web community ने इस overhead से बचने के लिए code को memory में resident रखकर extra cost घटाने वाले PHP और FastCGI बनाए

CGI अब पहले जितना खराब क्यों नहीं हो सकता

  • पहले CGI की bottlenecks में से एक यह थी कि web scripts Perl, Python, Java जैसी languages में लिखी जाती थीं, जिन्हें बहुत तेज़ startup speed के लक्ष्य से design नहीं किया गया था
  • आज Go और Rust इस्तेमाल करने पर CGI-style request processing कहीं ज़्यादा effectively काम कर सकती है
  • Simon Willison ने 2020 में datasette-ripgrep बनाते समय Rust में लिखे ripgrep CLI tool को shell के ज़रिए call करके search चलाया और अच्छे results पाए
  • CGI program अलग process के रूप में चलता है, इसलिए यह कई CPUs इस्तेमाल करने वाली architecture के साथ भी अच्छी तरह fit हो सकता है
    • Modern servers में 384 CPU threads हो सकते हैं
    • छोटे VMs में भी 16 CPU हो सकते हैं
    • CPU और memory performance भी पहले की तुलना में बहुत तेज़ हो गई है
  • 1998-स्टाइल web application लिखने का तरीका भी Go और Rust के साथ एक दिलचस्प experiment बन सकता है, लेकिन यह ज़्यादातर services के लिए default choice नहीं है

1 टिप्पणियां

 
GN⁺ 2025-07-07
Hacker News रायें
  • Python जैसी चीज़ इस्तेमाल करें तब भी आजकल CGI काफ़ी तेज़ है
    अगर CGI स्क्रिप्ट शुरू होने में CPU के 400ms लगते हैं और सर्वर 64-core है, तो प्रति सेकंड 160 requests, यानी एक सर्वर पर रोज़ 1.4 करोड़ hits संभाले जा सकते हैं
    static assets को छोड़कर भी अगर कोई web service रोज़ कुछ मिलियन requests पर हांफ रही है, तो bottleneck CGI process शुरू होने का समय नहीं है
    पहले होता तो मैं इसे “Python standard library में लंबे समय से supported boring technology” कहता, लेकिन बचे हुए Python maintainers stability और backward compatibility को नुकसानदेह मानते दिखते हैं, और standard library से बहुत boring और stable modules हटाते आए हैं
    cgi module Python 3.13 में हटा दिया गया
    पिछले 25 वर्षों के ज़्यादातर समय में इसे रोज़ इस्तेमाल किया है, इसलिए prototyping के लिए अब भी Python इस्तेमाल करने की आदत है, लेकिन अब इसका अफ़सोस होता है और JS और Lua के बीच सोच रहा हूँ

    • cgi हटाने का आधार https://peps.python.org/pep-0594/#cgi में है
      दिलचस्प बात यह है कि वहाँ 14 जुलाई 2000, यानी 25 साल पहले के https://peps.python.org/pep-0206/ को link किया गया है, जिसमें उस समय भी cgi package को “खराब design वाला और अब सुधारना लगभग असंभव” बताया गया था
      https://github.com/jackrosenthal/legacy-cgi package standard library module का drop-in replacement देता हुआ लगता है
    • Python maintainers जिसे हटा रहे हैं वह cgi नाम का module है, CGI scripts implement करने का support अपने-आप नहीं
      वह support http.server module के CGIHTTPRequestHandler में बचा हुआ है
      cgi module में तो HTML form data parse करने वाले कुछ functions ही थे
    • Python द्वारा standard library से CGI हटाने पर नाराज़गी समझ में आती है
      लेकिन फिर alternative के तौर पर JS, जिसके पास खुद standard library ही नहीं है, पर विचार करना मुझे समझ नहीं आता
      Lua की standard library में भी CGI module नहीं है
    • पहले high-performance web एक तरह की technical art थी
      अब यह ज़्यादा उस तरफ़ है कि जल्दी launch करने के लिए डाले गए बेतहाशा wasteful हिस्से खोजो और उन्हें रोक दो
      ठीक से कोशिश की जाए तो app storage access के अलावा लगभग कोई extra latency न जोड़े
    • ऐसे मामलों में मैं default रूप से JIT वाले PHP या JS को ज़्यादा पसंद करता हूँ
      Python 1.6 से सीखा था, लेकिन मुख्य रूप से operating system scripting के लिए इस्तेमाल करता आया हूँ
      1999~2003 में Apache और IIS modules में Tcl इस्तेमाल किया, और modules को बार-बार C में rewrite करते हुए बहुत सारे सबक मुश्किल तरीके से सीखे
  • हाल में 350 डॉलर के mini server पर Golang binary, RabbitMQ, Redis, MySQL सब उसी मशीन पर चलाकर test किया, और उसने लगातार प्रति सेकंड 5,000 requests संभालीं
    24 घंटे के हिसाब से यह 40 करोड़ requests प्रति दिन है
    आज के free tools कितने शानदार हैं, यह हैरान करता है, और फिर भी हम cloud providers को इतना पैसा देते हैं, यह भी हैरान करता है
    पूरी तरह same comparison नहीं है, लेकिन basement की machine पर सब कुछ develop और tune करने की प्रक्रिया सचमुच अच्छी लगी

    • बहुत बार देखा है कि लोग यह जाने बिना कि server प्रति सेकंड 1 request से कहीं ज़्यादा संभाल सकता है, development speed को 10 गुना धीमा करने वाला Kubernetes microservices monster deploy कर देते हैं
      “Google ऐसा करता है” के अलावा कोई वजह नहीं, फिर भी ऐसा overhead लगातार झेलना अजीब है
      हमें जिस modular monolith architecture से अच्छा फायदा मिल रहा है, उस पर ज़रूर लिखना चाहिए
    • cloud provider को पैसा देना ज़रूरी नहीं है
      hosting company से dedicated server किराये पर लेकर मन भर इस्तेमाल कर सकते हैं। बस bandwidth या transfer limits में काफ़ी बंध जाते हैं
      cloud इसलिए इस्तेमाल होता है क्योंकि इसमें कई हित जुड़े होते हैं। जैसे VC और investors के पास cloud companies की equity भी होती है, और वे उस काल्पनिक traffic spike से investment डूबने से डरते हैं जो असल में आने वाला नहीं
      cloud sales investors की बेचैनी को छूने में माहिर है
    • side project को basement से host करने का सोचा था, लेकिन तब power outage और ISP failure के लिए vulnerable हो जाता है
      यात्रा के दौरान drive fail हो जाए तो कोई उपाय नहीं, और गलती से lock कर दूँ तो fallback के लिए serial terminal भी नहीं है
      r/homelab वालों की तरह setup कर सकता हूँ, लेकिन फिर खासकर मेरा समय जोड़ने पर यह साफ़ नहीं रहता कि सच में पैसे बचते भी हैं या नहीं
      निष्कर्षतः cloud provider scale की economies की वजह से काफ़ी अच्छा deal लगता है
    • VM cost देखें तो महंगी होने की वजह बहुत ज़्यादा compute नहीं, बल्कि काफी local disk वाले server की ज़रूरत है
      अजीब बात है कि दोनों में से एक चीज़ अलग से नहीं मिल पाती
      कल्पना कीजिए, सिर्फ 4 20TB drives और ठीक-ठाक CPU लगा हो तो कितना बड़ा business या service चला सकते हैं
      cloud provider से ऐसा configuration पाना आसान नहीं है
  • “शुरुआती web community ने जल्दी सीख लिया कि यह bad idea है और PHP जैसी technologies invent कीं” वाला हिस्सा, कड़ाई से कहें तो core technology mod_php थी
    PHP अपने execution तरीके में Perl से अलग नहीं था, लेकिन mod_perl की तुलना में mod_php के design choices की वजह से PHP scripts server पर बस डाल देने से तेज़ चलती थीं, जबकि mod_perl चलाने के लिए थोड़ी सोच-विचार और जादू चाहिए होता था

    • उस दौर में मैं एक दोस्त के साथ वह चीज़ बना रहा था जिसे बाद में learning management system कहा जाता
      उसमें content management, assignment uploads, event calendar, grade management, real-time chat, forums थे और सब कुछ CGI पर pure C में था, जिस पर काम करना नरक जैसा था
      जिस दिन PHP के बारे में पता चला, लगभग रोना आ गया था, क्योंकि RFC पढ़कर या HTTP को reverse-engineer करके शुरू से मुश्किल से बनाई गई हर चीज़ PHP में सिर्फ simple function call थी
      अब घटिया urlencode implementation debug करने या HTTP header में किसी अजीब carriage return की वजह से पूरा दिन बर्बाद करने की ज़रूरत नहीं थी
    • सही है, लेकिन mod_php PHP ecosystem में शुरुआती दौर में जुड़ गया था और जल्दी ही default distribution method बन गया
      Apache module का पहला version शायद 1996 में PHP/FI Version 2.0 के लिए था: https://www.php.net/manual/phpfi2.php#module
  • अगर cgi-bin को DB access करना हो, तो हर बार process शुरू होने पर connection खोलना पड़ेगा
    FastCGI की तरह code को memory में बनाए रखना सिर्फ startup time की cost से बचने के लिए नहीं है, बल्कि इसलिए भी है कि DB connection pool या कम-से-कम per-thread persistent connection रखा जा सके

    • scale बढ़ने पर connection count की वजह से database पर दबाव पड़ता है
      “Python single-threaded है, इसलिए बहुत सारे instances चला दो” और “Python धीमा है, इसलिए बहुत सारे instances चला दो” — दोनों साथ करने पर ऐसा ही हुआ था
      scale बढ़ने पर आखिरकार pgbouncer जैसे Python के बाहर के shared connection pool और बहुत सारी tuning से load संभालना पड़ता है, ताकि DB बंद न हो जाए
      बेशक, उसके बाद जब इसे ठीक-ठाक performance देने वाली multi-threaded language में फिर से implement किया, तो चीज़ें फिर बहुत simple हो गईं
    • इसलिए CGI अंततः ऐसे model में evolve हुआ जिसमें requests के बीच कुछ state बनाए रखी जाती है
    • इसे handle करने के standard तरीके भी थे
      असल में यह एक अलग daemon चलाने जैसा है, जो proxy की तरह काम करता है
      TCP/IP की जगह Unix socket इस्तेमाल करें तो connection cost तुलनात्मक रूप से कम हो जाती है
    • UDP इस्तेमाल कर सकते हैं
  • इस hardware पर hello world app का 2,400 requests/sec देना थोड़ा खराब नहीं है क्या
    performance छोड़कर बदले में ठीक-ठीक क्या मिल रहा है, यह भी समझ नहीं आता। code भी ज्यादा simple नहीं हुआ

    • यह खराब संख्या तभी है जब आपको 2,000 requests/sec से ऊपर जाना हो
      ऐसी sites कुल sites का सिर्फ एक हिस्सा हैं
    • शानदार नहीं है, लेकिन कई use cases के लिए पर्याप्त है
      शायद HN की traffic bomb भी झेल लेगा
  • कल भी इस पर चर्चा हुई थी: https://news.ycombinator.com/item?id=44464272

  • कंपनी में हम कभी-कभी जल्दी बनाए जाने वाले internal web apps के लिए अब भी cgi-bin directory serve करते हैं
    simple रखा जाए तो usability अच्छी रहती है
    CGI होने का मतलब यह नहीं कि HTTP/1.0 को सीधे stdout पर print करना ही पड़े
    उदाहरण के लिए, Python का built-in wsgiref.handlers.CGIHandler इस्तेमाल करें तो किसी भी WSGI app को CGI script की तरह चला सकते हैं
    import wsgiref.handlers, flask
    app = flask.Flask(name)
    wsgiref.handlers.CGIHandler().run(app)
    हम scripts को uwsgi और उसके CGI plugin[1] से चलाते हैं
    mod_cgi की वजह से Apache या lighttpd चलाने की तुलना में यह ज्यादा simple और flexible लगता है
    uwsgi systemd unit के रूप में चलता है, इसलिए systemd की hardening और sandboxing features का भी पूरा उपयोग कर सकते हैं
    uwsgi की CGI handling में mod_cgi की तुलना में एक सुविधाजनक बात यह है कि किसी खास file type के लिए interpreter specify किया जा सकता है
    cgi = /cgi-bin=/webapps/cgi-bin/src
    cgi-allowed-ext = .py
    cgi-helper = .py=/webapps/cgi-bin/venv/bin/python3 # all dependencies go here
    first byte तक time 250~350ms है, और हमारे use case के लिए यह acceptable है
    [1]: https://uwsgi-docs.readthedocs.io/en/latest/CGI.html

    • अच्छी जानकारी है, और wsgiref.handlers.CGIHandler अभी deprecation के लिए तय नहीं लगता
  • हाल ही में एक side project में Apache इस्तेमाल किया, और वजहों में से एक .htaccess feature था, इसलिए ऐसी ही बातचीत हुई
    .htaccess file कहीं भी रख दें, तो Apache उसे हर request पर अतिरिक्त server configuration के रूप में पढ़ सकता है: https://httpd.apache.org/docs/2.4/howto/htaccess.html
    इससे बचने की बड़ी वजह performance थी। हर request पर अतिरिक्त disk access चाहिए होता था, और संभव हो तो इसे main config file में डालना हमेशा बेहतर था
    लेकिन अब ज्यादातर servers में SSD होते हैं, और Linux के पास filesystem cache के लिए खाली RAM होने की भी काफी संभावना है
    बेशक, Apache को config एक बार नहीं बल्कि हर request पर parse करना पड़ता है, इसलिए performance अब भी थोड़ी खराब होती है
    फिर भी, आजकल ज्यादातर server CPUs ज्यादा powerful हैं, इसलिए कई use cases में इसे accept किया जा सकता है
    side project अभी बहुत early version में है, लेकिन पहले से उपयोग में है: https://github.com/StaticPatch/StaticPatch/tree/main

    • Rasmus Lerdorf को quote करें तो:
      “मैं असली programmer नहीं हूँ। जब तक चीज़ चलने न लगे, मैं तरह-तरह की चीज़ें जोड़कर देखता हूँ और फिर आगे बढ़ जाता हूँ। असली programmers कहेंगे, ‘ठीक है, चल तो रहा है, लेकिन यहाँ-वहाँ memory leak हो रही है। इसे ठीक नहीं करना चाहिए?’ मैं Apache को हर 10 requests पर restart कर सकता हूँ।”
      PHP उसके बाद बहुत आगे आ चुका है, लेकिन उसका बड़ा हिस्सा शुरुआती गलतियों को ठीक करने की प्रक्रिया था
      “PHP 8 इतना बेहतर इसलिए है क्योंकि इसमें मेरा code बहुत कम है।”
    • समझ नहीं आता कि Apache file system को बस watch क्यों नहीं करता
      इस choice की वजह से 99.99% HTTP requests अनावश्यक disk reads के कारण slow हो जाती हैं
  • तेज़ prototyping workflow के हिस्से के तौर पर इस पर और ज़्यादा सोचा
    आधुनिक JIT languages में, जब तक वे FastCGI मॉडल पर नहीं जाते, startup time ज़्यादातर imports से ही dominate होगा
    local scripts के लिए h2o web server इस्तेमाल करना शुरू करने पर यह विचार आया; mruby और FastCGI handler के साथ config files साफ़-सुथरी और तेज़ी से लिखी जा सकती हैं, और speed भी बहुत तेज़ है: https://h2o.examp1e.net/configure/fastcgi_directives.html
    एक और जगह जहाँ यह उपयोगी है: जब ग्राहकों को local software को अपने code से extend करने देना हो
    उदाहरण के लिए, किसी AI tool को extend करने के लिए MCP इस्तेमाल करवाने के बजाय, उनसे किसी खास request structure को CGI के रूप में implement कराया जा सकता है

    • end-user environment में CGI programs के लिए MCP frontend कोई बुरा idea नहीं है
      सोच रहा हूँ कि क्या MCP service को खुद भी CGI के रूप में implement किया जा सकता है
      MCP framework ऐसे program के रूप में functionality expose कर सकता है जो दोनों execution modes support करता हो
      specification को थोड़ा और खंगालना पड़ेगा
    • FastCGI अक्सर CGI के लगभग सभी फायदे खो देता है
  • मेरे लिए inetd ही CGI था
    इसकी वजह से internet कहीं ज़्यादा मज़ेदार हो गया था
    मैंने खुद inetd से कई shell scripts host की थीं, और एक HTTP server भी था जो पूरी तरह Bash में लिखा था
    वह VPS बहुत पहले गायब हो गया, और उस समय मैं version control भी इस्तेमाल नहीं करता था
    जिस laptop पर मैंने वह लिखा था, वह भी अब नहीं है
    फिर भी वह सचमुच मज़ेदार था
    deployment Makefile + scp जितना आसान था, और testing एक और Bash script थी जिसमें कई netcat और grep मिलाए गए थे
    क्या अच्छे दिन थे