Эстекти башкаруу жана таштандыны чогултуу
CPython аткаруу учурунда объекттерди кантип бөлүштүрөт, көзөмөлдөйт жана бошотот
- шилтемелерди эсептөө объекттин качан бошотуларын кантип чечерин жана эмне үчүн
sys.getrefcountар дайым бирге көбүрөөк көрсөтөрүн түшүндүрүү; - циклдик шилтемелер таза эсептөөнү кантип айланып өтөрүн жана муундук чогултуучу аларды кантип бошотоорун сүрөттөө;
- объектти тирүү кармабай туруп аны байкоо же кэштөө үчүн
weakrefколдонуу; - классикалык
__del__катачылыктарынан (кайра тирилтүү, циклдердеги белгисиз иреттик, аяктоо) качуу; tracemalloc,gcжанаsys.getsizeofменен күтүлбөгөн эстек өсүшүн диагноздоо.
Бул тема сиз Python объект моделин — өткөн темадан идентификация, өзгөрүлмөлүүлүк жана көчүрүү семантикасын — мурунтан билесиз деп болжолдойт. Бул жерде биз бир деңгээл тереңге, ошол объекттерди тирүү кармаган аткаруу машинериясына түшөбүз.
1. Шилтемелерди эсептөө: негизги механизм
CPython түзгөн ар бир объект ob_refcnt деген кичине бүтүн сандык талааны алып жүрөт, ал ага азыр канча шилтеме көрсөтүп турганын эсептейт. Ат байлоо, тизмеге кошуу, аргумент өткөрүү — булардын ар бири эсептегичке бирди кошот; атты өчүрүү, аны кайра байлоо же көрүнүү аймагынан чыгуу бирди кемитет. Эреже так жана заматта: эсептегич нөлгө жеткен заматта объект бошотулат, анын __del__ (эгер бар болсо) иштейт жана өзүнүн шилтемелери бошотулат — бул каскад менен дагы көбүрөөк объектти бошото алат.
import sys
a = [10, 20, 30] # тизме-объектте азыр бир шилтеме бар: 'a'
b = a # ОШОЛ ЭЛЕ объектке экинчи шилтеме
print(sys.getrefcount(a)) # 3 (a, b жана getrefcount'тун өз аргументи)
del b # бир шилтеме жоголду
print(sys.getrefcount(a)) # 2 (a жана аргумент)
del a # акыркы чыныгы шилтеме жоголду -> эсептегич -> 0 -> азыр бошотулду
Ушул себептен CPython эстектин көбүн детерминдүү жана тез, «дүйнөнү токтотуу» тыныгуусуз бошотот: бошотуу кадимки шилтеме эсебине өрүлгөн. Ошондой эле контекст менеджери жапкан файл with блогу аяктап, анын акыркы шилтемеси жоголор замат дароо бошотулат.