2014-04-10 16 views
8

Wie ist der zum Speichern von Daten im Arbeitsspeicher erforderliche Arbeitsspeicher mit dem Speicherplatz vergleichbar, der zum Speichern der gleichen Daten in einer Datei erforderlich ist? Oder gibt es keine generalisierte Korrelation?Datengröße im Speicher im Vergleich zur Festplatte

Zum Beispiel sagen, ich habe einfach eine Milliarde Fließkommawerte. In Binärform gespeichert, wären das 4 Milliarden Bytes oder 3,7 GB auf der Festplatte (ohne Header und ähnliches). Dann sage ich, dass ich diese Werte in eine Liste in Python lese ... wie viel RAM sollte ich erwarten?

+0

Mehr RAM! Unter anderem gibt es Listen Overhead. Wenn Sie sich Sorgen machen, a) finden Sie heraus, und b) erwägen Sie einfach, die rohen Daten im Speicher zu speichern und sie sofort zu entpacken (es kommt darauf an, was Sie damit machen). – Ryan

+2

Verwandt: http: // stackoverflow.com/a/994010/846892 –

+0

Mein erster Gedanke ist, dass der Benutzer eine Weile warten würde, bis alle Daten in den RAM geladen wurden. –

Antwort

3

Python Objektdaten Größe

Wenn die Daten in irgendeine Python-Objekt gespeichert wird, wird es ein wenig mehr Daten zu den tatsächlichen Daten im Speicher angebracht sein.

Dies kann leicht getestet werden.

The size of data in various forms

Es ist interessant zu sehen, wie auf den ersten, die Overhead des Python-Objekt für kleine Daten signifikant ist, wird aber schnell vernachlässigbar.

Hier ist der verwendete ipython Code ist die Handlung

%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

Diese Antwort ist nicht korrekt. Die Dokumentation für sys.getsizeof besagt, dass "nur der Speicherverbrauch, der dem Objekt direkt zugeordnet wird, berücksichtigt wird, nicht der Speicherverbrauch der Objekte, auf die es sich bezieht." Sie haben also nur den in den Containern zugewiesenen Speicher berücksichtigt und nicht den zusätzlichen Speicher berücksichtigt, der den Nummernobjekten selbst zugewiesen wurde. –

+1

Haben Sie eine Empfehlung, wie Sie die volle Speicherbelegung ermitteln können? Ich werde die Handlung wiederholen! – tmthydvnprt

+0

Ich denke, dass Sie 'len (double_list) * sys.getsizeof (1.0)' zur gemeldeten Speichergröße für 'list',' set' und 'tuple' hinzufügen müssen. Es gibt wahrscheinlich etwas zusätzlichen Speicher, der benötigt wird, um die Zuordnungen zu verwalten, aber ich weiß nicht, wie ich es messen soll, und es sollte vernachlässigbar sein. –

1

in einer einfachen Python Liste, jede Zahl mit doppelter Genauigkeit benötigt mindestens 32 Bytes Speicher, sondern nur 8 Bytes verwendet werden, zu erzeugen, die tatsächlichen zum Speichern von Anzahl, der Rest ist notwendig, um die dynamische Natur von Python zu unterstützen.

Der Schwimmer Objekt in CPython verwendet ist definiert in floatobject.h:

typedef struct { 
    PyObject_HEAD 
    double ob_fval; 
} PyFloatObject; 

wo PyObject_HEAD ist a macro that expands zum PyObject struct:

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

Daher jede Gleitkomma-Objekt in Python speichert zwei Pointer- Größe Felder (so dass jeder 8 Bytes auf einer 64-Bit-Architektur dauert) neben dem 8-Byte-Double, geben 24 Bytes Heap-allozierten Speicher pro Nummer. Dies wird durch sys.getsizeof(1.0) == 24 bestätigt.

Dies bedeutet, dass eine Liste von n verdoppelt in Python mindestens 8*n Byte Speicher (PyObject*) zu der Anzahl Objekte, und jede Zahl Objekt erfordert zusätzliche 24 Bytes nur zum Speichern der Zeiger erfolgt. Um es zu testen, versuchen Sie die folgenden Zeilen in dem Python REPL ausgeführt wird:

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

und die Speichernutzung des Python-Interpreter sehen (Ich habe rund 350 MB zugewiesenen Speicher auf meinem x86-64 Computer). Beachten Sie, wenn Sie versucht:

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

Sie nur etwa 80 MB erhalten würde, weil alle Elemente in der Liste der gleichen Instanz der Gleitkommazahl 1.0 beziehen.

Verwandte Themen