2017-01-07 2 views
0

Я хочу, чтобы скопировать большой файл (> = 1 Гб) памяти:Почему буфер Python 3x больше, чем bash dd?

#!/usr/bin/env python3 
# -*- coding: utf-8 -*- 

from subprocess import check_output 
from shlex import split 

zeroes = open('/dev/zero') 

SCALE = 1024 

B = 1 
KB = B * SCALE 
MB = KB * SCALE 
GB = MB * SCALE 

def ck(str): 
    print('{}:\n{}\n'.format(str, check_output(split('free -m')).decode())) 

ck('## Before') 

buffer = zeroes.read(GB) 

ck('## After') 

Выход:

## Before: 
       total  used  free  shared buff/cache available 
Mem:   15953  7080  6684   142  2188  8403 
Swap:   2047   0  2047 


## After: 
       total  used  free  shared buff/cache available 
Mem:   15953  9132  4632   142  2188  6351 
Swap:   2047   0  2047 

Очевидно 6684 - 4632 = 2052 Мб (что почти 2x размер ожидаемого 1 ГБ).

Тесты с dd показывают ожидаемые результаты:

# mkdir -p /mnt/tmpfs/ 
# mount -t tmpfs -o size=1000G tmpfs /mnt/tmpfs/ 
# free -m 
       total  used  free  shared buff/cache available 
Mem:   15953  7231  6528   144  2192  8249 
Swap:   2047   0  2047 
# dd if=/dev/zero of=/mnt/tmpfs/big_file bs=1M count=1024 
1024+0 records in 
1024+0 records out 
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.695143 s, 1.5 GB/s 
# free -m 
       total  used  free  shared buff/cache available 
Mem:   15953  7327  5406  1168  3219  7129 
Swap:   2047   0  2047 

В чем проблема? Почему python был вдвое большим?

Каковы наилучшие методы репликации желаемый результат * в Python 3x?

* Желаемый результат - python использует тот же объем памяти, что и dd.

+0

Re: «желаемый результат» - какой * * ваш желаемый результат? Если вы хотите работать с огромными буферами хранения - на любом языке - вам лучше использовать IO с отображением памяти. –

+0

BTW, если ваш контент является строкой Unicode, а не bytestring ... ну, это ваша проблема. –

+0

... для чтения байтов, используйте 'zeroes = open ('/ dev/zero', 'rb')' –

ответ

1

См. How is unicode represented internally in Python?.

Поскольку вы не указали, что ваш файл двоичный, вы читаете символы Юникода, для которых требуется хранить 2-4 байта на символ для хранения в памяти даже для кода, представленного как один байт на диске.


Использование:

zeroes = open('/dev/zero', 'rb') # the 'b' flag is critical here! 

..., чтобы открыть файл для чтения байтовых строк.

+0

Поскольку реализация PEP 393 в строках Unicode Python 3.3 использует внутренне представленные несколькими способами. В зависимости от требований для хранения символа можно использовать 1, 2 или 4 байтовые последовательности ([unicode api] (https://docs.python.org/3/c-api/unicode.html)). Это фиксированные кодировки ширины и, я считаю, соответствуют латинским-1, USC-2 и UTF-32. Нет необходимости использовать представление 2 или 4 байта при декодировании '/ dev/zeros' в качестве символов. Данные могут быть надлежащим образом сохранены с использованием латинского-1. Попробуйте: 's = '\ 0' * (1 << 20); печать (sys.getsizeof (s)) '. Результат - 1 Мбайт + 25 байт. – Dunes

Смежные вопросы