2024 में 10 लाख समवर्ती tasks चलाने के लिए कितनी memory चाहिए
(hez2010.github.io)- यह बेंचमार्क 2024 के अंत तक के नवीनतम languages और runtimes के आधार पर 1 से 10 लाख तक के concurrent tasks की memory usage की तुलना करता है, और नवीनतम नतीजों के लिए अलग Take 2 पेज देखने की सलाह देता है
- सभी tests को एक ही संरचना में रखा गया: हर task 10 सेकंड तक wait करता है और फिर सभी tasks के पूरा होने का इंतज़ार किया जाता है; इसमें कई threads के बजाय coroutines, asynchronous tasks, goroutines और virtual threads की memory characteristics की तुलना की गई है
- तुलना में Rust
tokio·async_std, C# और NativeAOT, NodeJS, Pythonasyncio, Go goroutine, Java virtual thread, और Java GraalVM native image शामिल हैं; पूरा code GitHub पर उपलब्ध है - tasks की संख्या बढ़ने के साथ अलग-अलग runtimes में memory वृद्धि का अंतर बहुत बड़ा दिखा, और 10 लाख tasks पर C# ने सबसे कम memory usage दिखाया, जबकि Rust ने भी efficient नतीजे बनाए रखे
- नवीनतम .NET में बड़ा सुधार दिखा और NativeAOT ने Rust को कड़ी टक्कर दी, लेकिन Go goroutine ने 10 लाख tasks पर विजेता नतीजे से 13 गुना से अधिक, और Java से 2 गुना से अधिक memory का उपयोग किया
बेंचमार्क का तरीका और सार्वजनिक सामग्री
- 2024 के अंत तक के नवीनतम language versions के साथ 2023 की asynchronous programming memory consumption तुलना को फिर से चलाने का यह परिणाम है
- ऊपर यह निर्देश दिया गया है कि नवीनतम परिणामों के लिए How Much Memory Do You Need in 2024 to Run 1 Million Concurrent Tasks? - Take 2 देखें
- test program command-line argument के रूप में मिले
Nconcurrent tasks बनाता है, हर task 10 सेकंड तक wait करता है, और फिर सभी tasks समाप्त होने पर program बंद हो जाता है - तुलना का फोकस कई threads पर नहीं, बल्कि coroutine-आधारित concurrency models पर है
- पूरा benchmark code async-runtimes-benchmarks-2024 पर सार्वजनिक है
तुलना में शामिल languages और runtimes
- Rust की तुलना
tokioऔरasync_stdदो asynchronous runtimes के साथ की गई है- दोनों Rust में व्यापक रूप से इस्तेमाल होने वाले asynchronous runtimes हैं
- C# में
async/awaitका सीधा support है, औरTask.DelayतथाTask.WhenAllसे tasks चलाए जाते हैं- .NET 7 से उपलब्ध NativeAOT की भी तुलना की गई है
- NativeAOT managed code को VM के बिना चलाने के लिए सीधे final binary में compile करता है
- NodeJS में
setTimeoutकोutil.promisifyसे wrap करकेPromise.allके साथ wait किया जाता है - Python में
asyncio.sleepऔरasyncio.gatherका उपयोग किया गया है - Go में concurrency primitive के रूप में goroutine का उपयोग होता है, और individual await की जगह
WaitGroupसे सभी tasks के पूरा होने का इंतज़ार किया जाता है - Java में JDK 21 से उपलब्ध virtual thread का उपयोग किया गया है
- GraalVM की native image की भी तुलना की गई है
- GraalVM native image को .NET NativeAOT जैसे समान विचार के रूप में शामिल किया गया है
test environment
- hardware: 13th Gen Intel Core i7-13700K
- operating system: Debian GNU/Linux 12(bookworm)
- Rust: 1.82.0
- .NET: 9.0.100
- Go: 1.23.3
- Java: openjdk 23.0.1 build 23.0.1+11-39
- Java(GraalVM): java 23.0.1 build 23.0.1+11-jvmci-b01
- NodeJS: v23.2.0
- Python: 3.13.0
- जहाँ संभव था, सभी programs release mode में चलाए गए
- test environment में
libicuनहीं होने के कारण internationalization और globalization support disabled था
tasks की संख्या बढ़ने पर memory में बदलाव
-
न्यूनतम footprint: 1 task
- runtime की अपनी memory requirement देखने के लिए पहले सिर्फ 1 task चलाया गया
- Rust, C# NativeAOT, और Go को statically compiled native binaries के रूप में चलाया गया, इसलिए इनकी memory usage बहुत कम रही और परिणाम एक-दूसरे के करीब थे
- Java GraalVM native image ने भी अच्छा परिणाम दिया, लेकिन दूसरे statically compiled targets की तुलना में थोड़ी अधिक memory इस्तेमाल की
- managed platform या interpreter पर चलने वाले programs ने अधिक memory consume की
- इस चरण में Go का footprint सबसे छोटा था
- Java GraalVM ने OpenJDK Java की तुलना में काफी अधिक memory इस्तेमाल की, हालांकि यह settings से adjust हो सकता है
-
10 हजार tasks
- Rust के दोनों benchmarks में 10 हजार tasks पर भी न्यूनतम footprint की तुलना में memory usage बहुत अधिक नहीं बढ़ी, और memory बहुत कम बनी रही
- C# NativeAOT ने भी लगभग 10MB memory ही इस्तेमाल की और Rust के ठीक पीछे रहा
- Go की memory usage इस चरण में काफी बढ़ गई
- Java GraalVM native image के virtual threads, Go goroutine से हल्के दिखाई दिए
- Go और Java GraalVM native image statically compiled native binaries थे, फिर भी उन्होंने VM पर चलने वाले C# से अधिक RAM इस्तेमाल की
-
1 लाख tasks
- tasks की संख्या 1 लाख होने पर सभी languages की memory consumption तेज़ी से बढ़नी शुरू हुई
- Rust और C# ने इस चरण में भी अच्छे नतीजे दिए
- C# NativeAOT ने Rust से भी कम RAM इस्तेमाल की और सभी languages से आगे रहा
- Go program इस बिंदु पर सिर्फ Rust ही नहीं, बल्कि Java, C#, और NodeJS से भी पीछे रहा
- अपवाद के रूप में GraalVM पर चलाया गया Java, Go को हराने वालों की सूची से बाहर रहा
-
10 लाख tasks
- 10 लाख tasks पर C# ने बाकी सभी languages को स्पष्ट रूप से पीछे छोड़ दिया
- Rust ने अपेक्षा के अनुसार memory efficiency में अच्छे नतीजे जारी रखे
- Go और दूसरे runtimes के बीच का अंतर और बड़ा हो गया
- Go ने विजेता नतीजे की तुलना में 13 गुना से अधिक memory इस्तेमाल की
- Java की तुलना में भी Go ने 2 गुना से अधिक memory इस्तेमाल की, जो इस आम धारणा से अलग नतीजा है कि JVM memory-heavy होता है और Go हल्का
अंतिम अवलोकन
- जब concurrent tasks की संख्या बहुत अधिक हो, तो हर task जटिल computation न करने पर भी काफी memory इस्तेमाल कर सकता है
- हर language runtime में trade-offs अलग तरह से सामने आते हैं
- कम tasks पर वह हल्का और efficient हो सकता है
- लेकिन लाखों tasks तक scale करने पर memory वृद्धि तेज़ हो सकती है
- नवीनतम compiler और runtime के आधार पर .NET में बड़ा सुधार दिखा
- .NET NativeAOT ने Rust के बराबरी के competitive नतीजे दिए
- Java की GraalVM native image ने भी memory efficiency में अच्छे नतीजे दिए
- Go goroutine ने resource consumption के लिहाज़ से लगातार inefficient परिणाम दिखाए
अभी कोई टिप्पणी नहीं है.