2012-03-24 10 views
7

बनाना मैं एक प्रोग्रामर हूं जो लिनक्स आधारित सर्वर का उपयोग करके एक मल्टीप्लेयर ऑनलाइन गेम विकसित कर रहा है। हम अपनी दुनिया के लिए "इंस्टेंट" आर्किटेक्चर का उपयोग करते हैं। इसका मतलब यह है कि प्रत्येक क्षेत्र में प्रवेश करने वाले प्रत्येक खिलाड़ी को उस क्षेत्र की प्रतिलिपि मिलती है ताकि वे अपने पार्टी के सदस्यों के साथ खेल सकें और उसी क्षेत्र में खेलने वाले सभी अन्य खिलाड़ियों से स्वतंत्र हो सकें।अधिक कुशल उपयोग फोर्क() और कॉपी-ऑन-राइट मेमोरी शेयरिंग

आंतरिक हम प्रत्येक उदाहरण के लिए एक अलग प्रक्रिया का उपयोग करें। प्रारंभ में प्रत्येक इंस्टेंस प्रक्रिया शुरू हो जाएगी, दिए गए क्षेत्र के लिए आवश्यक संसाधनों को लोड करें, इसे यादृच्छिक इलाके बनाएं, और फिर खिलाड़ियों से नए कनेक्शन की अनुमति दें। किसी उदाहरण द्वारा उपयोग की जाने वाली स्मृति की मात्रा आम तौर पर 25 मेगापिक्सल संसाधनों और इकाइयों के साथ यादृच्छिक रूप से जेनरेट किए गए स्तर सहित थी।

उदाहरणों की स्मृति पदचिह्न को कम करने के लिए, और स्पॉन समय को तेज करने के लिए, हम एक ऐसे दृष्टिकोण में बदल गए जहां हम एक एकल मास्टर इंस्टेंस बनाते हैं जो सभी संसाधनों को लोड करता है जो किसी भी उदाहरण की आवश्यकता हो सकती है (लगभग 150 मेगापिक्सल मेमोरी) और फिर जब एक नया उदाहरण आवश्यक है, तो एक नया उदाहरण बनाने के लिए कांटा() फ़ंक्शन का उपयोग करें और कॉपी-ऑन-राइट मेमोरी साझाकरण का उपयोग करें ताकि नए इंस्टेंस को केवल "अद्वितीय" डेटा सेट के लिए स्मृति की आवश्यकता हो। यादृच्छिक रूप से जेनरेट किए गए स्तर और संस्थाओं का पदचिह्न जो प्रत्येक उदाहरण के लिए अद्वितीय डेटा बनाता है, लगभग 3-4 मेगाहर्ट्ज मेमोरी है।

दुर्भाग्य से स्मृति साझा करने के साथ-साथ मुझे लगता है कि यह हो सकता से काम नहीं कर रहा है। बहुत सारे मेमोरी पेज unshared बनने लगते हैं।

सबसे पहले, जैसा कि हम प्रीफ़ोर उदाहरण में हमारे अधिक डेटा सेट को लोड करते हैं, प्रत्येक फोर्कड इंस्टेंस के लिए आवश्यक मेमोरी नीचे जाती है, लेकिन आखिर में एक इन्फ्लिक्शन पॉइंट होता है जहां प्रीफ़ोर में अधिक संपत्तियां लोड करना वास्तव में उपयोग किए जाने वाले डेटा को बढ़ाता है प्रत्येक फोर्कड उदाहरण।

सबसे अच्छा परिणाम हम डेटा पूर्व कांटा सेट के 80 मेग लोड कर रहे हैं, और फिर ताजा उदाहरणों होने पड़ा है की मांग बाकी लोड। इसके परिणामस्वरूप लगभग 7-10 अतिरिक्त मेग प्रति उदाहरण और 80 मेगापिक्सल निश्चित लागत होती है। निश्चित रूप से एक अच्छा सुधार, लेकिन सैद्धांतिक सर्वश्रेष्ठ नहीं।

मैं पूरी 150 मेग डेटा सेट और फिर कांटा लोड करते हैं, तो प्रत्येक काँटेदार उदाहरण स्मृति के बारे में 50 अधिक मेग का उपयोग करता है! कुछ भी नहीं करने से महत्वपूर्ण रूप से बदतर।

मेरा सवाल यह है कि, मैं अपने सभी डेटा सेट को प्रीफ़ोर इंस्टेंस में कैसे लोड कर सकता हूं, और सुनिश्चित कर सकता हूं कि मुझे केवल प्रत्येक उदाहरण के लिए मेमोरी पदचिह्न के रूप में वास्तव में अद्वितीय उदाहरण डेटा का न्यूनतम सेट मिल रहा है।


