blob: be5640aa590f5a2b21caee3e7a4091d1e35887ab [file] [log] [blame]
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Computes and prints the default number of concurrent links.
Computes the number of concurrent links to be run in the build, as a function
of machine spec. Based on GetDefaultConcurrentLinks in GYP.
"""
import ctypes
import optparse
import os
import re
import subprocess
import sys
def _GetTotalMemoryInBytes():
"""Gets the total amount of virtual memory in bytes.
Returns:
See above
"""
if sys.platform in ('win32', 'cygwin'):
class MEMORYSTATUSEX(ctypes.Structure):
_fields_ = [
('dwLength', ctypes.c_ulong),
('dwMemoryLoad', ctypes.c_ulong),
('ullTotalPhys', ctypes.c_ulonglong),
('ullAvailPhys', ctypes.c_ulonglong),
('ullTotalPageFile', ctypes.c_ulonglong),
('ullAvailPageFile', ctypes.c_ulonglong),
('ullTotalVirtual', ctypes.c_ulonglong),
('ullAvailVirtual', ctypes.c_ulonglong),
('sullAvailExtendedVirtual', ctypes.c_ulonglong),
]
stat = MEMORYSTATUSEX(dwLength=ctypes.sizeof(MEMORYSTATUSEX))
ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat))
return stat.ullTotalPhys
elif 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 not match:
continue
return float(match.group(1)) * 2**10
elif sys.platform == 'darwin':
try:
return int(subprocess.check_output(['sysctl', '-n', 'hw.memsize']))
except subprocess.CalledProcessError:
return 0
# TODO: Implement this for other platforms.
return 0
def _GetDefaultConcurrentLinks(mem_per_link_gb, reserve_mem_gb):
# Inherit the legacy environment variable for people that have set it in GYP.
pool_size = int(os.getenv('GYP_LINK_CONCURRENCY', 0))
if pool_size:
return pool_size
mem_total_bytes = _GetTotalMemoryInBytes()
mem_total_bytes = max(0, mem_total_bytes - reserve_mem_gb * 2**30)
num_concurrent_links = int(max(1, mem_total_bytes / mem_per_link_gb / 2**30))
hard_cap = max(1, int(os.getenv('GYP_LINK_CONCURRENCY_MAX', 2**32)))
return min(num_concurrent_links, hard_cap)
def main():
parser = optparse.OptionParser()
parser.add_option('--mem_per_link_gb', action='store', type='int', default=6)
parser.add_option('--reserve_mem_gb', action='store', type='int', default=0)
parser.disable_interspersed_args()
options, _ = parser.parse_args()
print _GetDefaultConcurrentLinks(options.mem_per_link_gb,
options.reserve_mem_gb)
return 0
if __name__ == '__main__':
sys.exit(main())