0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-24 08:30:56 +01:00
mongodb/site_scons/site_tools/task_limiter.py
Juan Gu 855dfadef0 SERVER-94077 Use isort in Ruff configs (#27865)
GitOrigin-RevId: e793d662774ccd3ab6c3f356c2287cf1f7ff9805
2024-10-10 19:33:49 +00:00

98 lines
3.2 KiB
Python

import re
import SCons
task_limiter_patterns = {}
def setup_task_limiter(
env, name, concurrency_ratio=0.75, builders=None, source_file_regex=".*", target_file_regex=".*"
):
global task_limiter_patterns
task_limiter_patterns[name] = {}
task_limiter_patterns[name]["source"] = re.compile(source_file_regex)
task_limiter_patterns[name]["target"] = re.compile(target_file_regex)
# We need to convert the ratio value into a int that corrlates to a specific
# number of concurrent jobs allowed
concurrency_ratio = float(concurrency_ratio)
if concurrency_ratio <= 0.0:
env.FatalError(
f"The concurrency ratio for {name} must be a positive, got {max_concurrency}"
)
if concurrency_ratio > 1.0:
concurrency_ratio = 1.0
max_concurrency = env.GetOption("num_jobs") * concurrency_ratio
max_concurrency = round(max_concurrency)
if max_concurrency < 1.0:
max_concurrency = 1.0
max_concurrency = int(max_concurrency)
# A bound map of stream (as in stream of work) name to side-effect
# file. Since SCons will not allow tasks with a shared side-effect
# to execute concurrently, this gives us a way to limit link jobs
# independently of overall SCons concurrency.
concurrent_stream_map = dict()
def task_limiter_emitter(target, source, env):
global task_limiter_patterns
nonlocal name
matched = False
for s_file in source:
if re.search(task_limiter_patterns[name]["source"], s_file.path):
matched = True
break
if not matched:
for t_file in target:
if re.search(task_limiter_patterns[name]["target"], t_file.path):
matched = True
break
if matched:
se_name = f"#{name}-stream{hash(str(target[0])) % max_concurrency}"
se_node = concurrent_stream_map.get(se_name, None)
if not se_node:
se_node = env.Entry(se_name)
# This may not be necessary, but why chance it
env.NoCache(se_node)
concurrent_stream_map[se_name] = se_node
env.SideEffect(se_node, target)
return (target, source)
if isinstance(builders, dict):
for target_builder, suffixes in builders.items():
builder = env["BUILDERS"][target_builder]
emitterdict = builder.builder.emitter
for suffix in emitterdict.keys():
if suffix not in suffixes:
continue
base = emitterdict[suffix]
emitterdict[suffix] = SCons.Builder.ListEmitter(
[
base,
task_limiter_emitter,
]
)
else:
for target_builder in builders:
builder = env["BUILDERS"][target_builder]
base_emitter = builder.emitter
new_emitter = SCons.Builder.ListEmitter([base_emitter, task_limiter_emitter])
builder.emitter = new_emitter
return max_concurrency
def exists(env):
return True
def generate(env):
env.AddMethod(setup_task_limiter, "SetupTaskLimiter")