python - पाइथन में इन्ट्स को तीन गुना अधिक स्मृति की आवश्यकता क्यों होती है?




object memory (2)

Longintrepr.h से, हम देखते हैं कि एक पाइथन 'int' ऑब्जेक्ट को इस सी संरचना के साथ परिभाषित किया गया है:

struct _longobject {
        PyObject_VAR_HEAD
        digit ob_digit[1];
};

डिजिट 32-बिट हस्ताक्षरित मान है। अंतरिक्ष का बड़ा हिस्सा परिवर्तनीय आकार ऑब्जेक्ट हेडर द्वारा लिया जाता है। Object.h से, हम इसकी परिभाषा पा सकते हैं:

typedef struct {
    PyObject ob_base;
    Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;

typedef struct _object {
    _PyObject_HEAD_EXTRA
    Py_ssize_t ob_refcnt;
    struct _typeobject *ob_type;
} PyObject;

हम देख सकते हैं कि हम मूल्य में "अंक" की गणना को संग्रहीत करने के लिए 64-बिट सिस्टम मानते हुए एक pie_ssize_t, 64-बिट्स का उपयोग कर रहे हैं। यह संभवतः अपर्याप्त है। हम यह भी देख सकते हैं कि सामान्य ऑब्जेक्ट हेडर में 64-बिट संदर्भ गणना है, और ऑब्जेक्ट प्रकार के लिए एक पॉइंटर है, जो 64-बिट स्टोरेज भी होगा। पाइथन को ऑब्जेक्ट को डिलीकेट करने के बारे में जानने के लिए संदर्भ गणना आवश्यक है, और ऑब्जेक्ट प्रकार के पॉइंटर को यह जानने के लिए जरूरी है कि हमारे पास एक स्ट्रिंग है, कहें, एक स्ट्रिंग, क्योंकि सी संरचनाओं के प्रकार का परीक्षण करने का कोई तरीका नहीं है एक मनमाना सूचक से एक वस्तु।

_PyObject_HEAD_EXTRA को अधिकांश पाइथन के निर्माण पर कुछ भी परिभाषित नहीं किया गया है, लेकिन यदि बिल्ड उस विकल्प को सक्षम करता है, तो प्रत्येक पाइथन ऑब्जेक्ट्स की एक लिंक की गई सूची को ढेर पर स्टोर करने के लिए इस्तेमाल किया जा सकता है, प्रत्येक 64-बिट्स के दो पॉइंटर्स का उपयोग करके।

64-बिट सिस्टम पर पायथन में एक पूर्णांक 24 बाइट लेता है। यह स्मृति की 3 गुणा है जिसे सी-64-बिट पूर्णांक के लिए सी में जरूरी है। अब, मुझे पता है क्योंकि यह पाइथन पूर्णांक वस्तुएं हैं। लेकिन अतिरिक्त मेमोरी के लिए क्या उपयोग किया जाता है? मेरे पास अनुमान है, लेकिन यह निश्चित रूप से जानना अच्छा लगेगा।


याद रखें कि पायथन int प्रकार में सी int की सीमित सीमा नहीं है; एकमात्र सीमा उपलब्ध स्मृति है।

मेमोरी मान को संग्रहीत करने के लिए जाता है, पूर्णांक भंडारण का वर्तमान आकार (भंडारण आकार मनमानी आकारों का समर्थन करने के लिए परिवर्तनीय है), और मानक पायथन ऑब्जेक्ट बुककीपिंग (प्रासंगिक ऑब्जेक्ट का संदर्भ और संदर्भ गणना)।

आप longintrepr.h स्रोत देख सकते हैं (पायथन 3 int प्रकार परंपरागत रूप से पाइथन 2 में long प्रकार के रूप में जाना जाता है); यह पूर्णांक आकार को ट्रैक करने के लिए PyVarObject सी प्रकार का प्रभावी उपयोग करता है:

struct _longobject {
        PyObject_VAR_HEAD
        digit ob_digit[1];
};

ob_digit सरणी 15 या 30 बिट्स चौड़े (आपके प्लेटफॉर्म के आधार पर) के 'अंक' स्टोर करता है; तो मेरे 64-बिट ओएस एक्स सिस्टम पर, एक पूर्णांक (2 ^ 30) - 1 1 'अंक' का उपयोग करता है:

>>> sys.getsizeof((1 << 30) - 1)
28

लेकिन यदि आप संख्या में 2 30-बिट अंकों का उपयोग करते हैं तो अतिरिक्त 4 बाइट की आवश्यकता होती है, आदि:

>>> sys.getsizeof(1 << 30)
32
>>> sys.getsizeof(1 << 60)
36
>>> sys.getsizeof(1 << 90)
40

बेस 24 बाइट्स तब PyObject_VAR_HEAD संरचना हैं, ऑब्जेक्ट आकार, संदर्भ गणना और टाइप पॉइंटर (मेरे 64-बिट ओएस एक्स प्लेटफ़ॉर्म पर प्रत्येक 8 बाइट्स / 64 बिट्स) को PyObject_VAR_HEAD हैं।

पायथन 2 पर, पूर्णांक <= sys.maxint लेकिन> = -sys.maxint - 1 केवल एक मान को संग्रहीत एक सरल संरचना का उपयोग करके संग्रहीत किया जाता है:

typedef struct {
    PyObject_HEAD
    long ob_ival;
} PyIntObject;

क्योंकि यह PyObject बजाय PyObject का उपयोग करता है, संरचना में कोई ob_size फ़ील्ड नहीं है और स्मृति आकार केवल 24 बाइट तक ही सीमित है; 8 long मूल्य के लिए, संदर्भ संख्या के लिए 8 और प्रकार ऑब्जेक्ट पॉइंटर के लिए 8।





python-internals