2013-10-18 17 views
15

पर अनावश्यक स्टैक्स वहाँ वहाँ बाहर है कि एक "विभाजित ढेर" क्रम मॉडल का उपयोग कर 64-बिट आर्किटेक्चर पर अनावश्यक है एक राय हो रहा है। मैं हो रहा है कहते हैं, क्योंकि मैंने नहीं देखा है किसी को भी वास्तव में कहना है कि, इसके चारों ओर केवल नृत्य:स्प्लिट amd64

एक ठेठ मल्टी-थ्रेडेड कार्यक्रम की स्मृति उपयोग काफी कम कर सकते हैं, के रूप में प्रत्येक थ्रेड एक की आवश्यकता नहीं है सबसे खराब केस स्टैक आकार। 32-बिट एड्रेस स्पेस में लाखों धागे (या तो पूर्ण एनपीटीएल धागे या सह-दिनचर्या) चलाने के लिए संभव हो जाता है। - Ian Lance Taylor

... जिसका अर्थ है कि एक 64-बिट पता स्थान पहले से ही इसे संभाल कर सकते हैं।

और ...

... विभाजन के ढेर की लगातार भूमि के ऊपर और संकीर्ण उपयोग के मामले (आई/ओ बाध्य कार्यों की भारी संख्या को उत्पन्न करने के 32-बिट आर्किटेक्चर पर) नहीं है स्वीकार्य ... - bstrie

दो सवाल: वे क्या कह रहे हैं यह है? दूसरा, यदि हां, तो वे 64-बिट आर्किटेक्चर पर अनावश्यक क्यों हैं?

उत्तर

19

हाँ, कि वे क्या कह रहे हैं।

स्प्लिट स्टैक्स 64 बिट आर्किटेक्चर पर अनावश्यक हैं (क्योंकि वर्तमान में 64 बिट वर्चुअल एड्रेस स्पेस इतनी बड़ी है कि इसमें लाखों स्टैक एड्रेस रेंज शामिल हो सकती हैं, यदि आवश्यक हो तो प्रत्येक 32 बिट एड्रेस स्पेस के रूप में बड़ा हो सकता है।

Flat memory model में आजकल उपयोग में, वर्चुअल पतों से फ़िशिकल मेमोरी स्थानों का अनुवाद hardware MMU के समर्थन से किया जाता है। amd64 पर यह पता चला है यह बेहतर है (जिसका अर्थ है, कुल मिलाकर तेजी से), प्रत्येक नए स्टैक आप बना रहे हैं करने के लिए 64 बिट वर्चुअल ऐड्रेस स्पेस का बड़ा हिस्सा आरक्षण जबकि केवल वास्तविक रैम को पहले पृष्ठ (4kB) मानचित्रण। इस तरह, स्टैक आवश्यक वर्चुअल पतों (प्रत्येक function prologue में एक बड़ा अनुकूलन) में आवश्यक कोड के रूप में आवश्यक रूप से बढ़ने और घटने में सक्षम हो जाएगा, जबकि ओएस वर्चुअल पतों के प्रत्येक पृष्ठ को वास्तविक रूप से मैप करने के लिए एमएमयू को फिर से कॉन्फ़िगर करता है रैम का पृष्ठ, जब भी ढेर कुछ कॉन्फ़िगर करने योग्य थ्रेसहोल्ड के ऊपर/नीचे बढ़ता है या नीचे गिर जाता है।

थ्रेसहोल्ड को चतुराई से चुनकर (उदाहरण के लिए dynamic arrays का सिद्धांत देखें) आप औसत स्टैक ऑपरेशन पर ओ (1) जटिलता प्राप्त कर सकते हैं, जबकि लाखों स्टैक के लाभों को बनाए रखते हुए जो आपको चाहिए उतना ही बढ़ सकता है और केवल वे उपयोग की स्मृति का उपभोग करें।

पुनश्च: वर्तमान जाओ कार्यान्वयन तक इस :-) के किसी भी पीछे है

+0

सैद्धांतिक अधिकतम ढेर आकार कैसे परिभाषित किया गया है? – thwd

+2

यह परिभाषित नहीं है, यह सिर्फ भाषा या कंपाइलर का विकल्प है। मुझे और स्पष्ट होना चाहिए था, मैं इसे संपादित कर दूंगा। – Tobia

9

जाओ कोर टीम वर्तमान में discussing एक भविष्य जाओ संस्करण में सन्निहित ढेर उपयोग करने की संभावना है।

विभाजन ढेर दृष्टिकोण से उपयोगी है क्योंकि ढेर अधिक लचीलेपन बढ़ सकता है, लेकिन यह भी जरूरी है कि क्रम स्मृति की एक अपेक्षाकृत बड़ा हिस्सा आवंटित भर में इन ढेर वितरित करने के लिए। इस वजह से गो के मेमोरी उपयोग के बारे में confusion बहुत सारे हैं।

