दो ही वर्ण, एक == ख के साथ अजगर तार, स्मृति, आईडी (क) == आईडी (ख), साझा कर सकते हैं या दो बार स्मृति में हो सकता है, आईडी (क)! = आईडी (ख)। पाइथन समान स्ट्रिंग के लिए नई मेमोरी आवंटित करता है?
ab = "ab"
print id(ab), id("a"+"b")
यहाँ अजगर स्वीकार करता है कि नव निर्मित "एक" + "ख" एक ही "ab" पहले से ही स्मृति में के रूप में है की कोशिश करो - बुरा नहीं।
अब राज्य के नाम के एक एन-लंबी सूची पर विचार [ "एरिजोना", "अलास्का", "अलास्का", "कैलिफोर्निया" ...] (एन ~ मेरे मामले में 500000)।
मैं 50 अलग-अलग आईडी() s ⇒ प्रत्येक स्ट्रिंग "एरिजोना" देखता हूं ... केवल एक बार संग्रहीत किया जाता है, ठीक है।
लेकिन डिस्क पर सूची लिखें और इसे फिर से पढ़ें: "समान" सूची में अब एन अलग आईडी() एस है, और अधिक मेमोरी है, नीचे देखें।
कैसे आते हैं - क्या कोई पाइथन स्ट्रिंग मेमोरी आवंटन समझा सकता है?
""" when does Python allocate new memory for identical strings ?
ab = "ab"
print id(ab), id("a"+"b") # same !
list of N names from 50 states: 50 ids, mem ~ 4N + 50S, each string once
but list > file > mem again: N ids, mem ~ N * (4 + S)
"""
from __future__ import division
from collections import defaultdict
from copy import copy
import cPickle
import random
import sys
states = dict(
AL = "Alabama",
AK = "Alaska",
AZ = "Arizona",
AR = "Arkansas",
CA = "California",
CO = "Colorado",
CT = "Connecticut",
DE = "Delaware",
FL = "Florida",
GA = "Georgia",
)
def nid(alist):
""" nr distinct ids """
return "%d ids %d pickle len" % (
len(set(map(id, alist))),
len(cPickle.dumps(alist, 0))) # rough est ?
# cf http://stackoverflow.com/questions/2117255/python-deep-getsizeof-list-with-contents
N = 10000
exec("\n".join(sys.argv[1:])) # var=val ...
random.seed(1)
# big list of random names of states --
names = []
for j in xrange(N):
name = copy(random.choice(states.values()))
names.append(name)
print "%d strings in mem: %s" % (N, nid(names)) # 10 ids, even with copy()
# list to a file, back again -- each string is allocated anew
joinsplit = "\n".join(names).split() # same as > file > mem again
assert joinsplit == names
print "%d strings from a file: %s" % (N, nid(joinsplit))
# 10000 strings in mem: 10 ids 42149 pickle len
# 10000 strings from a file: 10000 ids 188080 pickle len
# Python 2.6.4 mac ppc
जोड़ा गया 25jan:
पायथन स्मृति में तार के दो प्रकार के (या किसी भी कार्यक्रम के) होते हैं:
- Ustrings अद्वितीय तार का एक Ucache में, इन स्मृति बचाने के लिए, और एक बनाने के = = बी तेज़ अगर दोनों Ucache
- शुतुरमुर्ग, अन्य हैं, जो किसी भी समय संग्रहीत किए जा सकते हैं।
intern(astring)
यूकेचे (एलेक्स +1) में अस्थिर रखता है; इसके अलावा हम कुछ भी नहीं जानते कि पाइथन ओस्ट्रिंग को यूकेचे में कैसे ले जाता है - "ए" के बाद "ए" + "बी" कैसे मिलता है? ("फाइलों से स्ट्रिंग्स" व्यर्थ है - जानने का कोई तरीका नहीं है।)
संक्षेप में, यूकेच (कई हो सकते हैं) धुंधले रहेंगे।
एक ऐतिहासिक फुटनोट: SPITBOL सभी तारों को विशिष्टता सीए। 1970
क्या मेरे उत्तर में मूल्य का कुछ भी है जो आपको नहीं लगता कि आपके भीतर शामिल है? यदि नहीं, तो मैं अपना जवाब हटा दूंगा। यदि वहां है, तो क्या आप इसे अपने में संपादित करना चाहते हैं और * फिर * मैं अपना जवाब हटा दूंगा? 'Intern' का उल्लेख करने के लिए –
+1। मैं पूरी तरह से भूल गया था कि यह कार्य अस्तित्व में था। एन में "joinsplit = [intern (n) का उपयोग करके \ n"। Join (names) .split()] 'नौकरी की और मेरे मैकबुक पर 4,374,528 से 3,190,783 तक मेमोरी उपयोग कम किया। –
@ जॉन, मुझे लगता है कि पाइथन पर एक विशेष "अंदरूनी के परिप्रेक्ष्य" के बिना एक अनुभवी प्रोग्रामर से आपका दो दृष्टिकोण (मेरा "अंदरूनी परिप्रेक्ष्य" से मेरा) मानना महत्वपूर्ण है - यह सुनिश्चित नहीं है कि यह प्राप्त करने का एक इष्टतम तरीका है एक ही जवाब में एक ही "त्रिकोण"! –