2015-10-23 30 views
6

Bellek yönetiminin Bytearray ile Python'da liste arasında nasıl bir fark olduğunu bilmek isterim.Python'da Bytearray ve List Arasındaki Fark

Difference between bytearray and list gibi bir kaç soru buldum ama tam olarak soruma cevap vermiyor.

Sorum tam ...

from array import array 
>>> x = array("B", (1,2,3,4)) 
>>> x.__sizeof__() 
36 
>>> y = bytearray((1,2,3,4)) 
>>> y.__sizeof__() 
32 
>>> z = [1,2,3,4] 
>>> z.__sizeof__() 
36 

biz liste/array.array arasındaki boyutlarda bir fark (4 element için 36 bayt) ve bir bayt dizisi (4 element için 32 bayt olduğunu görebileceğiniz gibi). Birisi bana bunun neden olduğunu açıklayabilir mi? 4 öğeleri (4 * 8 == 32) için 32 bayt bellek kapladığı bayt dizisi için anlamlıdır, ancak bu liste ve array.array için nasıl yorumlanabilir? Her bir eleman sadece 8 bayt işgal ettiğinde, iki bitişik eleman arasında fark yok neden

# Lets take the case of bytearray (which makes more sense to me at least :p) 
for i in y: 
     print(i, ": ", id(i)) 

1 : 499962320 
2 : 499962336 #diff is 16 units 
3 : 499962352 #diff is 16 units 
4 : 499962368 #diff is 16 units 

, burada 16 birimleri tarafından farklıdır. Bu, her bir bellek adresi işaretçisinin bir nibble işaret ettiği anlamına mı geliyor?

Ayrıca bir tamsayı için bellek ayırma ölçütleri nedir? Python'un daha fazla bellek, tam sayı değerine bağlı olarak daha fazla bellek atayacağını okudum (yanlışsam beni düzelt).

Örn:

>>> y = 10 
>>> y.__sizeof__() 
14 
>>> y = 1000000 
>>> y.__sizeof__() 
16 
>>> y = 10000000000000 
>>> y.__sizeof__() 
18 

Python bellek ayırır kriter nedir?

Python neden bu kadar fazla bellek kaplıyorken C yalnızca 8 bayt kaplıyor (benimki 64 bitlik bir makinedir)? Tam olarak (2 ** 64) tamsayı aralığında olduğunda?

Meta veriler:

Python sürümü:'3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit (Intel)]'

Makine kemer: 64 bit

PS: Nazikçe iyi yazıya bana yol Python bellek yönetimi nerede daha iyi açıkladı. Bu şeyleri anlamak için neredeyse bir saat harcadım ve bu soruyu SO'ya sorarak bitirdim. :(

+2

İyi soru, yukarı dönük. Hey, şanslısın: my Linux Xubuntu 64 bit makine CPython 3.4.3 üzerinde 'y .__ sizeof __()' ', y = 1M'' aynı, y = 10' 'için 28 '' bana verir 32' 'y = 10000000000000' için – Pynchia

+0

Merhaba @Pynchia, Benim makinem 64 bit olmasına rağmen, Mine bir 32 bit python. Emin değilim, ama sebebi bu olabilir. Birinin netleşmesini bekleyelim. –

cevap

1

Ben iddia etmiyorum bu tam cevabı, ancak bazı ipuçları bu anlamada vardır.

bytearray bayt dizisidir ve list Yani [1,2,3] aslında bellek işaretçileri tutar. Nesne referansları dizisidir başka yerde bellekte depolanır, bu tamsayılar için. bir liste yapısının toplam bellek tüketimini hesaplamak için, (bu __sizeof__ artı GC yükü aradığını her yerde başka sys.getsizeof kullanıyorum) bunu yapabilirsiniz

>>> x = [1,2,3] 
>>> sum(map(getsizeof, x)) + getsizeof(x) 
172 

Sonucu olabilir d Farklı makinelerde.

Ayrıca, şuna bak:

Listeler değiştirilebilir olduğu için var
>> getsizeof([]) 
64 

. hızlı olması için, bu yapının (örneğin listenin uzunluğu artı meta bir depolama) nesnelere başvurular saklamak için bir bellek aralığı ayırır. Öğeleri eklediğinizde, sonraki bellek hücreleri bu öğelere başvurularla doldurulur. Yeni öğeleri depolamak için yer olmadığı zaman, yeni, daha geniş aralık tahsis edilir, orada mevcut veriler kopyalanır ve eski yayınlanır. Bu dinamik diziler denir.

Bu kodu çalıştırarak, bu davranışı gözlemleyebiliriz.

import sys 
data=[] 
n=15 
for k in range(n): 
    a = len(data) 
    b = sys.getsizeof(data) 
    print('Length: {0:3d}; Size in bytes: {1:4d}'.format(a, b)) 
    data.append(None) 

Benim sonuçları:

Length: 0; Size in bytes: 64 
Length: 1; Size in bytes: 96 
Length: 2; Size in bytes: 96 
Length: 3; Size in bytes: 96 
Length: 4; Size in bytes: 96 
Length: 5; Size in bytes: 128 
Length: 6; Size in bytes: 128 
Length: 7; Size in bytes: 128 
Length: 8; Size in bytes: 128 
Length: 9; Size in bytes: 192 
Length: 10; Size in bytes: 192 
Length: 11; Size in bytes: 192 
Length: 12; Size in bytes: 192 
Length: 13; Size in bytes: 192 
Length: 14; Size in bytes: 192 

Biz 8 bellek adreslerini (64-bit her) depolamak için kullanılan 64 bayt olduğunu görebiliriz.

Neredeyse aynı bytearray() (data = bytearray() ikinci satırı değiştirmek ve sonuncusu içinde 1 ekleme) ile gider.

Length: 0; Size in bytes: 56 
Length: 1; Size in bytes: 58 
Length: 2; Size in bytes: 61 
Length: 3; Size in bytes: 61 
Length: 4; Size in bytes: 63 
Length: 5; Size in bytes: 63 
Length: 6; Size in bytes: 65 
Length: 7; Size in bytes: 65 
Length: 8; Size in bytes: 68 
Length: 9; Size in bytes: 68 
Length: 10; Size in bytes: 68 
Length: 11; Size in bytes: 74 
Length: 12; Size in bytes: 74 
Length: 13; Size in bytes: 74 
Length: 14; Size in bytes: 74 

Fark şimdi gerçek bayt değerleri değil, işaretçileri tutmak için kullanılan bellektir. daha fazla araştırma için yardımcı

Umut.

+0

Merhaba @ anti1869, Yorumunuz için teşekkürler. Onun çok kapsamlı ve yararlı. Ama yorumunuzda soruları takip ediyorum. Buraya tüm bilgileri ekleyemiyorum ve bu nedenle altta başka bir yorum ekleyemiyorum. Teşekkürler –

+0

Listeniz onun açıklamanıza göre anlaşılıyor, ancak bayt dizisinin büyüklüğü neden 56 ile başladı. Neden 74'e ulaştıktan sonra kararlı oluyor? Ve eğer daha fazla bilgi verebilirseniz, 64 ve 56'ların ilk büyüklüğünü verirseniz seviniriz. Teşekkürler –

+0

Veri yapıları kaynak koduna bakın. Orada iç konteyner yapısını göreceksiniz ve ne zaman başlatma için bellek ayırır. Ayrıca büyüme algoritması çok net olarak görülebilir. https://github.com/python/cpython/blob/master/Objects/listobject.c – anti1869