यह "सुविधा" कहीं और नहीं देखी गई। मुझे पता है कि 32 वें बिट का उपयोग कचरा संग्रहण के लिए किया जाता है। लेकिन ऐसा क्यों है कि केवल किलों के लिए और अन्य बुनियादी प्रकारों के लिए नहीं?
यह "सुविधा" कहीं और नहीं देखी गई। मुझे पता है कि 32 वें बिट का उपयोग कचरा संग्रहण के लिए किया जाता है। लेकिन ऐसा क्यों है कि केवल किलों के लिए और अन्य बुनियादी प्रकारों के लिए नहीं?
जवाबों:
इसे टैग किए गए पॉइंटर प्रतिनिधित्व कहा जाता है , और दशकों के लिए कई अलग-अलग दुभाषियों, वीएम और रनटाइम सिस्टम में उपयोग किया जाने वाला एक बहुत ही सामान्य अनुकूलन चाल है। बहुत ज्यादा हर लिस्प कार्यान्वयन में उनका उपयोग होता है, कई स्मॉलटॉक वीएम, कई रूबी दुभाषिया, और इसी तरह।
आमतौर पर, उन भाषाओं में, आप हमेशा पॉइंटर्स टू ऑब्जेक्ट्स से गुजरते हैं। एक ऑब्जेक्ट में ही एक ऑब्जेक्ट हेडर होता है, जिसमें ऑब्जेक्ट मेटाडेटा होता है (जैसे ऑब्जेक्ट का प्रकार, उसका वर्ग (तों), शायद नियंत्रण प्रतिबंध या सुरक्षा एनोटेशन और इतने पर पहुंच), और फिर वास्तविक ऑब्जेक्ट डेटा ही। तो, एक साधारण पूर्णांक को एक सूचक के रूप में दर्शाया जाएगा और एक वस्तु जो मेटाडेटा और वास्तविक पूर्णांक से मिलकर बनेगी। यहां तक कि बहुत कॉम्पैक्ट प्रतिनिधित्व के साथ, यह एक साधारण पूर्णांक के लिए 6 बाइट की तरह कुछ है।
इसके अलावा, आप तेजी से पूर्णांक अंकगणितीय प्रदर्शन करने के लिए सीपीयू में इस तरह के पूर्णांक ऑब्जेक्ट को पास नहीं कर सकते हैं। यदि आप दो पूर्णांक जोड़ना चाहते हैं, तो आपके पास वास्तव में केवल दो बिंदु होते हैं, जो उन दो पूर्णांक ऑब्जेक्ट्स के ऑब्जेक्ट हेडर की शुरुआत को इंगित करते हैं जिन्हें आप जोड़ना चाहते हैं। तो, आपको पहले पूर्णांक पर पूर्णांक अंकगणितीय प्रदर्शन करने की आवश्यकता है, जिससे ऑब्जेक्ट में ऑफसेट को जोड़ने के लिए जहां पूर्णांक डेटा संग्रहीत किया जाता है। फिर आपको उस पते पर दखल देना होगा। दूसरे पूर्णांक के साथ फिर से वही करें। अब आपके पास दो पूर्णांक हैं आप वास्तव में सीपीयू को जोड़ने के लिए कह सकते हैं। बेशक, अब आपको परिणाम धारण करने के लिए एक नए पूर्णांक ऑब्जेक्ट का निर्माण करने की आवश्यकता है।
तो, एक पूर्णांक जोड़ के प्रदर्शन के लिए , आपको वास्तव में तीन पूर्णांक जोड़ और दो सूचक व्युत्पन्न प्लस ऑब्जेक्ट ऑब्जेक्ट निर्माण करने की आवश्यकता है। और आप लगभग 20 बाइट लेते हैं।
हालांकि, चाल यह है कि पूर्णांक जैसे तथाकथित अपरिवर्तनीय मूल्य प्रकारों के साथ, आपको आमतौर पर ऑब्जेक्ट हेडर में सभी मेटाडेटा की आवश्यकता नहीं होती है : आप बस उस सभी सामान को छोड़ सकते हैं, और बस इसे संश्लेषित कर सकते हैं (जो VM-nerd है- "नकली यह" के लिए बोलें), जब कोई भी देखने के लिए परवाह करता है। पूर्णांक में हमेशा कक्षा होगी Integer
, उस जानकारी को अलग से संग्रहीत करने की कोई आवश्यकता नहीं है। यदि कोई किसी पूर्णांक के वर्ग का पता लगाने के लिए प्रतिबिंब का उपयोग करता है, तो आप बस उत्तर देते हैं Integer
और कोई भी कभी भी नहीं जान पाएगा कि आपने वास्तव में उस जानकारी को ऑब्जेक्ट हेडर में संग्रहीत नहीं किया है और वास्तव में, ऑब्जेक्ट हेडर (या नहीं) भी नहीं है वस्तु)।
तो, चाल मान संग्रहीत है की सूचक के भीतर वस्तु के लिए , वस्तु को प्रभावी ढंग से एक में दो गिर।
सीपीयू हैं जो वास्तव में एक पॉइंटर (तथाकथित टैग बिट्स ) के भीतर अतिरिक्त स्थान रखते हैं जो आपको पॉइंटर के बारे में पॉइंटर के बारे में अतिरिक्त जानकारी संग्रहीत करने की अनुमति देते हैं। "यह वास्तव में एक सूचक नहीं है, यह पूर्णांक है" जैसी अतिरिक्त जानकारी। उदाहरणों में बरोज़ B5000, विभिन्न लिस्प मशीनें या AS / 400 शामिल हैं। दुर्भाग्य से, वर्तमान मुख्यधारा के अधिकांश सीपीयू में वह सुविधा नहीं है।
हालाँकि, वहाँ एक रास्ता है: ज्यादातर मौजूदा मुख्यधारा सीपीयू जब शब्द सीमाओं पर संरेखित नहीं होते हैं, तो काफी धीमी गति से काम करते हैं। कुछ भी अनकही पहुँच का समर्थन नहीं करते हैं।
इसका मतलब यह है कि व्यवहार में, सभी बिंदु 4 से विभाज्य होंगे, जिसका अर्थ है कि वे हमेशा दो 0
बिट्स के साथ समाप्त होंगे । यह हमें वास्तविक बिंदुओं (कि अंत में 00
) और संकेत के बीच अंतर करने की अनुमति देता है जो वास्तव में भेस में पूर्णांक हैं (जो अंत में समाप्त होते हैं 1
)। और यह अभी भी हमें सभी बिंदुओं के साथ छोड़ देता है जो 10
अन्य सामान करने के लिए स्वतंत्र रूप से समाप्त होते हैं। इसके अलावा, अधिकांश आधुनिक ऑपरेटिंग सिस्टम खुद के लिए बहुत कम पते आरक्षित करते हैं, जो हमें एक और क्षेत्र के साथ खिलवाड़ करने के लिए देता है (संकेत जो कहते हैं, 24 0
एस और अंत के साथ शुरू होते हैं 00
)।
तो, आप एक सूचक में 31-बिट पूर्णांक को सांकेतिक शब्दों में बदलना कर सकते हैं, बस इसे 1 बिट में बाईं ओर शिफ्ट कर सकते हैं और 1
इसे जोड़ सकते हैं। और आप उन लोगों के साथ बहुत तेजी से पूर्णांक अंकगणितीय प्रदर्शन कर सकते हैं , बस उन्हें उचित रूप से स्थानांतरित करके (कभी-कभी यह भी आवश्यक नहीं है)।
हम उन अन्य पता स्थानों के साथ क्या करते हैं? ठीक है, विशिष्ट उदाहरण एन्कोडिंग शामिल float
अन्य बड़ी पता स्थान और की तरह विशेष वस्तुओं की संख्या में रों true
, false
, nil
, 127 ASCII वर्ण, कुछ आमतौर पर इस्तेमाल किया संक्षिप्त स्ट्रिंग, खाली सूची, खाली वस्तु, खाली सरणी और इतने पर के पास 0
पता।
उदाहरण के लिए, MRI, YARV और रूबिनस रूबी दुभाषियों में, पूर्णांकों को मेरे द्वारा वर्णित तरीके false
से एन्कोड किया जाता है, पते के रूप में एन्कोडेड किया जाता है 0
(जो कि ऐसा ही होता है, C में इसका प्रतिनिधित्व भी होता false
है), true
पते के रूप में 2
(जो कि बस होता है) सी true
) एक बिट द्वारा स्थानांतरित कर दिया) और के nil
रूप में 4
।
int
।
एक अच्छे वर्णन के लिए https://ocaml.org/learn/tutorials/performance_and_profiling.html के अनुभाग में "पूर्णांक, टैग बिट्स, हीप-आबंटित मानों का प्रतिनिधित्व" देखें ।
संक्षिप्त उत्तर यह है कि यह प्रदर्शन के लिए है। किसी फ़ंक्शन के तर्क को पास करते समय इसे या तो पूर्णांक या पॉइंटर के रूप में पास किया जाता है। मशीन स्तर की भाषा के स्तर पर यह बताने का कोई तरीका नहीं है कि क्या एक रजिस्टर में एक पूर्णांक या एक सूचक है, यह सिर्फ एक 32 या 64% मूल्य है। तो OCaml चलाने का समय यह निर्धारित करने के लिए टैग बिट की जाँच करता है कि उसे क्या प्राप्त हुआ था एक पूर्णांक या एक सूचक। यदि टैग बिट सेट है, तो मान एक पूर्णांक है और इसे सही अधिभार के लिए पारित किया गया है। अन्यथा यह एक पॉइंटर है और इसके प्रकार को देखा जाता है।
केवल पूर्णांकों के पास यह टैग क्यों है? क्योंकि बाकी सब कुछ एक पॉइंटर के रूप में पास किया जाता है। जो पास किया गया है वह या तो एक पूर्णांक या कुछ अन्य डेटा प्रकार के लिए एक संकेतक है। केवल एक टैग बिट के साथ, केवल दो मामले हो सकते हैं।
यह वास्तव में "कचरा संग्रहण के लिए उपयोग नहीं किया जाता है।" इसका उपयोग आंतरिक रूप से एक सूचक और एक अनबॉक्स किए गए पूर्णांक के बीच अंतर करने के लिए किया जाता है।
मुझे 64-बिट OCaml के लिए 63-बिट फ़्लोटिंग-पॉइंट प्रकार को समझने के लिए ओपी की मदद करने के लिए इस लिंक को जोड़ना होगा
यद्यपि लेख का शीर्षक float
इसके बारे में लगता है , यह वास्तव में बात कर रहा हैextra 1 bit
OCaml रनटाइम प्रकार के समान प्रतिनिधित्व के माध्यम से बहुरूपता की अनुमति देता है। प्रत्येक OCaml मान को एक एकल शब्द के रूप में दर्शाया जाता है, ताकि "चीजों की सूची", जैसे कि (जैसे List.length) को एक्सेस करने और इन सूचियों को बनाने (जैसे List.map) का निर्माण करने के लिए एक ही कार्यान्वयन के लिए संभव हो, यह वही काम करता है, चाहे वे किलों की सूची, फ़्लोट्स की, या पूर्णांकों के सेटों की सूचियाँ हों।
जो कुछ भी एक शब्द में फिट नहीं होता है वह ढेर में एक ब्लॉक में आवंटित किया जाता है। इस डेटा का प्रतिनिधित्व करने वाला शब्द तब ब्लॉक का एक संकेतक है। चूंकि ढेर में केवल शब्दों के ब्लॉक होते हैं, इन सभी बिंदुओं को संरेखित किया जाता है: उनके कम से कम महत्वपूर्ण बिट्स हमेशा परेशान होते हैं।
तर्कहीन निर्माणकर्ता (इस तरह: प्रकार फल = सेब | नारंगी | केला) और पूर्णांक इतनी जानकारी का प्रतिनिधित्व नहीं करते हैं कि उन्हें ढेर में आवंटित करने की आवश्यकता है। उनका प्रतिनिधित्व अनबॉक्स है। डेटा सीधे शब्द के अंदर होता है जो अन्यथा एक संकेतक होता। इसलिए जबकि सूचियों की एक सूची वास्तव में संकेतकर्ताओं की सूची है, सूची की सूची में एक कम अप्रत्यक्षता के साथ ints शामिल हैं। सूचियों तक पहुँचने और निर्माण करने वाले कार्यों पर ध्यान नहीं जाता है क्योंकि इन्ट्स और पॉइंटर्स का आकार समान होता है।
फिर भी, गारबेज कलेक्टर को पूर्णांक से संकेत पहचानने में सक्षम होना चाहिए। एक सूचक ढेर में एक अच्छी तरह से गठित ब्लॉक को इंगित करता है जो कि परिभाषा के अनुसार है (क्योंकि यह जीसी द्वारा दौरा किया जा रहा है) और इसे चिह्नित किया जाना चाहिए। एक पूर्णांक का कोई भी मूल्य हो सकता है और अगर सावधानी नहीं बरती गई, तो गलती से एक पॉइंटर की तरह दिख सकता है। यह जिंदा दिखने के लिए मृत ब्लॉक का कारण बन सकता है, लेकिन इससे भी बदतर, यह जीसी को बिट्स को बदलने का कारण होगा, जो इसे लगता है कि लाइव ब्लॉक का हेडर है, जब यह वास्तव में एक पूर्णांक का अनुसरण कर रहा है जो एक संकेतक की तरह दिखता है और उपयोगकर्ता को गड़बड़ कर रहा है। डेटा।
यही कारण है कि अनबॉक्सेड पूर्णांक OCaml प्रोग्रामर को 31 बिट्स (32-बिट OCaml के लिए) या 63 बिट्स (64-बिट OCaml के लिए) प्रदान करते हैं। प्रतिनिधित्व में, पर्दे के पीछे, पूर्णांक वाले किसी शब्द का कम से कम महत्वपूर्ण बिट हमेशा एक सूचक से अलग करने के लिए निर्धारित होता है। 31- या 63-बिट पूर्णांक बल्कि असामान्य हैं, इसलिए जो कोई भी OCaml का उपयोग करता है वह यह सब जानता है। OCaml के उपयोगकर्ताओं को आमतौर पर पता नहीं होता है कि 64-बिट OCaml के लिए 63-बिट अनबॉक्स फ्लोट प्रकार क्यों नहीं है।
OCaml में केवल 31 बिट्स में इंट क्यों है?
मूल रूप से, कोक प्रमेय प्रोवर पर सर्वश्रेष्ठ संभव प्रदर्शन प्राप्त करने के लिए जहां प्रमुख ऑपरेशन पैटर्न मिलान है और प्रमुख डेटा प्रकार भिन्न प्रकार हैं। सर्वश्रेष्ठ डेटा प्रतिनिधित्व को एक समान प्रतिनिधित्व के रूप में पाया गया था जो अनबॉक्स किए गए डेटा से पॉइंटर्स को अलग करने के लिए टैग का उपयोग करता है।
लेकिन ऐसा क्यों है कि केवल किलों के लिए और अन्य बुनियादी प्रकारों के लिए नहीं?
ही नहीं int
। अन्य प्रकार जैसे कि char
और enums समान टैग किए गए प्रतिनिधित्व का उपयोग करते हैं।