Saya ingin tahu cara mendapatkan ukuran objek seperti string, integer, dll dengan Python.
Pertanyaan terkait: Berapa banyak byte per elemen yang ada dalam daftar Python (tuple)?
Saya menggunakan file XML yang berisi bidang ukuran yang menentukan ukuran nilai. Saya harus menguraikan XML ini dan melakukan pengkodean. Ketika saya ingin mengubah nilai bidang tertentu, saya akan memeriksa bidang ukuran nilai itu. Di sini saya ingin membandingkan apakah nilai baru yang saya masukkan adalah dengan ukuran yang sama seperti dalam XML. Saya perlu memeriksa ukuran nilai baru. Dalam hal string saya bisa mengatakan panjangnya. Tetapi dalam hal int, float, dll. Saya bingung.
__sizeof__
metode untuk kelas Anda. Built-indict
kelas python tidak mendefinisikannya, itu sebabnya Anda mendapatkan hasil yang benar saat menggunakan objek tipedict
.getsizeof
fungsi bernilai kecil di luar kotak.Jawabannya, "Cukup gunakan sys.getsizeof" bukan jawaban yang lengkap.
Jawaban itu memang berfungsi untuk objek builtin secara langsung, tetapi tidak menjelaskan apa yang mungkin berisi objek-objek itu, khususnya, jenis apa, seperti objek kustom, tupel, daftar, dikt, dan set berisi. Mereka dapat berisi instance satu sama lain, serta angka, string dan objek lainnya.
Jawaban yang Lebih Lengkap
Menggunakan 64 bit Python 3.6 dari distribusi Anaconda, dengan sys.getsizeof, saya telah menentukan ukuran minimum dari objek berikut, dan perhatikan bahwa set dan dicts mengalokasikan ruang sehingga yang kosong tidak tumbuh lagi sampai setelah jumlah yang ditentukan (yang mungkin bervariasi berdasarkan implementasi bahasa):
Python 3:
Bagaimana Anda menafsirkan ini? Nah katakanlah Anda memiliki satu set dengan 10 item di dalamnya. Jika setiap item masing-masing 100 byte, seberapa besar seluruh struktur data? Set adalah 736 itu sendiri karena memiliki ukuran satu kali hingga 736 byte. Kemudian Anda menambahkan ukuran item, sehingga totalnya adalah 1736 byte
Beberapa peringatan untuk definisi fungsi dan kelas:
Perhatikan bahwa setiap definisi kelas memiliki struktur proxy
__dict__
(48 byte) untuk attr kelas. Setiap slot memiliki deskriptor (seperti aproperty
) dalam definisi kelas.Mesin Virtual Slotted memulai dengan 48 byte pada elemen pertama mereka, dan meningkat 8 masing-masing tambahan. Hanya objek slotted kosong yang memiliki 16 byte, dan sebuah instance tanpa data masuk akal sangat sedikit.
Juga, setiap definisi fungsi memiliki objek kode, mungkin dokumen, dan atribut lainnya yang mungkin, bahkan a
__dict__
.Perhatikan juga bahwa kami menggunakan
sys.getsizeof()
karena kami peduli tentang penggunaan ruang marginal, yang mencakup pengumpulan sampah di atas objek, dari dokumen :Perhatikan juga bahwa mengubah ukuran daftar (misalnya menambahkannya secara berulang) menyebabkan mereka untuk melakukan pra-alokasi ruang, mirip dengan set dan dikt. Dari kode sumber listobj.c :
Data historis
Analisis Python 2.7, dikonfirmasi dengan
guppy.hpy
dansys.getsizeof
:Perhatikan bahwa kamus ( tetapi bukan set ) mendapat representasi yang lebih ringkas dalam Python 3.6
Saya pikir 8 byte per item tambahan untuk referensi masuk akal pada mesin 64 bit. 8 byte itu menunjuk ke tempat di memori item yang terkandung. 4 byte adalah lebar tetap untuk unicode di Python 2, jika saya ingat dengan benar, tetapi dalam Python 3, str menjadi unicode dengan lebar sama dengan lebar maks karakter.
(Dan untuk lebih lanjut tentang slot, lihat jawaban ini )
Fungsi Yang Lebih Lengkap
Kami ingin fungsi yang mencari elemen dalam daftar, tupel, set, dikte
obj.__dict__
, danobj.__slots__
, serta hal-hal lain yang mungkin belum terpikirkan.Kami ingin mengandalkan
gc.get_referents
untuk melakukan pencarian ini karena berfungsi pada level C (membuatnya sangat cepat). Kelemahannya adalah get_referents dapat mengembalikan anggota yang berlebihan, jadi kami perlu memastikan bahwa kami tidak menggandakan jumlah.Kelas, modul, dan fungsi adalah lajang - mereka ada satu kali dalam memori. Kami tidak begitu tertarik dengan ukurannya, karena tidak banyak yang dapat kami lakukan tentang mereka - mereka adalah bagian dari program ini. Jadi kami akan menghindari menghitungnya jika mereka dirujuk.
Kami akan menggunakan daftar jenis hitam sehingga kami tidak memasukkan seluruh program dalam jumlah ukuran kami.
Untuk mengontraskan ini dengan fungsi daftar putih berikut, sebagian besar objek tahu cara melintasi dirinya untuk tujuan pengumpulan sampah (yang kira-kira apa yang kita cari ketika kita ingin tahu seberapa mahal dalam memori objek tertentu. Fungsi ini digunakan oleh
gc.get_referents
.) Namun, ukuran ini akan jauh lebih luas dalam ruang lingkup daripada yang kita maksudkan jika kita tidak hati-hati.Sebagai contoh, fungsi tahu banyak tentang modul yang mereka buat.
Poin kontras lainnya adalah string yang merupakan kunci dalam kamus biasanya diinternir sehingga tidak terduplikasi. Memeriksa
id(key)
juga akan memungkinkan kami untuk menghindari penghitungan duplikat, yang kami lakukan di bagian selanjutnya. Solusi daftar hitam melompati tombol penghitungan yang merupakan string sekaligus.Jenis Daftar Putih, pengunjung Rekursif (implementasi lama)
Untuk menutupi sebagian besar dari tipe ini sendiri, daripada mengandalkan modul gc, saya menulis fungsi rekursif ini untuk mencoba memperkirakan ukuran sebagian besar objek Python, termasuk sebagian besar builtin, tipe dalam modul koleksi, dan tipe khusus (slotted dan lainnya) .
Fungsi semacam ini memberikan kontrol yang jauh lebih baik atas jenis yang akan kita hitung untuk penggunaan memori, tetapi memiliki risiko mengabaikan jenis:
Dan saya mengujinya dengan santai (saya harus melepasnya):
Implementasi ini rusak pada definisi kelas dan definisi fungsi karena kita tidak mengejar semua atribut mereka, tetapi karena mereka seharusnya hanya ada satu kali dalam memori untuk proses, ukurannya benar-benar tidak terlalu penting.
sumber
The Pympler paket ini
asizeof
modul bisa melakukan ini.Gunakan sebagai berikut:
Tidak seperti
sys.getsizeof
itu, ini berfungsi untuk objek yang Anda buat sendiri . Bahkan bekerja dengan numpy.Seperti yang disebutkan ,
Dan jika Anda membutuhkan tampilan lain pada data langsung, Pympler
sumber
org.apache.spark.util.SizeEstimator
mungkin relevanpympler
memiliki kemampuan untuk mengambil ukuran kode fungsi yang dapat dieksekusi dan callable lainnya dan objek kode ke akun.TypeError
pengecualian: "objek 'NoneType' tidak bisa dipanggil" setiap kali objek kustom saya memiliki beberapa subobjek di "tree" -nya dengan nilaiNone
. Apakah ada solusi cepat untuk ini?Untuk array numpy,
getsizeof
tidak berfungsi - bagi saya itu selalu mengembalikan 40 karena beberapa alasan:Lalu (dengan ipython):
Untungnya, meskipun:
sumber
getsizeof()
hanya memberi Anda ukuran objek (header array), bukan data di dalamnya. Sama untuk wadah python di manasys.getsizeof([1,2,4]) == sys.getsizeof([1,123**456,4]) == 48
, sementarasys.getsizeof(123**456) = 436
getsizeof()
fungsi diubah di beberapa titik untuk mengembalikan nilai yang diharapkan.Python 3.8 (Q1 2019) akan mengubah beberapa hasil
sys.getsizeof
, seperti yang diumumkan di sini oleh Raymond Hettinger:Ini muncul setelah edisi 33597 dan karya Inada Naoki (
methane
) seputar Compact PyGC_Head, dan PR 7043Lihat komit d5c875b :
sumber
Ini bisa lebih rumit daripada yang terlihat tergantung pada bagaimana Anda ingin menghitung sesuatu. Misalnya, jika Anda memiliki daftar int, apakah Anda ingin ukuran daftar yang berisi referensi ke int? (mis. hanya daftar, bukan apa yang terkandung di dalamnya), atau apakah Anda ingin menyertakan data aktual yang ditunjukkan, dalam hal ini Anda harus berurusan dengan referensi rangkap, dan bagaimana mencegah penghitungan ganda ketika dua objek berisi referensi untuk objek yang sama.
Anda mungkin ingin melihat salah satu profiler memori python, seperti pysizer untuk melihat apakah mereka memenuhi kebutuhan Anda.
sumber
Setelah mengalami masalah ini berkali-kali sendiri, saya menulis fungsi kecil (terinspirasi oleh jawaban @ aaron-hall) & tes yang melakukan apa yang saya harapkan sys.getsizeof lakukan:
https://github.com/bosswissam/pysize
Jika Anda tertarik pada latar belakang, ini dia
EDIT: Melampirkan kode di bawah ini untuk referensi mudah. Untuk melihat kode terbaru, silakan periksa tautan github.
sumber
Berikut ini adalah skrip cepat yang saya tulis berdasarkan jawaban sebelumnya untuk daftar ukuran semua variabel
sumber
Anda bisa membuat serial objek untuk mendapatkan ukuran yang terkait erat dengan ukuran objek:
Jika Anda ingin mengukur objek yang tidak dapat diasamkan (misalnya karena ekspresi lambda) cloudpickle dapat menjadi solusi.
sumber
Gunakan sys.getsizeof () jika Anda TIDAK ingin menyertakan ukuran objek yang terhubung (bersarang).
Namun, jika Anda ingin menghitung sub-objek yang bersarang dalam daftar, dicts, set, tuple - dan biasanya INI yang Anda cari - gunakan fungsi deep sizeof () rekursif () seperti yang ditunjukkan di bawah ini:
Anda juga dapat menemukan fungsi ini di kotak peralatan bagus , bersama dengan banyak satu-liners berguna lainnya:
https://github.com/mwojnars/nifty/blob/master/util.py
sumber
Jika Anda tidak membutuhkan ukuran objek yang tepat tetapi secara kasar mengetahui seberapa besar benda itu, satu cara cepat (dan kotor) adalah membiarkan program berjalan, tidur untuk waktu yang lama, dan memeriksa penggunaan memori (mis. : Monitor aktivitas Mac) dengan proses python khusus ini. Ini akan efektif ketika Anda mencoba menemukan ukuran satu objek besar tunggal dalam proses python. Sebagai contoh, saya baru-baru ini ingin memeriksa penggunaan memori dari struktur data baru dan membandingkannya dengan struktur data yang ditetapkan Python. Pertama saya menulis elemen (kata-kata dari buku domain publik besar) ke set, kemudian memeriksa ukuran proses, dan kemudian melakukan hal yang sama dengan struktur data lainnya. Saya menemukan proses Python dengan satu set mengambil dua kali lebih banyak memori daripada struktur data baru. Sekali lagi, kamu tidak akan t dapat dengan tepat mengatakan memori yang digunakan oleh proses sama dengan ukuran objek. Ketika ukuran objek semakin besar, ini menjadi dekat karena memori yang dikonsumsi oleh sisa proses menjadi diabaikan dibandingkan dengan ukuran objek yang Anda coba pantau.
sumber
Anda dapat menggunakan getSizeof () seperti yang disebutkan di bawah ini untuk menentukan ukuran objek
sumber
Saya menggunakan trik ini ... Mungkin tidak akan akurat pada objek kecil, tapi saya pikir itu jauh lebih akurat untuk objek yang kompleks (seperti permukaan pygame) daripada sys.getsizeof ()
Di windows 10 saya, python 3.7.3, hasilnya adalah:
sumber