commit:     d0fa3d28c5de6a0a34ac87de5e1a463adbe58405
Author:     Sam James <sam <AT> gentoo <DOT> org>
AuthorDate: Thu Sep 29 06:37:19 2022 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Tue Oct 11 19:18:35 2022 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=d0fa3d28

binpkg: compress/decompress xz in parallel; compress zstd in parallel

- As before, needs >= xz-5.3.3_alpha for parallel decompression.
- zstd does not support parallel decompression.

Closes: https://github.com/gentoo/portage/pull/918
Signed-off-by: Sam James <sam <AT> gentoo.org>

 NEWS                                   |  7 +++++++
 bin/quickpkg                           |  8 +++++++-
 lib/_emerge/BinpkgExtractorAsync.py    |  4 ++++
 lib/portage/gpkg.py                    |  8 +++++++-
 lib/portage/package/ebuild/doebuild.py | 14 +++++++++++---
 lib/portage/util/compression_probe.py  |  6 +++---
 lib/portage/util/cpuinfo.py            | 22 +++++++++++++++++++++-
 7 files changed, 60 insertions(+), 9 deletions(-)

diff --git a/NEWS b/NEWS
index 28e8f97ca..a3591e94d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,10 @@
+portage-3.0.39 (UNRELEASED)
+--------------
+
+Features:
+* gpkg: Call xz and zstd with -T N where N is the number of jobs from 
${MAKEOPTS}
+  for parallel compression (xz & zstd) and decompression (xz with newer 
versions).
+
 portage-3.0.38.1 (2022-10-04)
 --------------
 

diff --git a/bin/quickpkg b/bin/quickpkg
index 67eee697a..9ff8d7b5a 100755
--- a/bin/quickpkg
+++ b/bin/quickpkg
@@ -36,6 +36,7 @@ from portage.exception import (
     PermissionDenied,
 )
 from portage.util import ensure_dirs, shlex_split, varexpand, _xattr
+from portage.util.cpuinfo import makeopts_to_job_count
 
 xattr = _xattr.xattr
 from portage._sets import load_default_config, SETPREFIX
@@ -168,7 +169,12 @@ def quickpkg_atom(options, infos, arg, eout):
                         % (binpkg_compression, missing_package)
                     )
                     return 1
-                cmd = shlex_split(varexpand(compression["compress"], 
mydict=settings))
+
+                cmd = compression["compress"].replace(
+                    "{JOBS}",
+                    str(makeopts_to_job_count(settings.get("MAKEOPTS", "1"))),
+                )
+                cmd = shlex_split(varexpand(cmd, mydict=settings))
                 # Filter empty elements that make Popen fail
                 cmd = [x for x in cmd if x != ""]
                 with open(binpkg_tmpfile, "wb") as fobj:

diff --git a/lib/_emerge/BinpkgExtractorAsync.py 
b/lib/_emerge/BinpkgExtractorAsync.py
index 919837fc1..65b383998 100644
--- a/lib/_emerge/BinpkgExtractorAsync.py
+++ b/lib/_emerge/BinpkgExtractorAsync.py
@@ -10,6 +10,7 @@ from portage.util.compression_probe import (
     compression_probe,
     _compressors,
 )
