Bir Python yapısının bellek içi boyutu


118

32 ve 64 bit platformlarda Python veri yapısının bellek boyutu için bir referans var mı?

Değilse, SO'da olması güzel olurdu. Ne kadar kapsamlı olursa o kadar iyidir! Öyleyse aşağıdaki Python yapıları tarafından kaç bayt kullanılıyor ( lenilgili olduğunda içerik türüne ve içeriğine bağlı olarak )?

  • int
  • float
  • referans
  • str
  • unicode dizesi
  • tuple
  • list
  • dict
  • set
  • array.array
  • numpy.array
  • deque
  • yeni stil sınıflar nesnesi
  • eski stil sınıflar nesnesi
  • ... ve unuttuğum her şey!

(Yalnızca diğer nesnelere referansları tutan kaplar için, paylaşılabileceği için öğenin boyutunu saymak istemiyoruz.)

Ayrıca, çalışma zamanında bir nesne tarafından kullanılan belleği elde etmenin bir yolu var mı (özyinelemeli veya değil)?


Stackoverflow.com/questions/1059674/python-memory-model'de pek çok yararlı açıklama bulunabilir . Yine de daha sistematik bir genel bakış görmek istiyorum
LeMiz

3
NumPy dizisi aiçin a.nbytes.
Will

Bunun grafiksel bir görünümüyle ilgileniyorsanız, bir kez bir taslağı hazırladım: stackoverflow.com/a/30008338/2087463
tmthydvnprt

Yanıtlar:


145

Dan öneri önceki bir soruya bu konuda kullanmaktı ) (sys.getsizeof alıntı:

>>> import sys
>>> x = 2
>>> sys.getsizeof(x)
14
>>> sys.getsizeof(sys.getsizeof)
32
>>> sys.getsizeof('this')
38
>>> sys.getsizeof('this also')
48

Bu yaklaşımı benimseyebilirsiniz:

>>> import sys
>>> import decimal
>>> 
>>> d = {
...     "int": 0,
...     "float": 0.0,
...     "dict": dict(),
...     "set": set(),
...     "tuple": tuple(),
...     "list": list(),
...     "str": "a",
...     "unicode": u"a",
...     "decimal": decimal.Decimal(0),
...     "object": object(),
... }
>>> for k, v in sorted(d.iteritems()):
...     print k, sys.getsizeof(v)
...
decimal 40
dict 140
float 16
int 12
list 36
object 8
set 116
str 25
tuple 28
unicode 28

2012/09/30

python 2.7 (linux, 32-bit):

decimal 36
dict 136
float 16
int 12
list 32
object 8
set 112
str 22
tuple 24
unicode 32

python 3.3 (linux, 32-bit)

decimal 52
dict 144
float 16
int 14
list 32
object 8
set 112
str 26
tuple 24
unicode 26

2016/08/01

OSX, Python 2.7.10 (varsayılan, 23 Ekim 2015, 19:19:21) [GCC 4.2.1 Uyumlu Apple LLVM 7.0.0 (clang-700.0.59.5)] darwin'de

decimal 80
dict 280
float 24
int 24
list 72
object 16
set 232
str 38
tuple 56
unicode 52

1
Teşekkürler ve ikinci soru için özür dilerim ... çok kötü 2.5 kullanıyorum, 2.6 değil ...
LeMiz

Üzerinde yeni bir ubuntu bulunan sanal bir kutum olduğunu unuttum! Bu garip, sys.getsizeof (dict) benim için 136 (python 2.6, OS X tarafından barındırılan bir kubuntu sanal makinede çalışıyor, bu yüzden hiçbir şeyden emin değilim)
LeMiz 25.09.2019

@LeMiz: Benim için (Python 2.6, Windows XP SP3), sys.getsizeof (dict) -> 436; sys.getsizeof (dict ()) -> 140
John Machin

LeMiz-Kubuntu: python2.6 Python 2.6.2 (sürüm26-bakım, 19 Nisan 2009, 01:56:41) [GCC 4.3.3] linux2'de "yardım", "telif hakkı", "kredi" veya "lisans" yazın daha fazla bilgi için. >>> import sys >>> sys.getsizeof (dict) 436 >>> sys.getsizeof (dict ()) 136
LeMiz

1
değerleri olmamalı 0, 0.0, ''ve u''tutarlılık için?
SilentGhost

37

Bu tür görevler için mutlu bir şekilde pympler kullanıyorum . Python'un birçok sürümüyle uyumludur - asizeofözellikle modül 2.2'ye geri döner!

Örneğin, hughdbrown örneğini kullanarak ama from pympler import asizeofbaşında ve print asizeof.asizeof(v)sonunda görüyorum (MacOSX 10.5'te Python 2.5 sistemi):

$ python pymp.py 
set 120
unicode 32
tuple 32
int 16
decimal 152
float 16
list 40
object 0
dict 144
str 32

Açıkçası burada bazı yaklaşımlar var, ancak ayak izi analizi ve ayarlaması için çok yararlı buldum.


1
Bazı merak edilenler: çoğunuz sayılardan 4 daha fazla; nesne 0'dır; ve ondalık sayı, tahmininize göre yaklaşık 4 kat daha büyüktür.
hughdbrown

1
Evet. "4 daha yüksek" aslında "8'in katlarına yuvarlanıyor" gibi görünüyor ki bu malloc'un burada davranış şekli için doğru olduğuna inanıyorum. Ondalığın neden bu kadar bozulduğu hakkında hiçbir fikrim yok (2.6'daki pympler ile de).
Alex Martelli

2
Aslında, sys.getsizeof () işlevine benzer bir işlevsellik elde etmek için pympler.asizeof.flatsize () kullanmalısınız. Ayrıca kullanabileceğiniz bir align = parametresi vardır (Alex'in belirttiği gibi varsayılan olarak 8'dir).
Pankrat

@AlexMartelli Merhaba Alex! .. Python'da neden minimum karakter boyutu 25 bayttır? >>> getsizeof('a')verir 25ve >>> getsizeof('ab')verir 26``
Grijesh Chauhan

1
Hatta pythonhosted.org/Pympler içinde, ben varsayalım boyutu bayt cinsinden, ama neden hiçbir yerde yazılı değil
Zhomart

35

Bu cevapların tümü sığ boyut bilgisi toplar. Bu soruyu ziyaret edenlerin burada, "Hafızadaki bu karmaşık nesne ne kadar büyük?" Sorusuna cevap arayacaklarından şüpheleniyorum.

Burada harika bir cevap var: https://goshippo.com/blog/measure-real-size-any-python-object/

Yumruk hattı:

import sys

def get_size(obj, seen=None):
    """Recursively finds size of objects"""
    size = sys.getsizeof(obj)
    if seen is None:
        seen = set()
    obj_id = id(obj)
    if obj_id in seen:
        return 0
    # Important mark as seen *before* entering recursion to gracefully handle
    # self-referential objects
    seen.add(obj_id)
    if isinstance(obj, dict):
        size += sum([get_size(v, seen) for v in obj.values()])
        size += sum([get_size(k, seen) for k in obj.keys()])
    elif hasattr(obj, '__dict__'):
        size += get_size(obj.__dict__, seen)
    elif hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes, bytearray)):
        size += sum([get_size(i, seen) for i in obj])
    return size

