При работе с массивами байтов (большими данными) в python возникает проблема перерасхода памяти при разделении, а после отправки/копировании, как делать не стоит
1) классический пример с отправкой данных через сокет
1 2 3 4 5 6 7 8 9 10 11 12 |
def socket_emulate(): data_to_send = b'1' * (1024 * 1000000) # 976.570 MiB while data_to_send: sent = socket_send_emulate(data_to_send) # копируется значение и выделяется память + 5MiB data_to_send = data_to_send[sent:] def socket_send_emulate(data_to_send): return 1024 * 5000 if '__main__' == __name__: socket_emulate() |
2) классический пример с копированием данных в файл
1 2 3 4 5 6 7 |
with open('some_file', 'rb') as source: content = source.read(5000 * 1024) # здесь происходить копирование и + 5MiB памяти to_write = content[1024:] with open('other_file', 'wb') as dest: dest.write(to_write) |
здесь slice постоянно копирует содержимое в новую строку, что ведет к потерям памяти.
Что бы избежать этого всего был определен буфер протокол и объект MemoryView, который ссылается на пямять занятую первоначальным объектом, итого получается:
1) классический пример с отправкой данных через сокет
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def socket_emulate(): data_to_send = b'1' * (1024 * 1000000) # 976.570 MiB mv = memoryview(data_to_send) while mv: sent = socket_send_emulate(mv) # копирование не происходит и доп память не выделяется mv = mv[sent:] def socket_send_emulate(mv): return 1024 * 5000 if '__main__' == __name__: socket_emulate() |
2) классический пример с копированием данных в файл
1 2 3 4 5 6 7 |
with open('some_file', 'rb') as source: content = source.read(5000 * 1024) # копирование не происходит и доп память не выделяется to_write = memoryview(content)[1024:] with open('other_file', 'wb') as dest: dest.write(to_write) |
memoryview хорош для снижения затрат памяти и улучшения производительности,