python / python/cpython

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

オープン
#96,059 コメント 2 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

performance stdlib
主要言語
Python
スター
77.2k
フォーク
36k
PR マージ指標
PR 指標を取得中

説明

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

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

Issue でリンクされている Lib/multiprocessing/connection.py の _recv から始め、Unix と Windows で pipe の読み取りがどのように処理されているかを比較します。事前に確保したバッファーで、追加のコピーなしに大きなメッセージを受信でき、同時に両プラットフォームで既存の EOF および部分読み取りの動作が維持されることを確認してください。この issue では具体的なテストは指定されていません。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
python
領域
distributed-systems, operating-systems
issue の種類
機能追加
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
45/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。