[Python-es] Transferencia archivos grandes en socket

lasizoillo lasizoillo en gmail.com
Lun Abr 22 14:41:15 EDT 2019


Tiene toda la pinta de ser lo que te dice Alexis Roda. Piensa que cada vez
que haces crecer buf (buf+=recv(...)) pasa lo siguiente:
- buf apunta a obj1 en memoria
- lees el dato del socket creando obj2, también en memoria
- reserva el espacio para obj3 en memoria cuyo tamaño será aprox la suma de
los tamaños obj1 y obj2
- copias el contenido de obj1 y obj2 sobre obj3
- buf apunta a obj3
- obj1 y obj2 pierden referencias por lo que son destruidos y vaciados de
memoria

Como te puedes imaginar cuanto más grande es buf más trabajo le toca hacer.
La memoria se fragmenta, así que aunque creas que solo usas el resultado de
la copia (y copias muchas veces) usas más memoria. Cuando llenas la memoria
toca swapear (y eso es varios órdenes de magnitud más lento).

Haz caso a Alexis y escribe directo a disco sin mega buffers en memoria. La
parte de leer bloques ya lo estás haciendo bien.

Te paso una entrada a un blog donde de propina habla de como usar sendfile
para evitar copias entre kerner y memoria de usuario:
http://michaldul.com/python/sendfile/

Un saludo,

Javi

El lun., 22 abr. 2019 a las 19:45, PeRy (<perysoy en gmail.com>) escribió:

> Hola!
> el archivo es de 400MB, la transferencia empieza a todo lo que da la PI
> (10-11Mb/s estoy en LAN) para después bajar a 2Mb/s y a partir de los
> 200Megas descargados aproximadamente va bajando progresivamente terminando
> en menos de 0.5Mb/s, Con otro archivo de mayor tamaño (1.6Gb) es igual, a
> partir de 200 megas o así va bajando hasta 0.5Mb/s y con esa velocidad
> hasta el final.
>
> un saludo
>
> El lun., 22 abr. 2019 a las 19:17, AGTUGO (<agtugo en gmail.com>) escribió:
>
>> Que tan grande el archivo? Cuanto es mucho tiempo?
>>
>> On Sun, Apr 21, 2019 at 5:50 PM PeRy <perysoy en gmail.com> wrote:
>>
>>>
>>> Buenas! Estoy aprendiendo Python y estoy con el tema de los sockets, he
>>> creado un servidor y cliente para enviar archivos. Me he dado cuenta que en
>>> archivos grandes cuanto mas pasa el tiempo mas lenta se hace la recepción
>>> de la información, ¿alguna sugerencia por qué pasa y como se podría evitar?
>>> mi codigo:
>>>
>>> server:
>>>
>>> =============================================================================================
>>> elif b'\F' in data: # peticion de archivo para ser descargado
>>> transmitido = data.rstrip(b'\F')
>>> comparte_dir = os.path.join(os.getcwd(), 'compartir')
>>> print(os.path.join(comparte_dir, transmitido.decode()))
>>> filesize = os.path.getsize(os.path.join(comparte_dir,
>>> transmitido.decode()))
>>> print("TAMAÑO: {}".format(filesize))
>>> with open(os.path.join(comparte_dir, transmitido.decode()), 'rb') as f:
>>> self.socket.send(struct.pack('!I', filesize))  # enviamos en los
>>> primeros 4bytes el tamaño del archivo
>>> numero_bytes = self.socket.sendfile(f)
>>>                                         # data = f.read(8192)
>>> # numero_bytes = len(data)
>>> # self.socket.send(data)
>>> # while data:
>>> # data = f.read(8192)
>>> # self.socket.send(data)
>>> # numero_bytes += len(data)
>>>                                 print(numero_bytes)
>>>
>>> cliente:
>>>
>>> ===============================================================================================
>>> with open(archivo, 'wb') as f:
>>>                         buf = socket_cliente.recv(4)  # cabecera con elt
>>> amaño del archivo
>>>                         filesize = struct.unpack('!I', buf)
>>>                         print("filesize : {}".format(filesize))
>>>                         filesize=filesize[0]
>>>                         buf = b''
>>>                         tiempo_inicio = datetime.datetime.now()
>>>                         print(tiempo_inicio.strftime('%H:%M:%S'))
>>>                         while len(buf) < filesize:
>>>                             to_read = filesize - len(buf)
>>>                             buf += socket_cliente.recv(262144 if to_read
>>> > 262144 else to_read)  #8192 1024*8 o 4096 1024*4
>>>                             updt(filesize, len(buf))  # barra de progreso
>>>                         f.write(buf)
>>>
>>> ---------------------
>>> Muchas Gracias y un saludo
>>>
>>> _______________________________________________
>>> Python-es mailing list
>>> Python-es en python.org
>>> https://mail.python.org/mailman/listinfo/python-es
>>>
>>
>>
>> --
>> Arturo Muñoz Tolosa
>> _______________________________________________
>> Python-es mailing list
>> Python-es en python.org
>> https://mail.python.org/mailman/listinfo/python-es
>>
>
>
> _______________________________________________
> Python-es mailing list
> Python-es en python.org
> https://mail.python.org/mailman/listinfo/python-es
>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://mail.python.org/pipermail/python-es/attachments/20190422/4ce83895/attachment.html>


Más información sobre la lista de distribución Python-es