Files
2026-06-17 16:56:00 +00:00

88 lines
4.7 KiB
CMake

# Limit compiler/linker job concurrency to avoid OOMs on subtrees where compilation/linking is memory-intensive.
#
# Usage from CMake:
# set (MAX_COMPILER_MEMORY 2000 CACHE INTERNAL "") # megabyte
# set (MAX_LINKER_MEMORY 5000 CACHE INTERNAL "") # megabyte
# include (cmake/limit_jobs.cmake)
#
# (bigger values mean fewer jobs)
cmake_host_system_information(RESULT TOTAL_PHYSICAL_MEMORY QUERY TOTAL_PHYSICAL_MEMORY)
cmake_host_system_information(RESULT NUMBER_OF_LOGICAL_CORES QUERY NUMBER_OF_LOGICAL_CORES)
# Set to disable the automatic job-limiting
option(PARALLEL_COMPILE_JOBS "Maximum number of concurrent compilation jobs" OFF)
option(PARALLEL_LINK_JOBS "Maximum number of concurrent link jobs" OFF)
if (NOT PARALLEL_COMPILE_JOBS AND MAX_COMPILER_MEMORY)
math(EXPR PARALLEL_COMPILE_JOBS ${TOTAL_PHYSICAL_MEMORY}/${MAX_COMPILER_MEMORY})
if (NOT PARALLEL_COMPILE_JOBS)
set (PARALLEL_COMPILE_JOBS 1)
endif ()
if (PARALLEL_COMPILE_JOBS LESS NUMBER_OF_LOGICAL_CORES)
message("The auto-calculated compile jobs limit (${PARALLEL_COMPILE_JOBS}) underutilizes CPU cores (${NUMBER_OF_LOGICAL_CORES}). Set PARALLEL_COMPILE_JOBS to override.")
elseif (PARALLEL_COMPILE_JOBS GREATER NUMBER_OF_LOGICAL_CORES)
message("The auto-calculated compile jobs limit (${PARALLEL_COMPILE_JOBS}) exceeds CPU cores (${NUMBER_OF_LOGICAL_CORES}). Overriding PARALLEL_COMPILE_JOBS to ${NUMBER_OF_LOGICAL_CORES}.")
set (PARALLEL_COMPILE_JOBS ${NUMBER_OF_LOGICAL_CORES})
endif()
endif()
if (NOT PARALLEL_LINK_JOBS AND MAX_LINKER_MEMORY)
math(EXPR PARALLEL_LINK_JOBS ${TOTAL_PHYSICAL_MEMORY}/${MAX_LINKER_MEMORY})
if (NOT PARALLEL_LINK_JOBS)
set (PARALLEL_LINK_JOBS 1)
endif ()
if (PARALLEL_LINK_JOBS LESS NUMBER_OF_LOGICAL_CORES)
message("The auto-calculated link jobs limit (${PARALLEL_LINK_JOBS}) underutilizes CPU cores (${NUMBER_OF_LOGICAL_CORES}). Set PARALLEL_LINK_JOBS to override.")
elseif (PARALLEL_LINK_JOBS GREATER NUMBER_OF_LOGICAL_CORES)
message("The auto-calculated link jobs limit (${PARALLEL_LINK_JOBS}) exceeds CPU cores (${NUMBER_OF_LOGICAL_CORES}). Overriding PARALLEL_LINK_JOBS to ${NUMBER_OF_LOGICAL_CORES}.")
set (PARALLEL_LINK_JOBS ${NUMBER_OF_LOGICAL_CORES})
endif()
endif ()
# ThinLTO provides its own parallel linking
# (which is enabled only for RELWITHDEBINFO)
#
# But use 2 parallel jobs, since:
# - this is what llvm does
# - and I've verfied that lld-11 does not use all available CPU time (in peak) while linking one binary
#
# Each ThinLTO link of a large binary (clickhouse, standalone keeper) can use
# ~100 GB RAM when debug info is kept (-g), so don't run more concurrent LTO
# links than physically fit in memory - otherwise the linker is OOM-killed.
# With debug info disabled (-g0, DISABLE_ALL_DEBUG_SYMBOLS) a link needs only
# ~50 GB, so two still fit and we keep them parallel.
if (CMAKE_BUILD_TYPE_UC STREQUAL "RELWITHDEBINFO" AND ENABLE_THINLTO AND PARALLEL_LINK_JOBS GREATER 1)
if (DISABLE_ALL_DEBUG_SYMBOLS)
set (MAX_THINLTO_LINK_MEMORY 51200) # megabytes per concurrent ThinLTO link, measured ~49 GB with -g0
else ()
set (MAX_THINLTO_LINK_MEMORY 102400) # megabytes per concurrent ThinLTO link, measured ~100 GB with -g
endif ()
math (EXPR THINLTO_LINK_JOBS "${TOTAL_PHYSICAL_MEMORY} / ${MAX_THINLTO_LINK_MEMORY}")
if (THINLTO_LINK_JOBS LESS 1)
set (THINLTO_LINK_JOBS 1)
elseif (THINLTO_LINK_JOBS GREATER 2)
set (THINLTO_LINK_JOBS 2) # 2 is plenty; ThinLTO is already internally parallel
endif ()
if (THINLTO_LINK_JOBS LESS PARALLEL_LINK_JOBS)
message(STATUS "ThinLTO provides its own parallel linking - limiting parallel link jobs to ${THINLTO_LINK_JOBS} (system has ${TOTAL_PHYSICAL_MEMORY} MB RAM, ~${MAX_THINLTO_LINK_MEMORY} MB per link).")
set (PARALLEL_LINK_JOBS ${THINLTO_LINK_JOBS})
endif ()
endif()
message(STATUS "Building sub-tree with ${PARALLEL_COMPILE_JOBS} compile jobs and ${PARALLEL_LINK_JOBS} linker jobs (system: ${NUMBER_OF_LOGICAL_CORES} cores, ${TOTAL_PHYSICAL_MEMORY} MB RAM, 'OFF' means the native core count).")
if (PARALLEL_COMPILE_JOBS LESS NUMBER_OF_LOGICAL_CORES)
set(CMAKE_JOB_POOL_COMPILE compile_job_pool${CMAKE_CURRENT_SOURCE_DIR})
string (REGEX REPLACE "[^a-zA-Z0-9]+" "_" CMAKE_JOB_POOL_COMPILE ${CMAKE_JOB_POOL_COMPILE})
set_property(GLOBAL APPEND PROPERTY JOB_POOLS ${CMAKE_JOB_POOL_COMPILE}=${PARALLEL_COMPILE_JOBS})
endif ()
if (PARALLEL_LINK_JOBS LESS NUMBER_OF_LOGICAL_CORES)
set(CMAKE_JOB_POOL_LINK link_job_pool${CMAKE_CURRENT_SOURCE_DIR})
string (REGEX REPLACE "[^a-zA-Z0-9]+" "_" CMAKE_JOB_POOL_LINK ${CMAKE_JOB_POOL_LINK})
set_property(GLOBAL APPEND PROPERTY JOB_POOLS ${CMAKE_JOB_POOL_LINK}=${PARALLEL_LINK_JOBS})
endif ()