2014-04-10 33 views
8

Bellekte verileri depolamak için gereken RAM, aynı verileri bir dosyada depolamak için gereken disk alanıyla nasıl karşılaştırılır? Yoksa genel bir korelasyon yok mu? Örneğin, sadece bir milyar kayan nokta değerine sahip olduğumu söyleyin. İkili formda saklanır, diskte 4 milyar bayt veya 3,7 GB olur (üstbilgiler dahil değildir). O zaman Python'daki bir listeye bu değerleri okuduğumu söyleyeyim ... ne kadar RAM'in bunu gerektirmesini beklemeliyim?Veri boyutu bellekte diskte

+0

Daha fazla RAM! Diğer şeylerin yanı sıra liste başı vardır. Endişe ediyorsanız, a) bunu öğrenin ve b) ham verilerin sadece hafızaya kaydedilmesini ve paketin açılmasını göz önünde bulundurun (bununla ne yaptığınıza bağlı olarak değişir). – Ryan

+2

İlgili: http: // stackoverflow.com/a/994010/846892 –

+0

İlk düşüncem, kullanıcının tüm verilerin RAM'e yüklenmesini beklemesi biraz zaman alacaktı. –

cevap

3

Python nesne veri boyutu

veriler, bazı piton nesnesinde saklanıyorsa, bellekte gerçek verilere bağlı biraz daha veri olacaktır.

Bu, kolayca test edilebilir.

The size of data in various forms

İlk başta, piton nesnenin havai küçük veriler için önemli ne kadar, ilginçtir, ama çabuk ihmal edilebilir hale gelir. İşte

düz Python listesinde arsa

%matplotlib inline 
import random 
import sys 
import array 
import matplotlib.pyplot as plt 

max_doubles = 10000 

raw_size = [] 
array_size = [] 
string_size = [] 
list_size = [] 
set_size = [] 
tuple_size = [] 
size_range = range(max_doubles) 

# test double size 
for n in size_range: 
    double_array = array.array('d', [random.random() for _ in xrange(n)]) 
    double_string = double_array.tostring() 
    double_list = double_array.tolist() 
    double_set = set(double_list) 
    double_tuple = tuple(double_list) 

    raw_size.append(double_array.buffer_info()[1] * double_array.itemsize) 
    array_size.append(sys.getsizeof(double_array)) 
    string_size.append(sys.getsizeof(double_string)) 
    list_size.append(sys.getsizeof(double_list)) 
    set_size.append(sys.getsizeof(double_set)) 
    tuple_size.append(sys.getsizeof(double_tuple)) 

# display 
plt.figure(figsize=(10,8)) 
plt.title('The size of data in various forms', fontsize=20) 
plt.xlabel('Data Size (double, 8 bytes)', fontsize=15) 
plt.ylabel('Memory Size (bytes)', fontsize=15) 
plt.loglog(
    size_range, raw_size, 
    size_range, array_size, 
    size_range, string_size, 
    size_range, list_size, 
    size_range, set_size, 
    size_range, tuple_size 
) 
plt.legend(['Raw (Disk)', 'Array', 'String', 'List', 'Set', 'Tuple'], fontsize=15, loc='best') 
+1

Bu cevap doğru değil. Sys.getsizeof belgelerine göre "Yalnızca nesneye atfedilen bellek tüketimi, başvurduğu nesnelerin bellek tüketimini değil, hesaba katılır." Yani sadece kaplarda tahsis edilen belleği açıkladınız ve sayı nesnelerine kendileri için tahsis edilen ek hafızayı dikkate almadınız. –

+1

Tam bellek ayırmanın nasıl belirleneceğine dair bir öneriniz var mı? Ben arsa yeniden yapacağım! – tmthydvnprt

+0

"List", "set" ve "tuple" için bildirilen bellek boyutuna 'len (double_list) * sys.getsizeof (1.0)' eklemeniz gerektiğini düşünüyorum. Tahsisleri yönetmek için muhtemelen bir miktar ek bellek gerekiyor, ancak bunu nasıl ölçeceğimi bilmiyorum ve ihmal edilebilir. –

1

üretmek için kullanılan ipython kodu her çifte kesinlik sayısı belleği en az 32 bayt gerektirir, ancak sadece 8 byte gerçek saklamak için kullanılır sayı, geri kalanı Python'un dinamik doğasını desteklemek için gereklidir. CPython kullanılan

yüzer nesne floatobject.h tanımlanır:

typedef struct { 
    PyObject_HEAD 
    double ob_fval; 
} PyFloatObject; 

PyObject_HEADPyObject yapı için a macro that expands: Bu nedenle

typedef struct _object { 
    Py_ssize_t ob_refcnt; 
    struct _typeobject *ob_type; 
} PyObject; 

Python mağazalarında her kayan nokta nesne iki pointer- 8 baytlık çiftin yanı sıra (her biri 64 bit mimaride 8 bayt) büyüklükteki alanlar, sayı başına 24 bayt bellek ayırma belleği sağlar. Bu sys.getsizeof(1.0) == 24 tarafından onaylanmıştır.

Bu Python n katına bir listesi sadece sayı nesnelere işaretçiler (PyObject*) saklamak için bellek en az 8*n bayt alır ve her bir nesne numarası ilave 24 bayt gerektirdiğini gösterir. Bunu test etmek için, Python Repl aşağıdaki satırları çalıştırmayı deneyin:

>>> import math 
>>> list_of_doubles = [math.sin(x) for x in range(10*1000*1000)] 

ve Python yorumlayıcısı bellek kullanımını görmek (benim x86-64 bilgisayarda ayrılan belleğin yaklaşık 350 MB var). Eğer çalıştı unutmayın:

>>> list_of_doubles = [1.0 for __ in range(10*1000*1000)] 

sadece yaklaşık 80 MB elde ediyorum, listedeki tüm öğeleri kayan noktalı sayı 1.0 ait aynı örneğini ifade çünkü.