Skip to content

Commit

Permalink
Auto merge of rust-lang#111562 - clubby789:speedup-bootstrap-py, r=jy…
Browse files Browse the repository at this point in the history
…n514

Improve startup time of bootstrap

~~If the user has a `build/host` symlink set up, we can determine the target triple by reading it rather than invoking rustc. This significantly reduces startup time of bootstrap once any kind of build has been done~~
New approach explained below
```
➜  hyperfine -p 'git checkout -q master' -N './x.py -h' -r 50
Benchmark 1: ./x.py -h
  Time (mean ± σ):     140.7 ms ±   2.6 ms    [User: 99.9 ms, System: 39.3 ms]
  Range (min … max):   136.8 ms … 149.6 ms    50 runs

➜  rust git:(master) hyperfine -p 'git checkout -q speedup-bootstrap-py' -N './x.py -h' -r 50
Benchmark 1: ./x.py -h
  Time (mean ± σ):      95.2 ms ±   1.5 ms    [User: 67.7 ms, System: 26.7 ms]
  Range (min … max):    92.9 ms …  99.6 ms    50 runs
```

Also a small microoptimisation in using string splitting rather than regex when reading toml, which saves a few more milliseconds (2-5 testing locally), but less important.

Profiling shows the remaining runtime is around half setting up the Python runtime, and the vast majority of the remaining time is spent in subprocess building and running bootstrap itself, so probably can't be improved much further.
  • Loading branch information
bors committed May 26, 2023
2 parents 1221e43 + 9a86ceb commit 917b0b6
Showing 1 changed file with 44 additions and 49 deletions.
93 changes: 44 additions & 49 deletions src/bootstrap/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,16 +226,13 @@ def format_build_time(duration):

def default_build_triple(verbose):
"""Build triple as in LLVM"""
# If the user already has a host build triple with an existing `rustc`
# install, use their preference. This fixes most issues with Windows builds
# being detected as GNU instead of MSVC.
# If we're on Windows and have an existing `rustc` toolchain, use `rustc --version --verbose`
# to find our host target triple. This fixes an issue with Windows builds being detected
# as GNU instead of MSVC.
# Otherwise, detect it via `uname`
default_encoding = sys.getdefaultencoding()

if sys.platform == 'darwin':
if verbose:
print("not using rustc detection as it is unreliable on macOS", file=sys.stderr)
print("falling back to auto-detect", file=sys.stderr)
else:
if platform_is_win32():
try:
version = subprocess.check_output(["rustc", "--version", "--verbose"],
stderr=subprocess.DEVNULL)
Expand All @@ -253,19 +250,17 @@ def default_build_triple(verbose):
print("falling back to auto-detect", file=sys.stderr)

required = not platform_is_win32()
ostype = require(["uname", "-s"], exit=required)
cputype = require(['uname', '-m'], exit=required)
uname = require(["uname", "-smp"], exit=required)

# If we do not have `uname`, assume Windows.
if ostype is None or cputype is None:
if uname is None:
return 'x86_64-pc-windows-msvc'

ostype = ostype.decode(default_encoding)
cputype = cputype.decode(default_encoding)
kernel, cputype, processor = uname.decode(default_encoding).split()