मैं यहाँ क्या हो रहा है के रूप में एक सिद्धांत है और अगर किसी को मेरे लिए पुष्टि करते हैं कि यह मामला है मदद करने में सक्षम होगा मैं सोच रहा था।

मुझे लगता है कि malloc मुक्त श्रृंखला के साथ क्या करना है। प्रीफ़ोर इंस्टेंस के प्रत्येक मेमोरी पेज में शायद स्मृति में कुछ खाली स्पॉट्स शेष हैं। यदि, यादृच्छिक स्तर की पीढ़ी के दौरान, कुछ आवंटित किया जाता है जो किसी पृष्ठ में किसी एक मुक्त स्थान पर फिट होता है, तो पूरा पृष्ठ फोर्क प्रक्रिया में कॉपी किया जाएगा।

खिड़कियों में आप वैकल्पिक ढेर बना सकते हैं, और डिफ़ॉल्ट प्रक्रिया द्वारा उपयोग किया ढेर बदल जाते हैं। यदि यह संभव था, तो यह समस्या को हटा देगा। लिनक्स में ऐसी चीज करने का कोई तरीका है? मेरी जांच से संकेत मिलता है कि आप नहीं कर सकते हैं।

एक और संभावित समाधान होगा यदि मैं किसी भी तरह से मौजूदा मॉलोक फ्री चेन को त्याग सकता हूं, जिसके बाद मैलोक को ऑपरेटिंग सिस्टम से ताजा मेमोरी आवंटित करने के लिए मजबूर किया जा सकता है। मैंने यह देखने के लिए मॉलोक के कार्यान्वयन को देखने का प्रयास किया कि यह आसानी से संभव होगा, लेकिन ऐसा लगता है कि यह कुछ जटिल हो सकता है। अगर किसी के पास इस क्षेत्र के आसपास कोई विचार है या इस दृष्टिकोण के साथ कहां से शुरू करना है, तो मुझे यह सुनना अच्छा लगेगा।

और आखिरकार यदि किसी के पास कोई गलत विचार हो रहा है कि यहां क्या गलत हो रहा है, तो मैं वास्तव में उन्हें सुनना चाहता हूं। आपका बहुत बहुत धन्यवाद!

उत्तर

2

विंडोज़ में आप वैकल्पिक ढेर बना सकते हैं, और प्रक्रिया द्वारा उपयोग किए गए डिफ़ॉल्ट ढेर को बदल सकते हैं। यदि यह संभव था, तो यह समस्या को हटा देगा। लिनक्स में ऐसी चीज करने का कोई तरीका है?

मैं यूनिक्स आप बस mmap(2) मेमोरी एक बाईपास malloc मेमोरी कर सकते हैं।

मैं पूरी "भरोसेमंद गाय" चीज भी खो देता हूं। मेरे पास मास्टर मेमोरी mmap कुछ मेमोरी (80 एम, 150 एम जो भी हो) होगी, इसमें सामान लिखें, इसे केवल mprotect(2) के माध्यम से अच्छी तरह से पढ़ने के लिए चिह्नित करें और इसे वहां से लें। यह वास्तविक मुद्दे को हल करेगा और आपको सड़क के नीचे कोड बदलने के लिए मजबूर नहीं करेगा।

+0

मैं वास्तव में बहुत सारे काम के बिना malloc/new को बाईपास नहीं कर सकता क्योंकि यह एक बड़ा मौजूदा कोड बेस है, और हमारे सभी संसाधन लोडर काफी खुशी से उनका उपयोग करते हैं। मैं दृष्टिकोण को रद्द करने के लिए तैयार नहीं हूं, लेकिन यदि संभव हो तो मैं किसी को एल्स मेमोरी आवंटक का उपयोग करना चाहता हूं। – Negs

+1

@Negs आप कस्टम आवंटक का उपयोग कर सकते हैं या यहां तक ​​कि 'malloc' को हाइजैक भी कर सकते हैं। हालांकि, दूसरा पैराग्राफ पढ़ें। गाय पर भरोसा करना बंद करो और अपना खुद का 'mmap' करें। – cnicutar

+0

मुझे अभी भी एक कस्टम आवंटक लिखने की आवश्यकता होगी, और जब मैं इसका सहारा ले सकता हूं, तो मैं एक समाधान ढूंढना चाहता हूं जिसके लिए मुझे ऐसा करने की आवश्यकता नहीं है। संभवतः मेरी जरूरतों को सुविधाजनक बनाने के लिए मौजूदा मॉलोक के आसपास कुछ प्रकार का रैपर दृष्टिकोण? – Negs