From 180ee43bde99b8ce4c4f1d5237ab191e26118061 Mon Sep 17 00:00:00 2001 From: Cody Maloney Date: Tue, 28 Jan 2025 03:40:44 -0800 Subject: gh-129005: Avoid copy in _pyio.FileIO.readinto() (#129324) `os.read()` allocated and filled a buffer by calling `read(2)`, than that data was copied into the user provied buffer. Read directly into the caller's buffer instead by using `os.readinto()`. `os.readinto()` uses `PyObject_GetBuffer()` to make sure the passed in buffer is writeable and bytes-like, drop the manual check. --- Lib/_pyio.py | 13 +++++++------ .../Library/2025-01-26-10-01-21.gh-issue-129005.ncpLvw.rst | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-01-26-10-01-21.gh-issue-129005.ncpLvw.rst diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 14961c3..023478a 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -1692,13 +1692,14 @@ class FileIO(RawIOBase): return bytes(result) - def readinto(self, b): + def readinto(self, buffer): """Same as RawIOBase.readinto().""" - m = memoryview(b).cast('B') - data = self.read(len(m)) - n = len(data) - m[:n] = data - return n + self._checkClosed() + self._checkReadable() + try: + return os.readinto(self._fd, buffer) + except BlockingIOError: + return None def write(self, b): """Write bytes b to file, return number written. diff --git a/Misc/NEWS.d/next/Library/2025-01-26-10-01-21.gh-issue-129005.ncpLvw.rst b/Misc/NEWS.d/next/Library/2025-01-26-10-01-21.gh-issue-129005.ncpLvw.rst new file mode 100644 index 0000000..a825e9d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-01-26-10-01-21.gh-issue-129005.ncpLvw.rst @@ -0,0 +1 @@ +Optimize ``_pyio.FileIO.readinto`` by avoiding unnecessary objects and copies using :func:`os.readinto`. -- cgit v0.12