python / python/cpython

Avoid extraneous copy when `_recv`ing bytes through pipes in multiprocessing "connections"

Abierto
#96,059 2 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

performance stdlib
Lenguaje dominante
Python
Estrellas
77.2k
Forks
36k
Merge medio
1 d 9 h
PR fusionados (30 d)
558

Descripción

Feature or enhancement

Avoid extraneous copy when _recving bytes through pipes in multiprocessing "connections"

Pitch

In the default IPC implementation of the multiprocessing module using pipes, the Connection._recv method is defined as follows:

https://github.com/python/cpython/blob/586fc02be5b3e103bfddd49654034a898a8d6dfc/Lib/multiprocessing/connection.py#L378-L392

Seems like we can avoid a copy if we can read directly into a preallocated byte array? This would be beneficial if the bytes we're sending between processes are large. Another benefit here is that the buf.write() call above doesn't release the GIL, so in my workloads I've seen it causing stalls in another thread when trying to read from a multiprocessing.Queue instance.

Sample implementation that avoids the extraneous copy is shown below (bit untested). If it makes sense, I can submit a patch, but probably need some guidance to deal with the Windows case:

import io


def unix_readinto(fd, buf):
    # Thanks https://stackoverflow.com/q/13919006/1572989
    return io.FileIO(fd, closefd=False).readinto(buf)


class Connection(...):
    ...

    def _recv(self, size, readinto=unix_readinto):
        buf = io.BytesIO(initial_bytes=bytes(size))
        handle = self._handle
    
        mem = buf.getbuffer()
        total = 0
        while total != size:
            n = readinto(handle, mem[total:])
    
            if n == 0:
                if total == 0:
                    raise EOFError
                else:
                    raise OSError("got end of file during message")
    
            total += n
    
        return buf

Previous discussion

N/A

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza con _recv en Lib/multiprocessing/connection.py, enlazado en el issue, y compara cómo se gestionan las lecturas de tuberías en Unix y Windows. Verifica que un búfer preasignado pueda recibir mensajes grandes sin la copia adicional, preservando al mismo tiempo el comportamiento existente de EOF y de las lecturas parciales en ambas plataformas; el issue no especifica pruebas concretas.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
python
Área
distributed-systems, operating-systems
Tipo de issue
Nueva funcionalidad
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
45/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.