blob: 5784190c2c0cf40c8353aa39ca259be471f3ba81 [file] [log] [blame]
#!/usr/bin/env python3.8
# Copyright 2019 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This script computes the number of concurrent links we want to run in the
# build as a function of the machine.
from __future__ import print_function
import argparse
import json
import multiprocessing
import os
import re
import subprocess
import sys
UNITS = {'B': 1, 'KB': 2**10, 'MB': 2**20, 'GB': 2**30, 'TB': 2**40}
def parse_size(string):
i = next(i for (i, c) in enumerate(string) if not c.isdigit())
number = string[:i].strip()
unit = string[i:].strip()
return int(float(number) * UNITS[unit])
class ParseSize(argparse.Action):
def __call__(self, parser, args, values, option_string=None):
sizes = getattr(args, self.dest, [])
for value in values:
(k, v) = value.split('=', 1)
sizes.append((k, parse_size(v)))
setattr(args, self.dest, sizes)
def get_total_memory():
if sys.platform.startswith('linux'):
if os.path.exists("/proc/meminfo"):
with open("/proc/meminfo") as meminfo:
memtotal_re = re.compile(r'^MemTotal:\s*(\d*)\s*kB')
for line in meminfo:
match = memtotal_re.match(line)
if match:
return float(match.group(1)) * 2**10
elif sys.platform == 'darwin':
try:
return int(subprocess.check_output(['sysctl', '-n', 'hw.memsize']))
except Exception:
return 0
else:
return 0
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"--memory-per-job", action=ParseSize, default=[], nargs='*')
parser.add_argument("--reserve-memory", type=parse_size, default=0)
args = parser.parse_args()
mem_total_bytes = max(0, get_total_memory() - args.reserve_memory)
try:
cpu_cap = multiprocessing.cpu_count()
except:
cpu_cap = 1
concurrent_jobs = {}
for job, memory_per_job in args.memory_per_job:
num_concurrent_jobs = int(max(1, mem_total_bytes / memory_per_job))
concurrent_jobs[job] = min(num_concurrent_jobs, cpu_cap)
print(json.dumps(concurrent_jobs))
return 0
if __name__ == '__main__':
sys.exit(main())