2 पॉइंट द्वारा GN⁺ 2024-11-30 | 1 टिप्पणियां | WhatsApp पर शेयर करें

बेंचमार्क

  • Coroutine क्या है?

    • Coroutine कंप्यूटर प्रोग्राम का एक ऐसा घटक है जो प्रोग्राम के execution को अस्थायी रूप से रोककर फिर से शुरू कर सकता है, और यह cooperative multitasking के लिए subroutine का एक सामान्यीकृत रूप है.
    • यह cooperative tasks, exceptions, event loop, iterators, infinite lists और pipes जैसे प्रोग्राम घटकों को लागू करने के लिए उपयुक्त है.
  • Rust

    • दो प्रोग्राम लिखे गए: tokio और async_std का उपयोग करने वाले प्रोग्राम.
    • दोनों ही Rust में आमतौर पर उपयोग किए जाने वाले asynchronous runtime हैं.
  • C#

    • C# भी Rust की तरह async/await को सपोर्ट करता है.
    • .NET 7 से NativeAOT compilation उपलब्ध है, जिससे VM के बिना भी managed code चलाया जा सकता है.
  • NodeJS

    • asynchronous tasks के लिए Promise.all का उपयोग किया गया.
  • Python

    • asynchronous tasks चलाने के लिए asyncio module का उपयोग किया गया.
  • Go

    • concurrency को goroutine के जरिए लागू किया जाता है, और tasks के पूरा होने की प्रतीक्षा के लिए WaitGroup का उपयोग किया जाता है.
  • Java

    • JDK 21 से virtual threads उपलब्ध हैं, जो goroutine जैसी अवधारणा है.
    • GraalVM का उपयोग करके native image बनाई जा सकती है.

टेस्ट वातावरण

  • हार्डवेयर: 13वीं पीढ़ी Intel(R) Core(TM) i7-13700K
  • ऑपरेटिंग सिस्टम: Debian GNU/Linux 12 (bookworm)
  • Rust: 1.82.0
  • .NET: 9.0.100
  • Go: 1.23.3
  • Java: openjdk 23.0.1
  • Java (GraalVM): java 23.0.1
  • NodeJS: v23.2.0
  • Python: 3.13.0

परिणाम

  • न्यूनतम मेमोरी उपयोग

    • Rust, C# (NativeAOT), और Go native binary में compile होते हैं, इसलिए कम मेमोरी का उपयोग करते हैं.
    • Java (GraalVM native image) ने भी अच्छा प्रदर्शन दिखाया, लेकिन अन्य statically compiled भाषाओं की तुलना में अधिक मेमोरी का उपयोग किया.
  • 10K tasks

    • Rust में मेमोरी उपयोग लगभग नहीं बढ़ा.
    • C# (NativeAOT) ने भी कम मेमोरी का उपयोग किया.
    • Go ने अपेक्षा से अधिक मेमोरी का उपयोग किया.
  • 100K tasks

    • Rust और C# ने अच्छा प्रदर्शन दिखाया.
    • C# (NativeAOT) ने Rust से कम मेमोरी का उपयोग किया.
  • 10 लाख tasks

    • C# ने सभी भाषाओं को पीछे छोड़ते हुए सबसे कम मेमोरी का उपयोग किया.
    • Rust भी मेमोरी दक्षता में बहुत अच्छा रहा.
    • Go ने अन्य भाषाओं की तुलना में अधिक मेमोरी का उपयोग किया.

निष्कर्ष

  • बड़ी संख्या में समवर्ती tasks, भले ही वे जटिल काम न कर रहे हों, फिर भी काफी मेमोरी खर्च कर सकते हैं.
  • .NET और NativeAOT में सुधार स्पष्ट रूप से दिखाई देते हैं, और GraalVM से बनी Java native image भी मेमोरी दक्षता में उत्कृष्ट है.
  • goroutine अभी भी resource consumption के मामले में अप्रभावी हैं.

परिशिष्ट

  • Rust (tokio) में join_all की जगह for loop का उपयोग करके मेमोरी उपयोग आधा कर दिया गया. इस बेंचमार्क में Rust ने स्पष्ट बढ़त हासिल की.

1 टिप्पणियां

 
GN⁺ 2024-11-30
Hacker News राय
  • बेंचमार्क Node और Go के asynchronous processing तरीकों के अंतर को ठीक से नहीं दिखाता। Node Promise.all का उपयोग करता है और Go goroutine का, इसलिए अंतर है। asynchronous I/O और CPU-bound कामों के memory usage के अंतर की तुलना करना दिलचस्प होगा

  • यह "10 सेकंड तक इंतज़ार करने वाला काम" और "10 सेकंड बाद जगाया जाने वाला काम" के बीच का अंतर समझाता है। Go कोड का memory usage दूसरे कोड की तुलना में काफ़ी अलग है

  • Go और Node की निष्पक्ष तुलना के लिए timer schedule करने वाले goroutine और timer signal संभालने वाले goroutine का उपयोग करने का सुझाव दिया गया है। यह भी कहा गया है कि Node तुलना में Bun और Deno का शामिल न होना अजीब है

  • बहुत सारे concurrent tasks काफ़ी memory consume कर सकते हैं, लेकिन अगर प्रति task data कुछ KB से ज़्यादा है तो scheduler का memory overhead लगभग नज़रअंदाज़ करने लायक होता है

  • "concurrent tasks" की परिभाषा के अनुसार memory usage बदल सकता है। एक efficient implementation में 1M concurrent tasks के लिए लगभग 200MB चाहिए

  • यह इंगित किया गया है कि memory usage में Go, Java की तुलना में 2 गुना से भी ज़्यादा पीछे है, और कहा गया है कि यह benchmark वास्तविक प्रोग्रामों का प्रतिनिधित्व नहीं करता

  • सरल code से भाषाओं की तुलना करना developers के लिए अनुचित हो सकता है, और सलाह दी गई है कि वास्तविक काम जोड़कर memory usage और scheduling के अंतर को मापा जाए

  • कहा गया है कि benchmarks अक्सर गलतियों से भरे होते हैं, और ऐसे benchmarks प्रकाशित करने वालों की मंशा समझ में नहीं आती

  • Java benchmark के गलत होने की संभावना बताई गई है, क्योंकि ArrayList का initial size तय नहीं किया गया, जिससे बहुत से अनावश्यक objects बनते हैं

  • यह समझाया गया है कि Rust का asynchronous code उम्मीद से पहले क्यों पूरा हो जाता है। क्योंकि tokio::time::sleep() future के बनाए जाने के समय को track करता है