2015-09-23 32 views
6

Potrzebuję czytać i pisać ogromne pliki binarne. czy istnieje preferowana, a nawet optymalna liczba bajtów (co nazywam BLOCK_SIZE) powinienem read() na raz?preferowany rozmiar bloku podczas odczytu/zapisu dużych plików binarnych

1 bajt jest z pewnością zbyt mały; i nie sądzę, że czytanie 4GB w pamięci RAM jest dobrym pomysłem - czy istnieje "najlepszy" rozmiar bloku? czy to nawet zależy od systemu plików (jestem na ext4)? co muszę wziąć pod uwagę?

python's open() podaje nawet argument buffering. czy też muszę to poprawić?

to przykładowy kod, który po prostu łączy dwa pliki: in-0.data i in-1.data w out.data (w prawdziwym życiu jest więcej przetwarzania, które jest nieistotne dla danego pytania). BLOCK_SIZE wybierany jest równa io.DEFAULT_BUFFER_SIZE który wydaje się być domyślna dla buffering:

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

Nie wiem, czy istnieje na to ostateczna odpowiedź, prawdopodobnie zależna od systemu operacyjnego, systemu plików i dysku fizycznego na danym komputerze. Jeśli ma to być ogólne rozwiązanie, możesz chcieć dodać kod, aby przeskanować system w poszukiwaniu parametrów, aby obliczyć najlepszą odpowiedź. – cdkMoose

+0

Miałem nadzieję, że "przesłuchałem system", używając 'io.DEFAULT_BUFFER_SIZE' - ale naprawdę nie mam żadnego doświadczenia ze szczegółami tego wszystkiego ... –

+1

Nie ma jednej statycznej odpowiedzi na to nawet w danym systemie. Zależy to od dużej liczby zmiennych, z których niektóre mogą zmieniać się z upływem czasu lub różnić się za każdym razem. a także co jeszcze robi twój program lub system. Najlepszym rozwiązaniem może być napisanie czegoś w celu ustalenia odpowiedniego rozmiaru w tym momencie przy użyciu pewnych niezmiennych reprezentatywnych plików testowych. Ewentualnie możesz napisać test niezależny i uruchomić go raz, aby uzyskać dobre oszacowanie, a następnie wprowadzić kod do aplikacji (lub wykonać część testową procesu instalacji lub konfiguracji). – martineau

Odpowiedz

4

Niech OS podjąć decyzję za ciebie. Użyj modułu mmap:

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

Wykorzystuje podstawową mechanizm mapowania pamięci systemu operacyjnego dla mapowania zawartości pliku do pamięci RAM.

Pamiętaj, że w przypadku 32-bitowego Pythona obowiązuje limit rozmiaru pliku 2GB, więc jeśli zdecydujesz się na tę trasę, skorzystaj z wersji 64-bitowej.

Na przykład:

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 

Należy pamiętać, że nigdy nie trzeba było wywołać dowolną read() funkcje i zdecydować, jak wiele bajtów wprowadzają w pamięci RAM. Ten przykład po prostu kopiuje jeden plik do drugiego, ale jak powiedziałeś w twoim przykładzie, możesz zrobić wszystko, co potrzebujesz. Zwróć uwagę, że podczas gdy cały plik jest mapowany na przestrzeń adresową w pamięci RAM, nie oznacza to, że została tam skopiowana. Zostanie on skopiowany w kolejności, według uznania systemu operacyjnego.

+0

Jeśli rozumiem poprawnie, nadal musiałbym zdecydować o liczbie bajtów 'n', które chciałbym [' przeczytaj ([n]) '] (https://docs.python.org/3.4/library/ mmap.html # mmap.mmap.read). to wróciłem do mojego pierwotnego problemu. lub czego brakuje? –

+0

Próbuję teraz kod, ale zasadniczo mmap daje interfejs bytearray do danych, oprócz interfejsu pliku. Dzięki temu możesz uzyskać dostęp do danych, przetwarzać je itp., Tak jakby były już w bytearray. –

+0

Jak korzystać z "bytearray"? moje 'dane' są typu' 'już - co jest idealnie w porządku dla tego, czego potrzebuję. ale jestem zainteresowany, aby zobaczyć, gdzie to idzie! –