From f4bac8396b9661dca11de2e77d015647ca2d780f Mon Sep 17 00:00:00 2001 From: rmorotti Date: Thu, 27 Jun 2024 15:43:51 +0100 Subject: [PATCH 1/4] PERF: extract files from wheel in 1MB blocks and skip empty files --- src/pip/_internal/operations/install/wheel.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pip/_internal/operations/install/wheel.py b/src/pip/_internal/operations/install/wheel.py index a02a193d226..9815683aabe 100644 --- a/src/pip/_internal/operations/install/wheel.py +++ b/src/pip/_internal/operations/install/wheel.py @@ -377,9 +377,11 @@ def save(self) -> None: zipinfo = self._getinfo() - with self._zip_file.open(zipinfo) as f: - with open(self.dest_path, "wb") as dest: - shutil.copyfileobj(f, dest) + with open(self.dest_path, "wb") as dest: + if zipinfo.file_size > 0: + with self._zip_file.open(zipinfo) as f: + blocksize = min(zipinfo.file_size, 1048576) + shutil.copyfileobj(f, dest, blocksize) if zip_item_is_executable(zipinfo): set_extracted_file_to_default_mode_plus_executable(self.dest_path) From 1b8d2c8db293d6911c21994a8023010d696f6ffd Mon Sep 17 00:00:00 2001 From: rmorotti Date: Fri, 28 Jun 2024 09:36:15 +0100 Subject: [PATCH 2/4] add comment --- src/pip/_internal/operations/install/wheel.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pip/_internal/operations/install/wheel.py b/src/pip/_internal/operations/install/wheel.py index 9815683aabe..a33d6faf304 100644 --- a/src/pip/_internal/operations/install/wheel.py +++ b/src/pip/_internal/operations/install/wheel.py @@ -377,10 +377,12 @@ def save(self) -> None: zipinfo = self._getinfo() + # optimization: the file is created by open(), + # skip the decompression when there is 0 bytes to decompress. with open(self.dest_path, "wb") as dest: if zipinfo.file_size > 0: with self._zip_file.open(zipinfo) as f: - blocksize = min(zipinfo.file_size, 1048576) + blocksize = min(zipinfo.file_size, 1_048_576) shutil.copyfileobj(f, dest, blocksize) if zip_item_is_executable(zipinfo): From e2577ea3e29e5a3c13327320a3929b0e5557b5cc Mon Sep 17 00:00:00 2001 From: rmorotti Date: Fri, 28 Jun 2024 10:10:05 +0100 Subject: [PATCH 3/4] add news item --- news/12803.bugfix.rst | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 news/12803.bugfix.rst diff --git a/news/12803.bugfix.rst b/news/12803.bugfix.rst new file mode 100644 index 00000000000..4193d33e05c --- /dev/null +++ b/news/12803.bugfix.rst @@ -0,0 +1,4 @@ +Improve pip install performance. Files are now extracted in 1MB blocks, +or in one block matching the file size for smaller files. +A decompressor is no longer instantiated when extracting 0 bytes files, +it is not necessary because there is no data to decompress. From 52cb3827ccc1a3151a579f81199433588f7ee442 Mon Sep 17 00:00:00 2001 From: rmorotti Date: Mon, 1 Jul 2024 10:44:05 +0100 Subject: [PATCH 4/4] reformat 1048576 as 1024 * 1024 --- src/pip/_internal/operations/install/wheel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pip/_internal/operations/install/wheel.py b/src/pip/_internal/operations/install/wheel.py index a33d6faf304..c7d9c09cc65 100644 --- a/src/pip/_internal/operations/install/wheel.py +++ b/src/pip/_internal/operations/install/wheel.py @@ -382,7 +382,7 @@ def save(self) -> None: with open(self.dest_path, "wb") as dest: if zipinfo.file_size > 0: with self._zip_file.open(zipinfo) as f: - blocksize = min(zipinfo.file_size, 1_048_576) + blocksize = min(zipinfo.file_size, 1024 * 1024) shutil.copyfileobj(f, dest, blocksize) if zip_item_is_executable(zipinfo):