Skip to content

Commit 3bb5ac2

Browse files
committed
build: parallelize the creation of qstr.i.last
Rather than simply invoking gcc in preprocessor mode with a list of files, use a Python script with the (python3) ThreadPoolExecutor to invoke the preprocessor in parallel. The amount of concurrency is the number of system CPUs, not the makefile "-j" parallelism setting, because there is no simple and correct way for a Python program to correctly work together with make's idea of parallelism. This reduces the build time of stm32f405 feather (a non-LTO build) from 16s to 12s on my 16-thread Ryzen machine.
1 parent 40a3d11 commit 3bb5ac2

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

py/genlast.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env python3
2+
3+
import sys
4+
from concurrent.futures import ThreadPoolExecutor
5+
import multiprocessing
6+
import threading
7+
import subprocess
8+
9+
10+
def checkoutput1(args):
11+
info = subprocess.run(args, check=True, stdout=subprocess.PIPE, input='')
12+
return info.stdout
13+
14+
idx1 = sys.argv.index('--')
15+
idx2 = sys.argv.index('--', idx1+1)
16+
check = sys.argv[1:idx1]
17+
always = sys.argv[idx1+1:idx2]
18+
command = sys.argv[idx2+1:]
19+
20+
output_lock = threading.Lock()
21+
def preprocess(fn):
22+
output = checkoutput1(command + [fn])
23+
# Ensure our output doesn't interleave with others
24+
# a threading.Lock is not a context manager object :(
25+
try:
26+
output_lock.acquire()
27+
sys.stdout.buffer.write(output)
28+
finally:
29+
output_lock.release()
30+
31+
def maybe_preprocess(fn):
32+
if subprocess.call(["grep", "-lqE", "(MP_QSTR|translate)", fn]) == 0:
33+
preprocess(fn)
34+
35+
executor = ThreadPoolExecutor(max_workers=multiprocessing.cpu_count() + 1)
36+
executor.map(maybe_preprocess, check)
37+
executor.map(preprocess, always)
38+
executor.shutdown()

py/mkrules.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ $(OBJ): | $(HEADER_BUILD)/qstrdefs.enum.h $(HEADER_BUILD)/mpversion.h
7878
# - else, process all source files ($^) [this covers "make -B" which can set $? to empty]
7979
$(HEADER_BUILD)/qstr.i.last: $(SRC_QSTR) $(SRC_QSTR_PREPROCESSOR) $(QSTR_GLOBAL_DEPENDENCIES) | $(HEADER_BUILD)/mpversion.h
8080
$(STEPECHO) "GEN $@"
81-
$(Q)grep -lE "(MP_QSTR|translate)" $(if $(filter $?,$(QSTR_GLOBAL_DEPENDENCIES)),$^,$(if $?,$?,$^)) | xargs $(CPP) $(QSTR_GEN_EXTRA_CFLAGS) $(CFLAGS) $(SRC_QSTR_PREPROCESSOR) >$(HEADER_BUILD)/qstr.i.last;
81+
$(Q)$(PYTHON3) $(PY_SRC)/genlast.py $(if $(filter $?,$(QSTR_GLOBAL_DEPENDENCIES)),$^,$(if $?,$?,$^)) -- $(SRC_QSTR_PREPROCESSOR) -- $(CPP) $(QSTR_GEN_EXTRA_CFLAGS) $(CFLAGS) >$(HEADER_BUILD)/qstr.i.last;
8282

8383
$(HEADER_BUILD)/qstr.split: $(HEADER_BUILD)/qstr.i.last $(PY_SRC)/makeqstrdefs.py
8484
$(STEPECHO) "GEN $@"

0 commit comments

Comments
 (0)