From 5da05f2707d5189432314d2ab1873206f74ceb5c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 14 Aug 2026 13:52:39 +0200 Subject: [PATCH 1/2] Reduce compile time / memory footprint of DQ --- PWGDQ/Tasks/CMakeLists.txt | 22 ++++++++++++++++++++++ PWGDQ/Tasks/tableReaderWithAssocPCH.cxx | 14 ++++++++++++++ PWGDQ/Tasks/tableReader_withAssoc.cxx | 4 ++++ 3 files changed, 40 insertions(+) create mode 100644 PWGDQ/Tasks/tableReaderWithAssocPCH.cxx diff --git a/PWGDQ/Tasks/CMakeLists.txt b/PWGDQ/Tasks/CMakeLists.txt index ff318c3dfa0..90fda23675d 100644 --- a/PWGDQ/Tasks/CMakeLists.txt +++ b/PWGDQ/Tasks/CMakeLists.txt @@ -9,6 +9,21 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. +# tableReader_withAssoc.cxx is 5000 lines of task definitions, and seven +# workflow variants below #include it verbatim -- differing only in which +# adaptAnalysisTask<> entries they list, with identical preprocessor state and +# identical link libraries. Without this it is parsed and instantiated seven +# times, and it is the heaviest thing in the PWG: a cc1plus compiling one of +# these was OOM-killed at ~8 GB RSS. +# +# Skipped under recc, which caches compilations remotely instead. +add_library(TableReaderWithAssocPCH OBJECT tableReaderWithAssocPCH.cxx) +target_link_libraries(TableReaderWithAssocPCH PUBLIC O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore O2Physics::MLCore) +if(NOT DEFINED ENV{USE_RECC}) + target_precompile_headers(TableReaderWithAssocPCH PRIVATE + [["PWGDQ/Tasks/tableReader_withAssoc.cxx"]]) +endif() + o2physics_add_dpl_workflow(table-reader SOURCES tableReader.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore O2Physics::MLCore @@ -17,36 +32,43 @@ o2physics_add_dpl_workflow(table-reader o2physics_add_dpl_workflow(table-reader-with-assoc SOURCES tableReader_withAssoc_workflowSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore O2Physics::MLCore + REUSE_FROM TableReaderWithAssocPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(table-reader-with-assoc-same-event-pairing-barrel-only SOURCES tableReader_withAssoc_SameEventPairingBarrelOnly_workflowSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore O2Physics::MLCore + REUSE_FROM TableReaderWithAssocPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(table-reader-with-assoc-same-event-pairing-muon-only SOURCES tableReader_withAssoc_SameEventPairingMuonOnly_workflowSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore O2Physics::MLCore + REUSE_FROM TableReaderWithAssocPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(table-reader-with-assoc-same-event-pairing SOURCES tableReader_withAssoc_SameEventPairing_workflowSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore O2Physics::MLCore + REUSE_FROM TableReaderWithAssocPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(table-reader-with-assoc-asymmetric-pairing SOURCES tableReader_withAssoc_AsymmetricPairing_workflowSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore O2Physics::MLCore + REUSE_FROM TableReaderWithAssocPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(table-reader-with-assoc-dilepton-track-pairing SOURCES tableReader_withAssoc_DileptonTrackPairing_workflowSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore O2Physics::MLCore + REUSE_FROM TableReaderWithAssocPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(table-reader-with-assoc-dilepton-track-track-pairing SOURCES tableReader_withAssoc_DileptonTrackTrackPairing_workflowSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore O2Physics::MLCore + REUSE_FROM TableReaderWithAssocPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(table-reader-with-assoc-direct diff --git a/PWGDQ/Tasks/tableReaderWithAssocPCH.cxx b/PWGDQ/Tasks/tableReaderWithAssocPCH.cxx new file mode 100644 index 00000000000..0575bdc8f19 --- /dev/null +++ b/PWGDQ/Tasks/tableReaderWithAssocPCH.cxx @@ -0,0 +1,14 @@ +// Copyright 2019-2026 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// Carrier for the precompiled header shared by the tableReader_withAssoc +// workflow variants; see TableReaderWithAssocPCH in this directory's +// CMakeLists.txt. It exists only to own the PCH. diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index 8574299c134..2dc98842bcd 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -12,6 +12,10 @@ // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // Configurable workflow for running several DQ or other PWG analyses +// Included verbatim by the *_workflowSpec.cxx variants and precompiled into +// TableReaderWithAssocPCH; without the guard the two collide. +#pragma once + #include "PWGDQ/Core/AnalysisCompositeCut.h" #include "PWGDQ/Core/AnalysisCut.h" #include "PWGDQ/Core/CutsLibrary.h" From 7499439563623bec1aa5a365f7721336b7e353fe Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 14 Aug 2026 10:47:32 +0200 Subject: [PATCH 2/2] Have a default PCH for framework / infrastructure headers --- Common/Core/CMakeLists.txt | 30 ++++++++++++++++++++++++++++++ Common/Core/analysisPCH.cxx | 14 ++++++++++++++ cmake/O2PhysicsAddWorkflow.cmake | 20 ++++++++++++++++++-- 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 Common/Core/analysisPCH.cxx diff --git a/Common/Core/CMakeLists.txt b/Common/Core/CMakeLists.txt index 6bf499cd3b7..431499b881b 100644 --- a/Common/Core/CMakeLists.txt +++ b/Common/Core/CMakeLists.txt @@ -24,6 +24,36 @@ o2physics_add_library(AnalysisCore FFitWeights.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsParameters ROOT::EG O2::CCDB ROOT::Physics O2::FT0Base O2::FV0Base O2::DataFormatsParamTOF) +# Precompiled header shared by DPL analysis workflows. Parsing the framework +# headers dominates the cost of a workflow translation unit, and there are +# ~1500 of them; o2physics_add_dpl_workflow reuses this by default. +# +# Skipped under recc, which caches compilations remotely instead -- the two do +# not combine, as a PCH is a local artefact of one compiler invocation. +# +# The link libraries have to match what the reusing targets compile with, so +# this carries only what every workflow already links. +add_library(AnalysisPCH OBJECT analysisPCH.cxx) +target_link_libraries(AnalysisPCH PUBLIC O2::Framework O2Physics::AnalysisCore) +if(NOT DEFINED ENV{USE_RECC}) + target_precompile_headers(AnalysisPCH PRIVATE + + + + + # NOT runDataProcessing.h. It states the contract itself: "we need to + # declare the customize method before include this file". Precompiling it + # makes it the first include in every workflow, so a source's customize() is + # never seen, its options are never registered, and the binary aborts at + # --dump-workflow with "missing option: ...". The link succeeds, so this + # surfaces as a runtime failure with no hint that a PCH caused it. + + + + + ) +endif() + o2physics_target_root_dictionary(AnalysisCore HEADERS TrackSelection.h TrackSelectionDefaults.h diff --git a/Common/Core/analysisPCH.cxx b/Common/Core/analysisPCH.cxx new file mode 100644 index 00000000000..2ee8ee5867f --- /dev/null +++ b/Common/Core/analysisPCH.cxx @@ -0,0 +1,14 @@ +// Copyright 2019-2026 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// Carrier for the precompiled header shared by DPL analysis workflows; see +// AnalysisPCH in this directory's CMakeLists.txt. It exists only to own the +// PCH, so it has no code of its own. diff --git a/cmake/O2PhysicsAddWorkflow.cmake b/cmake/O2PhysicsAddWorkflow.cmake index d2d599c4406..7be02fd7383 100644 --- a/cmake/O2PhysicsAddWorkflow.cmake +++ b/cmake/O2PhysicsAddWorkflow.cmake @@ -47,8 +47,24 @@ function(o2physics_add_dpl_workflow baseTargetName) set_property(TARGET ${targetExeName} PROPERTY JOB_POOL_COMPILE analysis) set_property(TARGET ${targetExeName} PROPERTY JOB_POOL_LINK analysis) - if(A_REUSE_FROM AND NOT DEFINED ENV{USE_RECC}) - target_precompile_headers(${targetExeName} REUSE_FROM ${A_REUSE_FROM}) + # Reuse a precompiled header. Without an explicit REUSE_FROM, fall back to the + # shared AnalysisPCH (Common/Core): a workflow translation unit spends most of + # its time parsing the framework headers, and there are ~1500 of them, so the + # default is worth more than the handful of targets that name their own. + # + # Set O2PHYSICS_DEFAULT_PCH to an empty string to opt out globally, e.g. when + # bisecting a PCH-related build failure. + if(NOT DEFINED O2PHYSICS_DEFAULT_PCH) + set(O2PHYSICS_DEFAULT_PCH AnalysisPCH) + endif() + set(_pch "${A_REUSE_FROM}") + if(NOT _pch) + set(_pch "${O2PHYSICS_DEFAULT_PCH}") + endif() + # A target cannot reuse its own PCH, and the carrier is not built when recc + # is caching compilations remotely instead. + if(_pch AND NOT _pch STREQUAL targetExeName AND NOT DEFINED ENV{USE_RECC}) + target_precompile_headers(${targetExeName} REUSE_FROM ${_pch}) endif() set(jsonFile $.json)