+from portage.util.cpuinfo import makeopts_to_job_count
 from portage.process import find_binary
 from portage.util import (
     shlex_split,
@@ -53,6 +54,9 @@ class BinpkgExtractorAsync(SpawnProcess):
         decomp = _compressors.get(compression_probe(self.pkg_path))
         if decomp is not None:
             decomp_cmd = decomp.get("decompress")
+            decomp_cmd = decomp_cmd.replace(
+                "{JOBS}", str(makeopts_to_job_count(self.env.get("MAKEOPTS", 
"1")))
+            )
         elif tarfile.is_tarfile(
             portage._unicode_encode(
                 self.pkg_path, encoding=portage._encodings["fs"], 
errors="strict"

diff --git a/lib/portage/gpkg.py b/lib/portage/gpkg.py
index 7e1b98370..1f8fa1fd3 100644
--- a/lib/portage/gpkg.py
+++ b/lib/portage/gpkg.py
@@ -38,6 +38,7 @@ from portage.util._urlopen import urlopen
 from portage.util import writemsg
 from portage.util import shlex_split, varexpand
 from portage.util.compression_probe import _compressors
+from portage.util.cpuinfo import makeopts_to_job_count
 from portage.process import find_binary
 from portage.const import MANIFEST2_HASH_DEFAULTS, HASHING_BLOCKSIZE
 
@@ -1787,7 +1788,12 @@ class gpkg:
         if mode not in compressor:
             raise InvalidCompressionMethod("{}: {}".format(compression, mode))
 
-        cmd = shlex_split(varexpand(compressor[mode], mydict=self.settings))
+        cmd = compressor[mode]
+        cmd = cmd.replace(
+            "{JOBS}", str(makeopts_to_job_count(self.settings.get("MAKEOPTS", 
"1")))
+        )
+        cmd = shlex_split(varexpand(cmd, mydict=self.settings))
+
         # Filter empty elements that make Popen fail
         cmd = [x for x in cmd if x != ""]
 

diff --git a/lib/portage/package/ebuild/doebuild.py 
b/lib/portage/package/ebuild/doebuild.py
index d0d134b39..4f7049c21 100644
--- a/lib/portage/package/ebuild/doebuild.py
+++ b/lib/portage/package/ebuild/doebuild.py
@@ -111,7 +111,7 @@ from portage.util import (
     writemsg_stdout,
     write_atomic,
 )
-from portage.util.cpuinfo import get_cpu_count
+from portage.util.cpuinfo import get_cpu_count, makeopts_to_job_count
 from portage.util.lafilefixer import rewrite_lafile
 from portage.util.compression_probe import _compressors
 from portage.util.futures import asyncio
@@ -667,8 +667,12 @@ def doebuild_environment(
                 mysettings["PORTAGE_COMPRESSION_COMMAND"] = "cat"
         else:
             try:
+                compression_binary = compression["compress"].replace(
+                    "{JOBS}",
+                    str(makeopts_to_job_count(mysettings.get("MAKEOPTS", 
"1"))),
+                )
                 compression_binary = shlex_split(
-                    varexpand(compression["compress"], mydict=settings)
+                    varexpand(compression_binary, mydict=settings)
                 )[0]
             except IndexError as e:
                 writemsg(
@@ -683,9 +687,13 @@ def doebuild_environment(
                         % (binpkg_compression, missing_package)
                     )
                 else:
+                    compression_binary = compression["compress"].replace(
+                        "{JOBS}",
+                        str(makeopts_to_job_count(mysettings.get("MAKEOPTS", 
"1"))),
+                    )
                     cmd = [
                         varexpand(x, mydict=settings)
-                        for x in shlex_split(compression["compress"])
+                        for x in shlex_split(compression_binary)
                     ]
                     # Filter empty elements
                     cmd = [x for x in cmd if x != ""]

diff --git a/lib/portage/util/compression_probe.py 
b/lib/portage/util/compression_probe.py
index 423e786bf..bbff5a3c6 100644
--- a/lib/portage/util/compression_probe.py
+++ b/lib/portage/util/compression_probe.py
@@ -37,12 +37,12 @@ _compressors = {
         "package": "app-arch/lzop",
     },
     "xz": {
-        "compress": "xz ${BINPKG_COMPRESS_FLAGS}",
-        "decompress": "xz -d",
+        "compress": "xz -T{JOBS} ${BINPKG_COMPRESS_FLAGS}",
+        "decompress": "xz -T{JOBS} -d",
         "package": "app-arch/xz-utils",
     },
     "zstd": {
-        "compress": "zstd ${BINPKG_COMPRESS_FLAGS}",
+        "compress": "zstd -T{JOBS} ${BINPKG_COMPRESS_FLAGS}",
         # If the compression windowLog was larger than the default of 27,
         # then --long=windowLog needs to be passed to the decompressor.
         # Therefore, pass a larger --long=31 value to the decompressor

diff --git a/lib/portage/util/cpuinfo.py b/lib/portage/util/cpuinfo.py
index 3cbc5b650..77529bcda 100644
--- a/lib/portage/util/cpuinfo.py
+++ b/lib/portage/util/cpuinfo.py
@@ -1,7 +1,9 @@
 # Copyright 2015-2019 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
-__all__ = ["get_cpu_count"]
+import re
+
+__all__ = ["get_cpu_count", "makeopts_to_job_count"]
 
 # Before you set out to change this function, figure out what you're really
 # asking:
@@ -48,3 +50,21 @@ def get_cpu_count():
         return multiprocessing.cpu_count()
     except (ImportError, NotImplementedError):
         return None
+
+
+def makeopts_to_job_count(makeopts):
+    """
+    Parse the job count (-jN) from MAKEOPTS. Python version of
+    bin/isolated-functions.sh's ___makeopts_jobs().
+
+    @return: Number of jobs to run or number of CPUs if none set.
+    """
+    if not makeopts:
+        return get_cpu_count()
+
+    jobs = re.match(r".*(j|--jobs=\s)\s*([0-9]+)", makeopts)
+
+    if not jobs:
+        return get_cpu_count()
+
+    return jobs.groups()[1]

Reply via email to