प्रौद्योगिकी

JVM पर MMORPG चलाना है??

AAnonymous
4 मिनट पढ़ें

शुरुआत

इन दिनों मैं काफ़ी ढीला पड़ गया था। अब फिर से खुद को ठीक से संभालने की ज़रूरत है। :( काफ़ी समय बाद मैं ब्लॉग पोस्ट लिख रहा हूँ।

How We Make Games में मैंने लिखा था कि MMORPG मेरा अंतिम बड़ा चैलेंज होगा। उसके बाद जो सबसे सामान्य प्रतिक्रिया दिमाग में आती है, वह शायद यही है: Java? क्या आप सच में JVM पर एक real-time MMORPG बनाकर चलाने वाले हैं? क्या यह सिर्फ बहुत छोटे scale पर ही संभव नहीं है?

इस पोस्ट का एक ही केंद्रीय तर्क है। आज JVM पर high-Hz server tick का वास्तविक विकल्प बन पाना सबसे अधिक GC की प्रगति की वजह से है। Netty महत्वपूर्ण है। Kotlin महत्वपूर्ण है। Zone partitioning और AOI जैसी MMO techniques भी महत्वपूर्ण हैं। लेकिन इन सब से पहले जिस चीज़ को देखना चाहिए, वह pause time है।

इस क्षेत्र में असली सवाल average performance नहीं, GC है

अगर आपको पुराना Java याद है, तो real-time network game के बारे में सोचते ही सबसे पहले GC की चिंता आती होगी। और अधिक सटीक रूप से कहें तो यह throughput का नहीं, बल्कि tail latency का प्रश्न है। Average ठीक दिख सकता है, लेकिन एक लंबा stop-the-world pause आते ही tick पीछे खिसक जाता है और input responsiveness तथा combat feel दोनों टूट जाते हैं।

यह game server में विशेष रूप से खतरनाक है।

  • 20Hz server का tick budget 50ms होता है।
  • 60Hz server का tick budget 16.6ms होता है।
  • 128Hz server का tick budget 7.8ms होता है।

अगर GC pause कई बार अचानक दर्जनों milliseconds तक पहुँच जाए, तो average TPS सही दिखने पर भी players तुरंत महसूस कर लेते हैं कि कुछ गड़बड़ है। Rubber banding, input delay, combat desync और packet flush delay अक्सर ऐसे ही tail problems से शुरू होते हैं। इसलिए JVM real-time game के लिए ठीक है या नहीं, यह सवाल वास्तव में JVM का average performance कितना है से कम और GC अब कितना छोटा और predictable हो चुका है से ज़्यादा जुड़ा है।

आधुनिक JVM GC अब पहले जैसा नहीं रहा

यहीं पर स्थिति बहुत बदल चुकी है। सिर्फ OpenJDK की दिशा को देखें तो बदलाव साफ़ दिखता है।

  • ZGC, JDK 15 में production feature बना।
  • Generational ZGC, JDK 21 में आया।
  • JDK 23 में Generational ZGC default mode बन गया।
  • JDK 24 में non-generational ZGC हटा दिया गया।
  • यानी Java 25 को generational-only ZGC युग का पहला LTS माना जा सकता है
  • Shenandoah पहले से production GC था, और Java 25 में उसका generational mode भी product feature बन गया।

यह सिर्फ JVM में एक नया option जुड़ जाने की बात नहीं है। OpenJDK के अनुसार, Generational ZGC को इस तरह डिज़ाइन किया गया है कि वह young objects को अधिक बार collect करे, allocation stall के जोखिम को घटाए, required heap overhead को कम करे, और GC CPU overhead को भी नीचे लाए। सबसे महत्वपूर्ण बात यह है कि pause behavior बना रहता है। JEP 439 कहता है कि application pauses आम तौर पर 1ms से कम रखे जाते हैं।

इसका मतलब यह है कि जो पुरानी धारणा Java game server को शुरू से ही बाहर कर देती थी, यानी GC कभी-कभी पूरी दुनिया रोक देता है, वह अब default premise नहीं रही। GC गायब नहीं हुआ है। लेकिन GC अब अपने आप में JVM को तुरंत खारिज करने का निर्णायक कारण भी नहीं रहा।

Production के वास्तविक उदाहरण भी इसी दिशा की पुष्टि करते हैं

सबसे दिलचस्प उदाहरणों में से एक Netflix है। Netflix ने JDK 21 के बाद अपनी default GC posture को Generational ZGC की ओर मोड़ा, और उसके अनुसार अब उसके critical streaming video services में आधे से अधिक JDK 21 + Generational ZGC पर चल रहे हैं।

और भी महत्वपूर्ण बात यह है कि परिणाम उम्मीद से बेहतर निकले। Netflix ने शुरू में सोचा था कि ZGC शायद थोड़ा throughput छोड़कर कम latency खरीदने वाला tradeoff होगा। लेकिन व्यवहार में average latency और P99 latency दोनों बेहतर हुए, और CPU utilization भी बराबर या बेहतर रहा। उनके सबसे खराब मामलों में से एक में non-generational ZGC, G1 की तुलना में 36% अधिक CPU ले रहा था, जबकि Generational ZGC ने उसी workload पर लगभग 10% CPU improvement दिया।

बेशक Netflix कोई game company नहीं है। लेकिन यहाँ देखने वाली बात product category नहीं है। असली बात यह है कि कोई system pauses और tail latency को कितनी स्थिरता से संभालता है। Real-time game server भी मूल रूप से यही समस्या हल करता है, बस और भी कड़े budget के अंदर।

तो क्या JVM पर real-time game वास्तव में बनाया जा सकता है?

अब क्या JVM पर real-time game बन सकता है? जैसे एक ही वाक्य वाले सवाल से ज़्यादा मदद नहीं मिलती। इसे अलग-अलग क्षेत्रों में बाँटकर देखना होगा।

काफ़ी व्यवहारिक क्षेत्र अब पहले से कहीं व्यापक है।

  • Tick-based MMORPG
  • Sandbox world servers
  • Lobby, matchmaking, और state synchronization backends
  • ऐसे multiplayer games जिन्हें लगभग 20~60Hz server tick चाहिए

एक बहुत प्रसिद्ध उदाहरण Minecraft Java Edition server है। सिर्फ यही तथ्य अब यह कहना कठिन बना देता है कि Java real-time multiplayer world चला ही नहीं सकता।

इसके बावजूद कुछ ऐसे क्षेत्र हैं जहाँ अभी भी अतिरिक्त सावधानी चाहिए।

  • 128Hz competitive FPS, जहाँ tick budget बहुत कड़ा है
  • ऐसे workloads जिन्हें बहुत ही deterministic latency चाहिए
  • ऐसे environments जिनमें memory headroom बहुत कम हो
  • ऐसे systems जहाँ GC threads और application threads पहले से saturated CPU पर आपस में टकरा रहे हों

इसलिए बात यह नहीं है कि JVM सब कुछ कर सकता है। बात यह है कि ज्यादातर game-server scenarios में GC pause की वह समस्या, जो पहले JVM को खारिज करने की सबसे बड़ी वजह थी, अब काफी हद तक कम हो चुकी है

और उसके बाद ही MMO-specific design वाकई मायने रखती है

यहाँ क्रम बहुत महत्वपूर्ण है। मैं बार-बार कहता रहा हूँ कि zone tick, per-system cadence, और AOI-driven synchronization अहम हैं। जिस mmorpg-service पर मैं काम कर रहा हूँ, वह वास्तव में इसी संरचना का पालन करता है।

  • Base loop 10Hz पर चलता है
  • World और Zone settings को 1~15Hz range में समायोजित किया जा सकता है
  • Monster AI, state के अनुसार अलग cadence इस्तेमाल करती है
  • Drop despawn checks और auto-recovery retries धीमे interval पर चलते हैं
  • Netty I/O threads केवल packets लेते हैं, जबकि वास्तविक game rules को zone loops लागू करते हैं
  • AOIManager distance और events के आधार पर synchronization frequency बदलता है

लेकिन यह सब अभी भी दूसरी परत है। अगर pause time अभी भी कई बार दर्जनों milliseconds तक उछल रहा हो, तो ऊपर से zone tick बाँटना और AOI को सूक्ष्म बनाना नींव को नहीं बचाता। High Hz के व्यवहारिक होने की सबसे बड़ी वजह GC की प्रगति है। MMO design, उसी परत के ऊपर बनाई जाने वाली दूसरी संरचना है।

आखिरकार, इस पोस्ट का सार एक ही वाक्य है

आज JVM पर high-Hz processing के व्यावहारिक होने की सबसे बड़ी वजह GC की प्रगति है।

पहले Java = खतरनाक stop-the-world जैसी धारणा बहुत मज़बूत थी। अब low-pause collectors कहीं अधिक mature हो चुके हैं, और Generational ZGC तथा Shenandoah की नई दिशा के साथ JVM अब ऐसी platform नहीं रही जिसे real-time server की चर्चा से अपने आप बाहर कर दिया जाए।

जब आप इसके ऊपर Kotlin और Netty रखते हैं, और फिर zone loops, cadence तथा AOI जैसी MMO design techniques जोड़ते हैं, तो कहानी पूरी तरह बदल जाती है। अब सवाल यह नहीं होना चाहिए कि क्या JVM इसे असंभव बनाती है?, बल्कि यह होना चाहिए कि हम अपने latency budget के भीतर GC और tick को कैसे design करें?

इसी वजह से मुझे लगता है कि JVM पर MMORPG चलाना अब पूरी तरह एक वास्तविक विकल्प बन चुका है।