सन्निहित लेकिन उगने वाली दाढ़ी (पुनर्निधारणीय) बनाना स्टैक्स एक विकल्प है कि एक ही लचीलापन प्रदान करेगा और शायद जाओ की स्मृति उपयोग के बारे में भ्रम की स्थिति को कम है। कम स्मृति मशीनों पर कुछ बीमार कोने-मामलों का उपचार करने के साथ-साथ लिंक किए गए धागे को देखें।

32-बिट बनाम 64-बिट आर्किटेक्चर पर फायदे/नुकसान के रूप में, मुझे नहीं लगता कि खंडित ढेर के उपयोग के साथ पूरी तरह से सीधे जुड़े हुए हैं।

2

अद्यतन जाओ 1.4 (Q4 2014)

Change to the runtime:

1,4, क्रम (जाने के लिए ऊपर कचरा कलेक्टर, समवर्ती समर्थन, इंटरफ़ेस प्रबंधन, मानचित्र, स्लाइस, तार, ...) ज्यादातर असेंबलर समर्थन के साथ सी में लिखा गया था।
1.4, में से अधिकांश कोड का अनुवाद करने के लिए अनुवाद किया गया है ताकि कचरा कलेक्टर रनटाइम में प्रोग्राम के ढेर को स्कैन कर सके और चर के सक्रिय होने के बारे में सटीक जानकारी प्राप्त कर सकें

यह पुनर्लेखन कचरा कलेक्टर 1.4 में पूरी तरह से सटीक होने की अनुमति देता है, जिसका अर्थ है कि यह प्रोग्राम में सभी सक्रिय पॉइंटर्स के स्थान से अवगत है। इसका मतलब है कि ढेर छोटा होगा क्योंकि गैर-पॉइंटर्स को जीवित रखने के लिए कोई झूठी सकारात्मक नहीं होगी। अन्य संबंधित परिवर्तन भी ढेर आकार को कम करते हैं, जो पिछले रिलीज के कुल सापेक्ष 10% -30% से कम है।

एक परिणाम यह है कि "गर्म विभाजन" समस्या को समाप्त करने के लिए ढेर को विभाजित नहीं किया जाता है। जब एक स्टैक सीमा तक पहुंच जाती है, तो एक नया, बड़ा ढेर आवंटित किया जाता है, गोरौटाइन के लिए सभी सक्रिय फ्रेम वहां कॉपी किए जाते हैं, और स्टैक में किसी भी पॉइंटर्स को अपडेट किया जाता है।


प्रारंभिक जवाब (मार्च 2014)

लेख "Contiguous stacks in Go" Agis Anastasopoulo से भी इस मुद्दे को संबोधित

इस तरह के मामलों में जहां ढेर सीमा एक तंग पाश में गिर करने के लिए होता में , सेगमेंट बनाने और नष्ट करने का ओवरहेड बार-बार महत्वपूर्ण हो जाता है।
इसे गो समुदाय के अंदर "हॉट स्प्लिट" समस्या कहा जाता है।

संगत स्टैक्स को लागू करके "हॉट स्प्लिट" को गो 1.3 में संबोधित किया जाएगा।

अब जब एक ढेर विकसित करने के लिए, के बजाय एक नया सेगमेंट निम्न होता आवंटन की जरूरत है:

  1. एक नया, कुछ बड़े ढेर
  2. कॉपी बनाएं नए स्टैक
  3. करने के लिए पुराने ढेर की सामग्री
  4. नए पते पर भेजने के लिए हर की नकल की सूचक फिर से समायोजित
  5. वर्ष ढेर को नष्ट

निम्नलिखित उल्लेख एक समस्या 32-बिट arhcitectures में मुख्य रूप से देखी गई:

एक निश्चित चुनौती हालांकि नहीं है।
1.2 रनटाइम यह नहीं जानता कि स्टैक में एक पॉइंटर आकार का शब्द वास्तविक सूचक है या नहीं है। वहां फ्लोट्स और शायद ही कभी पूर्णांक हो सकते हैं जो पॉइंटर्स के रूप में व्याख्या किए जाते हैं, वास्तव में डेटा को इंगित करेंगे।

ऐसे ज्ञान की कमी के कारण कचरा कलेक्टर को स्टैक फ्रेम में सभी स्थानों को जड़ें मानने के लिए रूढ़िवादी रूप से विचार करना पड़ता है। यह विशेष रूप से 32-बिट आर्किटेक्चर पर मेमोरी लीक की संभावना छोड़ देता है क्योंकि उनका पता पूल बहुत छोटा है।

हालांकि ढेर की प्रतिलिपि करते समय, ऐसे मामलों से बचा जाना चाहिए और केवल फिर से समायोजन करते समय वास्तविक पॉइंटर्स को ध्यान में रखा जाना चाहिए।

Work was done though और information about live stack pointers अब बाइनरी में एम्बेडेड है और रनटाइम पर उपलब्ध है।
इसका मतलब यह नहीं है कि 1.3 में संग्राहक precisely डेटा ढेर कर सकता है लेकिन स्टैक पॉइंटर्स को फिर से समायोजित करना संभव है।