Skip to content

Commit 9ecda8d

Browse files
committed
Auto merge of #110427 - Nilstrieb:parallel-bootstrap-startup, r=albertlarsan68
Parallelize initial Rust download in bootstrap Parallelize the initial download of Rust in `bootstrap.py` `time ./x.py --help` after `rm -r build` Before: 33s After: 27s
2 parents f2eb9f8 + a98968e commit 9ecda8d

File tree

1 file changed

+86
-15
lines changed

1 file changed

+86
-15
lines changed

src/bootstrap/bootstrap.py

+86-15
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import tempfile
1414

1515
from time import time
16+
from multiprocessing import Pool, cpu_count
1617

1718
try:
1819
import lzma
@@ -406,6 +407,48 @@ def channel(self):
406407
return self.version + "-" + self.date
407408

408409

410+
class DownloadInfo:
411+
"""A helper class that can be pickled into a parallel subprocess"""
412+
413+
def __init__(
414+
self,
415+
base_download_url,
416+
download_path,
417+
bin_root,
418+
tarball_path,
419+
tarball_suffix,
420+
checksums_sha256,
421+
pattern,
422+
verbose,
423+
):
424+
self.base_download_url = base_download_url
425+
self.download_path = download_path
426+
self.bin_root = bin_root
427+
self.tarball_path = tarball_path
428+
self.tarball_suffix = tarball_suffix
429+
self.checksums_sha256 = checksums_sha256
430+
self.pattern = pattern
431+
self.verbose = verbose
432+
433+
def download_component(download_info):
434+
if not os.path.exists(download_info.tarball_path):
435+
get(
436+
download_info.base_download_url,
437+
download_info.download_path,
438+
download_info.tarball_path,
439+
download_info.checksums_sha256,
440+
verbose=download_info.verbose,
441+
)
442+
443+
def unpack_component(download_info):
444+
unpack(
445+
download_info.tarball_path,
446+
download_info.tarball_suffix,
447+
download_info.bin_root,
448+
match=download_info.pattern,
449+
verbose=download_info.verbose,
450+
)
451+
409452
class RustBuild(object):
410453
"""Provide all the methods required to build Rust"""
411454
def __init__(self):
@@ -460,17 +503,49 @@ def download_toolchain(self):
460503
)
461504
run_powershell([script])
462505
shutil.rmtree(bin_root)
506+
507+
key = self.stage0_compiler.date
508+
cache_dst = os.path.join(self.build_dir, "cache")
509+
rustc_cache = os.path.join(cache_dst, key)
510+
if not os.path.exists(rustc_cache):
511+
os.makedirs(rustc_cache)
512+
463513
tarball_suffix = '.tar.gz' if lzma is None else '.tar.xz'
464-
filename = "rust-std-{}-{}{}".format(
465-
rustc_channel, self.build, tarball_suffix)
466-
pattern = "rust-std-{}".format(self.build)
467-
self._download_component_helper(filename, pattern, tarball_suffix)
468-
filename = "rustc-{}-{}{}".format(rustc_channel, self.build,
469-
tarball_suffix)
470-
self._download_component_helper(filename, "rustc", tarball_suffix)
471-
filename = "cargo-{}-{}{}".format(rustc_channel, self.build,
472-
tarball_suffix)
473-
self._download_component_helper(filename, "cargo", tarball_suffix)
514+
515+
toolchain_suffix = "{}-{}{}".format(rustc_channel, self.build, tarball_suffix)
516+
517+
tarballs_to_download = [
518+
("rust-std-{}".format(toolchain_suffix), "rust-std-{}".format(self.build)),
519+
("rustc-{}".format(toolchain_suffix), "rustc"),
520+
("cargo-{}".format(toolchain_suffix), "cargo"),
521+
]
522+
523+
tarballs_download_info = [
524+
DownloadInfo(
525+
base_download_url=self.download_url,
526+
download_path="dist/{}/{}".format(self.stage0_compiler.date, filename),
527+
bin_root=self.bin_root(),
528+
tarball_path=os.path.join(rustc_cache, filename),
529+
tarball_suffix=tarball_suffix,
530+
checksums_sha256=self.checksums_sha256,
531+
pattern=pattern,
532+
verbose=self.verbose,
533+
)
534+
for filename, pattern in tarballs_to_download
535+
]
536+
537+
# Download the components serially to show the progress bars properly.
538+
for download_info in tarballs_download_info:
539+
download_component(download_info)
540+
541+
# Unpack the tarballs in parallle.
542+
# In Python 2.7, Pool cannot be used as a context manager.
543+
p = Pool(min(len(tarballs_download_info), cpu_count()))
544+
try:
545+
p.map(unpack_component, tarballs_download_info)
546+
finally:
547+
p.close()
548+
474549
if self.should_fix_bins_and_dylibs():
475550
self.fix_bin_or_dylib("{}/bin/cargo".format(bin_root))
476551

@@ -486,13 +561,9 @@ def download_toolchain(self):
486561
rust_stamp.write(key)
487562

488563
def _download_component_helper(
489-
self, filename, pattern, tarball_suffix,
564+
self, filename, pattern, tarball_suffix, rustc_cache,
490565
):
491566
key = self.stage0_compiler.date
492-
cache_dst = os.path.join(self.build_dir, "cache")
493-
rustc_cache = os.path.join(cache_dst, key)
494-
if not os.path.exists(rustc_cache):
495-
os.makedirs(rustc_cache)
496567

497568
tarball = os.path.join(rustc_cache, filename)
498569
if not os.path.exists(tarball):

0 commit comments

Comments
 (0)