python / python/cpython

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

Ouverte
#96,059 2 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

performance stdlib
Langage dominant
Python
Étoiles
77.2k
Forks
36k
Métriques de merge des PR
Métriques de PR en attente

Description

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

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par _recv dans Lib/multiprocessing/connection.py, référencé dans l’issue, et comparez la manière dont les lectures sur les pipes sont gérées sous Unix et Windows. Vérifiez qu’un buffer préalloué peut recevoir de gros messages sans la copie supplémentaire, tout en préservant le comportement existant de EOF et des lectures partielles sur les deux plateformes ; l’issue ne nomme pas de tests spécifiques.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
distributed-systems, operating-systems
Type d'issue
Fonctionnalité
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
45/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.