2015-09-23 10 views
6

Ich muss lesen und schreiben riesige Binärdateien. Gibt es eine bevorzugte oder sogar optimale Anzahl von Bytes (was ich BLOCK_SIZE anrufen) ich sollte read() zu einer Zeit?bevorzugte Blockgröße beim Lesen/Schreiben von großen Binärdateien

1 Byte ist sicherlich zu wenig; und ich glaube nicht, 4GB in den RAM zu lesen ist auch eine gute Idee - gibt es eine "beste" Blockgröße? oder hängt das sogar vom Dateisystem ab (ich bin auf ext4)? Was muss ich beachten?

python's open() bietet sogar ein buffering Argument. Würde ich das auch noch verbessern müssen?

Dies ist ein Beispielcode, der nur die beiden Dateien in-0.data und in-1.data in out.data verbindet (im wirklichen Leben gibt es mehr Verarbeitung, die für die Frage irrelevant ist). die BLOCK_SIZE gleich io.DEFAULT_BUFFER_SIZE gewählt, die der Standard für buffering zu sein scheint:

from pathlib import Path 
from functools import partial 

DATA_PATH = Path(__file__).parent/'../data/' 

out_path = DATA_PATH/'out.data' 
in_paths = (DATA_PATH/'in-0.data', DATA_PATH/'in-1.data') 

BLOCK_SIZE = 8192 

def process(data): 
    pass 

with out_path.open('wb') as out_file: 
    for in_path in in_paths: 
     with in_path.open('rb') as in_file: 
      for data in iter(partial(in_file.read, BLOCK_SIZE), b''): 
       process(data) 
       out_file.write(data) 
#   while True: 
#    data = in_file.read(BLOCK_SIZE) 
#    if not data: 
#     break 
#    process(data) 
#    out_file.write(data) 
+0

Nicht sicher, dass es eine definitive Antwort dafür gibt, wahrscheinlich abhängig von Betriebssystem, Dateisystem und physikalischer Festplatte auf dem fraglichen Rechner. Wenn dies eine allgemeine Lösung sein soll, möchten Sie möglicherweise Code hinzufügen, um das System nach Parametern abzufragen, um die beste Antwort zu berechnen. – cdkMoose

+0

Ich hatte gehofft, das System mit 'io.DEFAULT_BUFFER_SIZE' abgefragt zu haben - aber ich habe wirklich keine Erfahrung mit den Details von all dem ... –

+1

Es gibt keine einzige statische Antwort für dieses sogar auf einem gegebenen System. Es hängt von einer großen Anzahl von Variablen ab, von denen sich einige im Laufe der Zeit ändern oder jedes Mal anders sein können. sowie was sonst noch Ihr Programm oder das System macht. Der beste Ansatz könnte darin bestehen, etwas zu schreiben, um eine gute Größe zu bestimmen, indem bestimmte unveränderliche repräsentative Testdateien verwendet werden. Alternativ können Sie einen eigenständigen Test schreiben und ihn einmal ausführen, um einen guten Kostenvoranschlag zu erhalten und ihn dann in Ihre Anwendung zu codieren (oder den Testteil des Installations- oder Einrichtungsprozesses zu machen). – martineau

Antwort

4

Lassen Sie das OS machen die Entscheidung für Sie. Verwenden Sie das Mmap Modul:

https://docs.python.org/3.4/library/mmap.html

Es verwendet zugrunde liegenden Speicher-Mapping-Mechanismus Ihres OS zur Abbildung des Inhalts einer Datei in dem Arbeitsspeicher.

Beachten Sie, dass bei Verwendung von 32-Bit-Python eine Dateigrößenbeschränkung von 2 GB besteht. Verwenden Sie daher unbedingt die 64-Bit-Version, wenn Sie diese Route wählen.

Zum Beispiel:

f1 = open('input_file', 'r+b') 
m1 = mmap.mmap(f1.fileno(), 0) 
f2 = open('out_file', 'a+b') # out_file must be >0 bytes on windows 
m2 = mmap.mmap(f2.fileno(), 0) 
m2.resize(len(m1)) 
m2[:] = m1 # copy input_file to out_file 
m2.flush() # flush results 

Beachten Sie, dass Sie nie() -Funktionen jede Lese zu nennen hatte und entscheiden, wie viele Bytes in den RAM zu bringen. In diesem Beispiel wird nur eine Datei in eine andere kopiert, aber wie Sie in Ihrem Beispiel gesagt haben, können Sie die von Ihnen benötigte Verarbeitung dazwischen durchführen. Beachten Sie, dass die gesamte Datei zwar einem Adressraum im RAM zugeordnet ist, dies jedoch nicht bedeutet, dass sie dort tatsächlich kopiert wurde. Es wird stückweise nach dem Ermessen des Betriebssystems kopiert.

+0

Wenn ich das richtig verstanden habe, müsste ich mich noch für die Anzahl der Bytes entscheiden 'n' Ich würde [' lesen ([n]) '] (https://docs.python.org/3.4/library/ mmap.html # mmap.mmap.read). dann bin ich zurück zu meinem ursprünglichen Problem. oder was fehlt mir? –

+0

Ich versuche jetzt etwas Code, aber im Wesentlichen mmap gibt Ihnen eine Bytearray-Schnittstelle zu Ihren Daten, zusätzlich zu der Dateischnittstelle. So können Sie auf Ihre Daten zugreifen, diese verarbeiten, als ob sie bereits in einem Bytearray wären. –

+0

Wie profitiere ich von einem 'Bytearray'? Meine 'Daten' sind vom Typ' 'schon - was vollkommen in Ordnung ist für das, was ich brauche. aber ich bin interessiert zu sehen, wohin das geht! –

Verwandte Themen