Skip to content

Commit 446a263

Browse files
authored
Use os.process_cpu_count where available (#25197)
This takes into account thread affinity, at least on python 3.13 and above. ``` $ taskset -c 0,1 ./test/runner core0 Running test_core: (1100 tests) Using 2 parallel test processes ... $ ./test/runner core0 Running test_core: (1100 tests) Using 128 parallel test processes ... ```
1 parent c4e1ed2 commit 446a263

File tree

6 files changed

+20
-10
lines changed

6 files changed

+20
-10
lines changed

test/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1843,7 +1843,7 @@ def get_library(self, name, generated_libs, configure=['sh', './configure'], #
18431843
if env_init is None:
18441844
env_init = {}
18451845
if make_args is None:
1846-
make_args = ['-j', str(shared.get_num_cores())]
1846+
make_args = ['-j', str(utils.get_num_cores())]
18471847

18481848
build_dir = self.get_build_dir()
18491849

test/parallel_testsuite.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,4 +441,4 @@ def __init__(self, co):
441441
def num_cores():
442442
if NUM_CORES:
443443
return int(NUM_CORES)
444-
return multiprocessing.cpu_count()
444+
return utils.get_num_cores()

tools/js_optimizer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ def check_symbol_mapping(p):
244244
# if we are making source maps, we want our debug numbering to start from the
245245
# top of the file, so avoid breaking the JS into chunks
246246

247-
intended_num_chunks = round(shared.get_num_cores() * NUM_CHUNKS_PER_CORE)
247+
intended_num_chunks = round(utils.get_num_cores() * NUM_CHUNKS_PER_CORE)
248248
chunk_size = min(MAX_CHUNK_SIZE, max(MIN_CHUNK_SIZE, total_size / intended_num_chunks))
249249
chunks = chunkify(funcs, chunk_size)
250250

tools/shared.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,6 @@ def run_process(cmd, check=True, input=None, *args, **kw):
115115
return ret
116116

117117

118-
def get_num_cores():
119-
return int(os.environ.get('EMCC_CORES', os.cpu_count()))
120-
121-
122118
def returncode_to_str(code):
123119
assert code != 0
124120
if code < 0:
@@ -169,7 +165,7 @@ def get_finished_process():
169165
except subprocess.TimeoutExpired:
170166
pass
171167

172-
num_parallel_processes = get_num_cores()
168+
num_parallel_processes = utils.get_num_cores()
173169
temp_files = get_temp_files()
174170
i = 0
175171
num_completed = 0

tools/system_libs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def get_top_level_ninja_file():
159159

160160

161161
def run_ninja(build_dir):
162-
cmd = ['ninja', '-C', build_dir, f'-j{shared.get_num_cores()}']
162+
cmd = ['ninja', '-C', build_dir, f'-j{utils.get_num_cores()}']
163163
if shared.PRINT_SUBPROCS:
164164
cmd.append('-v')
165165
shared.check_call(cmd, env=clean_env())
@@ -538,7 +538,7 @@ def build_objects(self, build_dir):
538538
# Choose a chunk size that is large enough to avoid too many subprocesses
539539
# but not too large to avoid task starvation.
540540
# For now the heuristic is to split inputs by 2x number of cores.
541-
chunk_size = max(1, len(objects) // (2 * shared.get_num_cores()))
541+
chunk_size = max(1, len(objects) // (2 * utils.get_num_cores()))
542542
# Convert batches to commands.
543543
for cmd, srcs in batches.items():
544544
cmd = list(cmd)

tools/utils.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,20 @@ def delete_contents(dirname, exclude=None):
112112
delete_file(entry)
113113

114114

115+
def get_num_cores():
116+
# Prefer `os.process_cpu_count` when available (3.13 and above) since
117+
# it takes into account thread affinity.
118+
# Fall back to `os.sched_getaffinity` where available and finally
119+
# `os.cpu_count`, which should work everywhere.
120+
if hasattr(os, 'process_cpu_count'):
121+
cpu_count = os.process_cpu_count()
122+
elif hasattr(os, 'sched_getaffinity'):
123+
cpu_count = len(os.sched_getaffinity(0))
124+
else:
125+
cpu_count = os.cpu_count()
126+
return int(os.environ.get('EMCC_CORES', cpu_count))
127+
128+
115129
# TODO(sbc): Replace with functools.cache, once we update to python 3.9
116130
memoize = functools.lru_cache(maxsize=None)
117131

0 commit comments

Comments
 (0)