Ukuran dalam memori dari struktur Python

118

Apakah ada referensi untuk ukuran memori dari struktur data Python pada platform 32- dan 64-bit?

Jika tidak, alangkah baiknya untuk memilikinya di SO. Lebih lengkap lebih baik! Jadi berapa banyak byte yang digunakan oleh struktur Python berikut (tergantung pada lendan jenis konten jika relevan)?

  • int
  • float
  • referensi
  • str
  • string unicode
  • tuple
  • list
  • dict
  • set
  • array.array
  • numpy.array
  • deque
  • objek kelas gaya baru
  • objek kelas gaya lama
  • ... dan semua yang saya lupakan!

(Untuk wadah yang hanya menyimpan referensi ke objek lain, kami jelas tidak ingin menghitung ukuran item itu sendiri, karena mungkin dibagikan.)

Selanjutnya, adakah cara untuk mendapatkan memori yang digunakan oleh suatu objek pada saat runtime (secara rekursif atau tidak)?

LeMiz
sumber
Banyak penjelasan bermanfaat dapat ditemukan di sini stackoverflow.com/questions/1059674/python-memory-model . Saya ingin melihat gambaran umum yang lebih sistematis
LeMiz
3
Untuk array NumPy a, gunakan a.nbytes.
Akan
Jika Anda tertarik dengan tampilan grafis ini, saya membuat plotnya sekali: stackoverflow.com/a/30008338/2087463
tmthydvnprt

Jawaban:

145

Rekomendasi dari pertanyaan sebelumnya tentang ini adalah menggunakan sys.getsizeof () , mengutip:

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

Anda bisa mengambil pendekatan ini:

>>> 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

01-08-2016

OSX, Python 2.7.10 (default, 23 Okt 2015, 19:19:21) [GCC 4.2.1 Kompatibel dengan Apple LLVM 7.0.0 (clang-700.0.59.5)] di darwin

decimal 80
dict 280
float 24
int 24
list 72
object 16
set 232
str 38
tuple 56
unicode 52
hughdbrown
sumber
1
Terima kasih, dan maaf atas penipuan untuk pertanyaan kedua ...
sayang
Saya lupa saya memiliki kotak virtual dengan ubuntu terbaru di atasnya! Aneh, sys.getsizeof (dict) bagi saya 136 (python 2.6 berjalan pada vm kubuntu, dihosting oleh OS X, jadi saya tidak yakin tentang apa pun)
LeMiz
@LeMiz: Bagi saya (Python 2.6, Windows XP SP3), sys.getsizeof (dict) -> 436; sys.getsizeof (dict ()) -> 140
John Machin
LeMiz-Kubuntu: python2.6 Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) [GCC 4.3.3] di linux2 Ketik "bantuan", "hak cipta", "kredit" atau "lisensi" untuk informasi lebih lanjut. >>> impor sys >>> sys.getsizeof (dict) 436 >>> sys.getsizeof (dict ()) 136
LeMiz
1
seharusnya tidak nilai-nilai menjadi 0, 0.0, ''dan u''untuk konsistensi?
SilentGhost
37

Saya dengan senang hati menggunakan pympler untuk tugas-tugas semacam itu. Ini kompatibel dengan banyak versi Python - asizeofmodul khususnya kembali ke 2.2!

Misalnya, menggunakan contoh hughdbrown tetapi dengan from pympler import asizeofdi awal dan print asizeof.asizeof(v)di akhir, saya melihat (sistem Python 2.5 di MacOSX 10.5):

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

Jelas ada beberapa perkiraan di sini, tetapi saya merasa sangat berguna untuk analisis dan penyetelan footprint.

Alex Martelli
sumber
1
Beberapa keingintahuan: kebanyakan dari Anda angkanya 4 lebih tinggi; objeknya adalah 0; dan desimal sekitar 4 kali lebih besar dari perkiraan Anda.
hughdbrown
1
Ya. "4 lebih tinggi" sebenarnya sebagian besar terlihat seperti "dibulatkan ke kelipatan 8" yang menurut saya benar untuk cara malloc berperilaku di sini. Tidak tahu mengapa desimal terdistorsi (dengan pympler pada 2.6, juga).
Alex Martelli
2
Sebenarnya, Anda harus menggunakan pympler.asizeof.flatsize () untuk mendapatkan fungsi yang mirip dengan sys.getsizeof (). Ada juga parameter align = yang bisa Anda gunakan (defaultnya adalah 8 seperti yang ditunjukkan Alex).
Pankrat
@AlexiHai Alex! .. Mengapa ukuran minimum sebuah char di python adalah 25 byte. >>> getsizeof('a')memberi 25dan >>> getsizeof('ab')memberi 26`
Grijesh Chauhan
1
Saya kira ukurannya dalam byte, tetapi mengapa tidak ditulis di mana pun, bahkan di pythonhosted.org/Pympler
Zhomart
35

Semua jawaban ini mengumpulkan informasi berukuran dangkal. Saya menduga bahwa pengunjung pertanyaan ini akan berakhir di sini untuk menjawab pertanyaan, "Seberapa besar benda kompleks ini dalam ingatan?"

Ada jawaban bagus disini: https://goshippo.com/blog/measure-real-size-any-python-object/

Bagian lucunya:

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

Digunakan seperti ini:

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

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

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

Jika Anda ingin mengetahui model memori Python lebih dalam, ada artikel bagus di sini yang memiliki potongan kode "ukuran total" yang serupa sebagai bagian dari penjelasan yang lebih panjang: https://code.tutsplus.com/tutorials/understand-how- banyak-memori-Anda-python-objek-gunakan - cms-25609

Kobold
sumber
Jadi ini harus menghasilkan jumlah total memori yang digunakan oleh, misalnya, sebuah dict yang mengandung banyak larik dan / atau dicts lainnya?
Charly Empereur-mot
1
@ CharlyEprimer-mot ya.
Kobold
Jawaban yang bagus. Namun tampaknya tidak berfungsi untuk objek cython yang dikompilasi. Dalam kasus saya, metode ini mengembalikan 96penunjuk ke objek cython dalam memori
ferdynator
8

Coba profiler memori. profiler memori

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
Tampa
sumber
1
Presisi tampaknya 1 / 100MB, atau 10,24 byte. Ini bagus untuk analisis makro, tetapi saya ragu bahwa ketepatan seperti itu akan mengarah pada perbandingan struktur data yang akurat seperti yang ditanyakan dalam pertanyaan.
Zoran Pavlovic
7

Anda juga dapat menggunakan modul guppy .

>>> 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.>

Dan:

>>> 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
Omid Raha
sumber
0

Anda juga dapat menggunakan tracemallocmodul dari pustaka standar Python. Tampaknya berfungsi dengan baik untuk objek yang kelasnya diimplementasikan dalam C (tidak seperti Pympler, misalnya).

zahypeti.dll
sumber
-1

Saat Anda menggunakan fungsi dir([object])built-in, Anda bisa mendapatkan __sizeof__fungsi built-in.

>>> a = -1
>>> a.__sizeof__()
24
halo_god
sumber