# The goal here is to come up with the same triple as LLVM would,
# at least for the subset of platforms we're willing to target.
ostype_mapper = {
kerneltype_mapper = {
'Darwin': 'apple-darwin',
'DragonFly': 'unknown-dragonfly',
'FreeBSD': 'unknown-freebsd',
Expand All @@ -275,17 +270,18 @@ def default_build_triple(verbose):
}

# Consider the direct transformation first and then the special cases
if ostype in ostype_mapper:
ostype = ostype_mapper[ostype]
elif ostype == 'Linux':
os_from_sp = subprocess.check_output(
['uname', '-o']).strip().decode(default_encoding)
if os_from_sp == 'Android':
ostype = 'linux-android'
if kernel in kerneltype_mapper:
kernel = kerneltype_mapper[kernel]
elif kernel == 'Linux':
# Apple doesn't support `-o` so this can't be used in the combined
# uname invocation above
ostype = require(["uname", "-o"], exit=required).decode(default_encoding)
if ostype == 'Android':
kernel = 'linux-android'
else:
ostype = 'unknown-linux-gnu'
elif ostype == 'SunOS':
ostype = 'pc-solaris'
kernel = 'unknown-linux-gnu'
elif kernel == 'SunOS':
kernel = 'pc-solaris'
# On Solaris, uname -m will return a machine classification instead
# of a cpu type, so uname -p is recommended instead. However, the
# output from that option is too generic for our purposes (it will
Expand All @@ -294,34 +290,34 @@ def default_build_triple(verbose):
cputype = require(['isainfo', '-k']).decode(default_encoding)
# sparc cpus have sun as a target vendor
if 'sparc' in cputype:
ostype = 'sun-solaris'
elif ostype.startswith('MINGW'):
kernel = 'sun-solaris'
elif kernel.startswith('MINGW'):
# msys' `uname` does not print gcc configuration, but prints msys
# configuration. so we cannot believe `uname -m`:
# msys1 is always i686 and msys2 is always x86_64.
# instead, msys defines $MSYSTEM which is MINGW32 on i686 and
# MINGW64 on x86_64.
ostype = 'pc-windows-gnu'
kernel = 'pc-windows-gnu'
cputype = 'i686'
if os.environ.get('MSYSTEM') == 'MINGW64':
cputype = 'x86_64'
elif ostype.startswith('MSYS'):
ostype = 'pc-windows-gnu'
elif ostype.startswith('CYGWIN_NT'):
elif kernel.startswith('MSYS'):
kernel = 'pc-windows-gnu'
elif kernel.startswith('CYGWIN_NT'):
cputype = 'i686'
if ostype.endswith('WOW64'):
if kernel.endswith('WOW64'):
cputype = 'x86_64'
ostype = 'pc-windows-gnu'
elif sys.platform == 'win32':
kernel = 'pc-windows-gnu'
elif platform_is_win32():
# Some Windows platforms might have a `uname` command that returns a
# non-standard string (e.g. gnuwin32 tools returns `windows32`). In
# these cases, fall back to using sys.platform.
return 'x86_64-pc-windows-msvc'
else:
err = "unknown OS type: {}".format(ostype)
err = "unknown OS type: {}".format(kernel)
sys.exit(err)

if cputype in ['powerpc', 'riscv'] and ostype == 'unknown-freebsd':
if cputype in ['powerpc', 'riscv'] and kernel == 'unknown-freebsd':
cputype = subprocess.check_output(
['uname', '-p']).strip().decode(default_encoding)
cputype_mapper = {
Expand Down Expand Up @@ -354,24 +350,23 @@ def default_build_triple(verbose):
cputype = cputype_mapper[cputype]
elif cputype in {'xscale', 'arm'}:
cputype = 'arm'
if ostype == 'linux-android':
ostype = 'linux-androideabi'
elif ostype == 'unknown-freebsd':
cputype = subprocess.check_output(
['uname', '-p']).strip().decode(default_encoding)
ostype = 'unknown-freebsd'
if kernel == 'linux-android':
kernel = 'linux-androideabi'
elif kernel == 'unknown-freebsd':
cputype = processor
kernel = 'unknown-freebsd'
elif cputype == 'armv6l':
cputype = 'arm'
if ostype == 'linux-android':
ostype = 'linux-androideabi'
if kernel == 'linux-android':
kernel = 'linux-androideabi'
else:
ostype += 'eabihf'
kernel += 'eabihf'
elif cputype in {'armv7l', 'armv8l'}:
cputype = 'armv7'
if ostype == 'linux-android':
ostype = 'linux-androideabi'
if kernel == 'linux-android':
kernel = 'linux-androideabi'
else:
ostype += 'eabihf'
kernel += 'eabihf'
elif cputype == 'mips':
if sys.byteorder == 'big':
cputype = 'mips'
Expand All @@ -387,14 +382,14 @@ def default_build_triple(verbose):
else:
raise ValueError('unknown byteorder: {}'.format(sys.byteorder))
# only the n64 ABI is supported, indicate it
ostype += 'abi64'
kernel += 'abi64'
elif cputype == 'sparc' or cputype == 'sparcv9' or cputype == 'sparc64':
pass
else:
err = "unknown cpu type: {}".format(cputype)
sys.exit(err)

return "{}-{}".format(cputype, ostype)
return "{}-{}".format(cputype, kernel)


@contextlib.contextmanager
Expand Down

0 comments on commit 917b0b6

Please sign in to comment.