Öyle kullanılır:

In [1]: get_size(1)
Out[1]: 24

In [2]: get_size([1])
Out[2]: 104

In [3]: get_size([[1]])
Out[3]: 184

Python'un bellek modelini daha derinlemesine bilmek istiyorsanız, burada daha uzun bir açıklamanın parçası olarak benzer bir "toplam boyut" kod parçacığı içeren harika bir makale var: https://code.tutsplus.com/tutorials/understand-how- çok-hafıza-your-python-nesneler kullanımlık - cms-25609


Öyleyse bu, örneğin birden çok dizi ve / veya diğer dikteler içeren bir diktede kullanılan toplam bellek miktarını vermelidir?
Charly Empereur-mot

1
@ CharlyEmpereur-mot evet.
Kobold

Mükemmel cevap. Ancak derlenmiş cython nesneleri için işe yaramıyor gibi görünüyor. Benim durumumda bu yöntem 96bellek içi bir
cython

8

Bellek profilleyiciyi deneyin. bellek profili oluşturucu

Line #    Mem usage  Increment   Line Contents
==============================================
     3                           @profile
     4      5.97 MB    0.00 MB   def my_func():
     5     13.61 MB    7.64 MB       a = [1] * (10 ** 6)
     6    166.20 MB  152.59 MB       b = [2] * (2 * 10 ** 7)
     7     13.61 MB -152.59 MB       del b
     8     13.61 MB    0.00 MB       return a

1
Kesinlik 1 / 100MB veya 10.24 bayt gibi görünüyor. Bu makro analiz için iyidir, ancak böyle bir kesinliğin, soruda sorulan veri yapılarının doğru bir şekilde karşılaştırılmasına yol açacağından şüpheliyim.
Zoran Pavlovic

7

Ayrıca lepistes modülünü de kullanabilirsiniz .

>>> from guppy import hpy; hp=hpy()
>>> hp.heap()
Partition of a set of 25853 objects. Total size = 3320992 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0  11731  45   929072  28    929072  28 str
     1   5832  23   469760  14   1398832  42 tuple
     2    324   1   277728   8   1676560  50 dict (no owner)
     3     70   0   216976   7   1893536  57 dict of module
     4    199   1   210856   6   2104392  63 dict of type
     5   1627   6   208256   6   2312648  70 types.CodeType
     6   1592   6   191040   6   2503688  75 function
     7    199   1   177008   5   2680696  81 type
     8    124   0   135328   4   2816024  85 dict of class
     9   1045   4    83600   3   2899624  87 __builtin__.wrapper_descriptor
<90 more rows. Type e.g. '_.more' to view.>

Ve:

>>> hp.iso(1, [1], "1", (1,), {1:1}, None)
Partition of a set of 6 objects. Total size = 560 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1  17      280  50       280  50 dict (no owner)
     1      1  17      136  24       416  74 list
     2      1  17       64  11       480  86 tuple
     3      1  17       40   7       520  93 str
     4      1  17       24   4       544  97 int
     5      1  17       16   3       560 100 types.NoneType

0

tracemallocPython standart kitaplığındaki modül de kullanılabilir . Sınıfı C'de uygulanan nesneler için iyi çalışıyor gibi görünüyor (örneğin Pympler'ın aksine).


-1

Yerleşik dir([object])işlevi kullandığınızda, yerleşik __sizeof__işlevden yararlanabilirsiniz.

>>> a = -1
>>> a.__sizeof__()
24
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.