From c552fb49945ade5880bf0460d1163ea7dd7210aa Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 12 Feb 2026 13:47:06 +0100 Subject: [PATCH 01/38] first step to compile --- CMakeLists.txt | 5 +++- pdi/tests/CMakeLists.txt | 48 ++++++++++++++++---------------- plugins/decl_hdf5/CMakeLists.txt | 4 ++- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a44e49e5f..0cb545dbe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -286,7 +286,7 @@ endif() ## HDF5 if("${BUILD_DECL_HDF5_PLUGIN}" OR "${BUILD_DECL_NETCDF_PLUGIN}") - + find_package(HDF5 COMPONENTS C ) set(HDF5_CMAKE_CACHE_ARGS) if("${BUILD_HDF5_PARALLEL}") @@ -326,6 +326,9 @@ if("${BUILD_DECL_HDF5_PLUGIN}" OR "${BUILD_DECL_NETCDF_PLUGIN}") if("${HDF5_VERSION}" VERSION_LESS 1.10) message(FATAL_ERROR "HDF5 version 1.10 at least required, HDF5 ${HDF5_VERSION} found.") endif() + if("${HDF5_VERSION}" VERSION_GREATER_EQUAL 2.0.0) + set(HDF5_IS_PARALLEL ${HDF5_PROVIDES_PARALLEL}) + endif() if("${BUILD_HDF5_PARALLEL}" AND NOT "${HDF5_IS_PARALLEL}") message(FATAL_ERROR "You requested a parallel HDF5 build (-DBUILD_HDF5_PARALLEL=ON) but a sequential SYSTEM version has been found\n" diff --git a/pdi/tests/CMakeLists.txt b/pdi/tests/CMakeLists.txt index 8c0bd8606..9deadcbc6 100644 --- a/pdi/tests/CMakeLists.txt +++ b/pdi/tests/CMakeLists.txt @@ -75,32 +75,32 @@ add_executable(PDI_unit_tests PDI_tuple_datatype.cxx ) -set(OPERAND_TYPES uint8_t int64_t float double) -foreach(OPERAND1_TYPE IN LISTS OPERAND_TYPES) - foreach(OPERAND2_TYPE IN LISTS OPERAND_TYPES) - string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") - configure_file(expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) - target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") - endforeach() -endforeach() +# set(OPERAND_TYPES uint8_t int64_t float double) +# foreach(OPERAND1_TYPE IN LISTS OPERAND_TYPES) +# foreach(OPERAND2_TYPE IN LISTS OPERAND_TYPES) +# string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") +# configure_file(expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) +# target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") +# endforeach() +# endforeach() -set(PARSEABLE_OPERAND_TYPES long double) -foreach(OPERAND1_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) - foreach(OPERAND2_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) - string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") - configure_file(parsed_expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) - target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") - endforeach() -endforeach() +# set(PARSEABLE_OPERAND_TYPES long double) +# foreach(OPERAND1_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) +# foreach(OPERAND2_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) +# string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") +# configure_file(parsed_expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) +# target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") +# endforeach() +# endforeach() -set(MODULABLE_OPERAND_TYPES uint8_t int64_t) -foreach(OPERAND1_TYPE IN LISTS MODULABLE_OPERAND_TYPES) - foreach(OPERAND2_TYPE IN LISTS MODULABLE_OPERAND_TYPES) - string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") - configure_file(modulo.cxx "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) - target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") - endforeach() -endforeach() +# set(MODULABLE_OPERAND_TYPES uint8_t int64_t) +# foreach(OPERAND1_TYPE IN LISTS MODULABLE_OPERAND_TYPES) +# foreach(OPERAND2_TYPE IN LISTS MODULABLE_OPERAND_TYPES) +# string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") +# configure_file(modulo.cxx "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) +# target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") +# endforeach() +# endforeach() target_compile_features(PDI_unit_tests PRIVATE cxx_std_17) target_link_libraries(PDI_unit_tests PDI::PDI_plugins Threads::Threads GTest::gtest GTest::gtest_main GTest::gmock GTest::gmock_main) diff --git a/plugins/decl_hdf5/CMakeLists.txt b/plugins/decl_hdf5/CMakeLists.txt index 970eba144..0f3142f81 100644 --- a/plugins/decl_hdf5/CMakeLists.txt +++ b/plugins/decl_hdf5/CMakeLists.txt @@ -51,7 +51,9 @@ find_package(HDF5 REQUIRED COMPONENTS C) if("${HDF5_VERSION}" VERSION_LESS 1.10) message(FATAL_ERROR "HDF5 version 1.10 at least required, HDF5 ${HDF5_VERSION} found.") endif() - +if("${HDF5_VERSION}" VERSION_GREATER_EQUAL 2.0.0) + set(HDF5_IS_PARALLEL ${HDF5_PROVIDES_PARALLEL}) +endif() if("${BUILD_HDF5_PARALLEL}" AND NOT "${HDF5_IS_PARALLEL}") message(FATAL_ERROR "Parallel HDF5 required, sequential HDF5 only found. Please set -DBUILD_HDF5_PARALLEL=OFF to disable parallel HDF5") endif() From d0f35402a6e138b4e1f2e1d23cde0f00fddaf6ed Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 12 Mar 2026 15:42:02 +0100 Subject: [PATCH 02/38] add a timer class --- pdi/include/pdi/timer.h | 76 +++++++++++++++++++++++++++++++++++++++++ pdi/src/timer.cxx | 72 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 pdi/include/pdi/timer.h create mode 100644 pdi/src/timer.cxx diff --git a/pdi/include/pdi/timer.h b/pdi/include/pdi/timer.h new file mode 100644 index 000000000..ff456cfad --- /dev/null +++ b/pdi/include/pdi/timer.h @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (C) 2015-2019 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of CEA nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#ifndef PDI_TIMER_H_ +#define PDI_TIMER_H_ + +#include +// #include +#include +#include +#include +// #include +#include + +// #include +// #include + +#include +// #include +namespace PDI { + +class PDI_EXPORT TimerManager { +public: + // Delete copy constructor and assignment + TimerManager(const TimerManager&) = delete; + void operator=(const TimerManager&) = delete; + + static TimerManager& getInstance(); + + void startTimer(const std::string& name); + void stopTimer(const std::string& name); + void printReport() const ; + void printReport(const std::string& name) const; + + const std::map& getResults(); + +private: + TimerManager() {} // Private Constructor + + std::map start_times; + std::map accumulated_times; +}; +} +#ifdef WITH_TIMER_REPORT + #define START_TIMER(name) PDI::TimerManager::getInstance().startTimer(name) + #define STOP_TIMER(name) PDI::TimerManager::getInstance().stopTimer(name) + #define PRINT_TIMER_REPORT() PDI::TimerManager::getInstance().printReport() +#else + #define START_TIMER(name) + #define STOP_TIMER(name) + #define PRINT_TIMER_REPORT() +#endif + + +#endif // PDI_TIMER_H_ diff --git a/pdi/src/timer.cxx b/pdi/src/timer.cxx new file mode 100644 index 000000000..c65eda28d --- /dev/null +++ b/pdi/src/timer.cxx @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (C) 2015-2019 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of CEA nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include +namespace PDI { + + + TimerManager& TimerManager::getInstance() { + static TimerManager instance; + return instance; + } + + // Start a timer by name + void TimerManager::startTimer(const std::string& name) { + start_times[name] = std::chrono::high_resolution_clock::now(); + } + + // Stop a timer and accumulate the duration + void TimerManager::stopTimer(const std::string& name) { + auto end_time = std::chrono::high_resolution_clock::now(); + + if (start_times.find(name) != start_times.end()) { + std::chrono::duration elapsed = end_time - start_times[name]; + accumulated_times[name] += elapsed.count(); + } + } + + // Export the results + void TimerManager::printReport() const { + std::cout << "\n--- Full Timer Report ---"<<&accumulated_times<second << " seconds" << std::endl; + } else { + std::cout << name << " timer not found." << std::endl; + } + } + + // Get the map directly (useful for MPI export) + const std::map& TimerManager::getResults() { + return accumulated_times; + } +} \ No newline at end of file From 925f48926bd82b60e55329f1445d451d0a0a1c02 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 12 Mar 2026 15:42:53 +0100 Subject: [PATCH 03/38] add timer for pdi init and finalize --- pdi/CMakeLists.txt | 4 ++++ pdi/src/pdi.cxx | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/pdi/CMakeLists.txt b/pdi/CMakeLists.txt index ace8475de..2e2809f6b 100644 --- a/pdi/CMakeLists.txt +++ b/pdi/CMakeLists.txt @@ -159,6 +159,7 @@ set(PDI_C_SRC src/ref_any.cxx src/scalar_datatype.cxx src/string_tools.cxx + src/timer.cxx src/tuple_datatype.cxx ) add_library(PDI_C ${PDI_C_SRC}) @@ -170,6 +171,9 @@ target_link_libraries(PDI_C PUBLIC paraconf::paraconf ${CMAKE_DL_LIBS} PRIVATE spdlog::spdlog) target_compile_features(PDI_C PRIVATE cxx_std_17 c_std_11) +if(WITH_TIMER_REPORT) + target_compile_definitions(PDI_C PUBLIC WITH_TIMER_REPORT) +endif() set_property(TARGET PDI_C PROPERTY LIBRARY_OUTPUT_NAME "pdi") set_property(TARGET PDI_C PROPERTY ENABLE_EXPORTS TRUE) set_property(TARGET PDI_C PROPERTY C_VISIBILITY_PRESET hidden) diff --git a/pdi/src/pdi.cxx b/pdi/src/pdi.cxx index 2b9824ca4..09c7336e8 100644 --- a/pdi/src/pdi.cxx +++ b/pdi/src/pdi.cxx @@ -42,6 +42,7 @@ #include "pdi/paraconf_wrapper.h" #include "pdi/plugin.h" #include "pdi/ref_any.h" +#include "pdi/timer.h" #include "global_context.h" @@ -167,6 +168,7 @@ PDI_errhandler_t PDI_errhandler(PDI_errhandler_t new_handler) PDI_status_t PDI_init(PC_tree_t conf) try { + START_TIMER("PDI"); Paraconf_wrapper fw; g_transaction.clear(); g_transaction_data.clear(); @@ -186,6 +188,8 @@ try { g_transaction.clear(); g_transaction_data.clear(); Global_context::finalize(); + STOP_TIMER("PDI"); + PRINT_TIMER_REPORT(); return PDI_OK; } catch (const Error& e) { return g_error_context.return_err(e); From f64e41f96fef5f68d25d4e96d63c8abb2f810073 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 12 Mar 2026 15:44:12 +0100 Subject: [PATCH 04/38] add timer option in cmake --- CMakeLists.txt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cb545dbe..c0114e871 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,8 +76,7 @@ option(BUILD_SHARED_LIBS "Build shared libraries rather than static ones" option(BUILD_TRACE_PLUGIN "Build Trace plugin" ON) option(BUILD_USER_CODE_PLUGIN "Build User-code plugin" ON) option(BUILD_JSON_PLUGIN "Build JSON plugin" OFF) - - +option(WITH_TIMER_REPORT "Enable timer" ON) ### Default build type @@ -308,7 +307,7 @@ if("${BUILD_DECL_HDF5_PLUGIN}" OR "${BUILD_DECL_NETCDF_PLUGIN}") sbuild_add_dependency(HDF5 "${USE_DEFAULT}" EMBEDDED_PATH "vendor/hdf5-1.12.3" COMPONENTS ${HDF5_COMPONENTS} - MODULE_VARS HDF5_IS_PARALLEL HDF5_VERSION + MODULE_VARS HDF5_IS_PARALLEL HDF5_PROVIDES_PARALLEL HDF5_VERSION CMAKE_CACHE_ARGS -DBUILD_STATIC_LIBS:BOOL=OFF -DBUILD_TESTING:BOOL=OFF @@ -327,7 +326,7 @@ if("${BUILD_DECL_HDF5_PLUGIN}" OR "${BUILD_DECL_NETCDF_PLUGIN}") message(FATAL_ERROR "HDF5 version 1.10 at least required, HDF5 ${HDF5_VERSION} found.") endif() if("${HDF5_VERSION}" VERSION_GREATER_EQUAL 2.0.0) - set(HDF5_IS_PARALLEL ${HDF5_PROVIDES_PARALLEL}) + set(HDF5_IS_PARALLEL "${HDF5_PROVIDES_PARALLEL}") endif() if("${BUILD_HDF5_PARALLEL}" AND NOT "${HDF5_IS_PARALLEL}") message(FATAL_ERROR From 2771711b37a672a0ce4765b88e794092bb1488d2 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 12 Mar 2026 15:46:07 +0100 Subject: [PATCH 05/38] add timer for hdf5 --- plugins/decl_hdf5/CMakeLists.txt | 7 +++++-- plugins/decl_hdf5/decl_hdf5.cxx | 7 ++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/plugins/decl_hdf5/CMakeLists.txt b/plugins/decl_hdf5/CMakeLists.txt index 0f3142f81..e25655e87 100644 --- a/plugins/decl_hdf5/CMakeLists.txt +++ b/plugins/decl_hdf5/CMakeLists.txt @@ -52,7 +52,7 @@ if("${HDF5_VERSION}" VERSION_LESS 1.10) message(FATAL_ERROR "HDF5 version 1.10 at least required, HDF5 ${HDF5_VERSION} found.") endif() if("${HDF5_VERSION}" VERSION_GREATER_EQUAL 2.0.0) - set(HDF5_IS_PARALLEL ${HDF5_PROVIDES_PARALLEL}) + set(HDF5_IS_PARALLEL "${HDF5_PROVIDES_PARALLEL}") endif() if("${BUILD_HDF5_PARALLEL}" AND NOT "${HDF5_IS_PARALLEL}") message(FATAL_ERROR "Parallel HDF5 required, sequential HDF5 only found. Please set -DBUILD_HDF5_PARALLEL=OFF to disable parallel HDF5") @@ -60,7 +60,7 @@ endif() set(HDF5_DEPS hdf5::hdf5) # MPI -if("${HDF5_IS_PARALLEL}") +if("${HDF5_IS_PARALLEL}" OR "${HDF5_PROVIDES_PARALLEL}") if("${BUILD_TESTING}" AND "${BUILD_FORTRAN}") set(MPI_COMPONENTS Fortran) endif() @@ -83,6 +83,9 @@ add_library(pdi_decl_hdf5_plugin MODULE target_link_libraries(pdi_decl_hdf5_plugin PUBLIC PDI::PDI_plugins ${HDF5_DEPS}) set_target_properties(pdi_decl_hdf5_plugin PROPERTIES CXX_VISIBILITY_PRESET hidden) +if(WITH_TIMER_REPORT) + target_compile_definitions(pdi_decl_hdf5_plugin PUBLIC WITH_TIMER_REPORT) +endif() # installation set(INSTALL_PDIPLUGINDIR "${PDI_DEFAULT_PLUGINDIR}" CACHE PATH "PDI plugins (${PDI_DEFAULT_PLUGINDIR})") install(TARGETS pdi_decl_hdf5_plugin diff --git a/plugins/decl_hdf5/decl_hdf5.cxx b/plugins/decl_hdf5/decl_hdf5.cxx index 6a910d6ed..5af49cc39 100644 --- a/plugins/decl_hdf5/decl_hdf5.cxx +++ b/plugins/decl_hdf5/decl_hdf5.cxx @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2015-2019 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2015-2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * Copyright (C) 2021 Institute of Bioorganic Chemistry Polish Academy of Science (PSNC) * All rights reserved. * @@ -39,6 +39,7 @@ #include #include #include +#include #include "file_op.h" #include "hdf5_wrapper.h" @@ -114,18 +115,22 @@ class decl_hdf5_plugin: public Plugin void data(const std::string& name, Ref ref) { + START_TIMER(pretty_name()); Hdf5_error_handler _; for (auto&& op: m_data[name]) { op.execute(context()); } + STOP_TIMER(pretty_name()); } void event(const std::string& event) { + START_TIMER(pretty_name()); Hdf5_error_handler _; for (auto&& op: m_events[event]) { op.execute(context()); } + STOP_TIMER(pretty_name()); } /** Pretty name for the plugin that will be shown in the logger From 01c5e3feb2244b05127b3708b7625b09d871cc82 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 12 Mar 2026 15:47:51 +0100 Subject: [PATCH 06/38] add timer for netcdf --- plugins/decl_netcdf/CMakeLists.txt | 4 +++- plugins/decl_netcdf/cmake/FindNetCDF.cmake | 2 +- plugins/decl_netcdf/dnc_file_context.cxx | 4 ++++ plugins/decl_netcdf/dnc_file_context.h | 3 ++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/plugins/decl_netcdf/CMakeLists.txt b/plugins/decl_netcdf/CMakeLists.txt index 96e14ed4d..f28a85b05 100644 --- a/plugins/decl_netcdf/CMakeLists.txt +++ b/plugins/decl_netcdf/CMakeLists.txt @@ -70,7 +70,9 @@ if("${BUILD_NETCDF_PARALLEL}") target_link_libraries(pdi_decl_netcdf_plugin PUBLIC MPI::MPI_CXX) endif() set_target_properties(pdi_decl_netcdf_plugin PROPERTIES CXX_VISIBILITY_PRESET hidden) - +if(WITH_TIMER_REPORT) + target_compile_definitions(pdi_decl_netcdf_plugin PUBLIC WITH_TIMER_REPORT) +endif() # installation set(INSTALL_PDIPLUGINDIR "${PDI_DEFAULT_PLUGINDIR}" CACHE PATH "PDI plugins (${PDI_DEFAULT_PLUGINDIR})") install(TARGETS pdi_decl_netcdf_plugin diff --git a/plugins/decl_netcdf/cmake/FindNetCDF.cmake b/plugins/decl_netcdf/cmake/FindNetCDF.cmake index 0cdd109d5..b1465e884 100644 --- a/plugins/decl_netcdf/cmake/FindNetCDF.cmake +++ b/plugins/decl_netcdf/cmake/FindNetCDF.cmake @@ -369,7 +369,7 @@ if("${NetCDF_FOUND}") if("${HDF5_VERSION}" VERSION_LESS 1.10) message(FATAL_ERROR "HDF5 version 1.10 at least required, HDF5 ${HDF5_VERSION} found.") endif() - if("PARALLEL4" IN_LIST NetCDF_FEATURES AND NOT "${HDF5_IS_PARALLEL}") + if("PARALLEL4" IN_LIST NetCDF_FEATURES AND NOT ("${HDF5_PROVIDES_PARALLEL}" OR "${HDF5_IS_PARALLEL}")) message(ERROR "Parallel HDF5 required by NetCDF, sequential HDF5 only found.") endif() list(APPEND NetCDF_LINK_LIBRARIES hdf5::hdf5) diff --git a/plugins/decl_netcdf/dnc_file_context.cxx b/plugins/decl_netcdf/dnc_file_context.cxx index b190f447c..c02439faf 100644 --- a/plugins/decl_netcdf/dnc_file_context.cxx +++ b/plugins/decl_netcdf/dnc_file_context.cxx @@ -212,6 +212,7 @@ Dnc_variable* Dnc_file_context::variable(const std::string& desc_name, const std void Dnc_file_context::execute(const std::string& desc_name, PDI::Ref ref) { + START_TIMER("Decl'NetCDF"); if (m_when.to_long(m_ctx)) { std::list variables_holder; // memory for Variables created from descriptor @@ -276,10 +277,12 @@ void Dnc_file_context::execute(const std::string& desc_name, PDI::Ref ref) nc_file.get_sizeof_variable(size_it->first, dataset_name, ref); } } + STOP_TIMER("Decl'NetCDF"); } void Dnc_file_context::execute() { + START_TIMER("Decl'NetCDF"); if (m_when.to_long(m_ctx)) { std::list variables_holder; std::vector variables_to_get; @@ -354,6 +357,7 @@ void Dnc_file_context::execute() i++; } } + STOP_TIMER("Decl'NetCDF"); } } // namespace decl_netcdf diff --git a/plugins/decl_netcdf/dnc_file_context.h b/plugins/decl_netcdf/dnc_file_context.h index 60cbb9ac1..56d99a23a 100644 --- a/plugins/decl_netcdf/dnc_file_context.h +++ b/plugins/decl_netcdf/dnc_file_context.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2024-2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * Copyright (C) 2020 Institute of Bioorganic Chemistry Polish Academy of Science (PSNC) * All rights reserved. * @@ -32,6 +32,7 @@ #include #include #include +#include #include "dnc_group.h" #include "dnc_io.h" From b532a083ac6c30af34b2b1c0ca448d6354cb1ccb Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 12 Mar 2026 15:48:48 +0100 Subject: [PATCH 07/38] add timer for json --- plugins/json/CMakeLists.txt | 4 +++- plugins/json/json.cxx | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/json/CMakeLists.txt b/plugins/json/CMakeLists.txt index 7ca193ae5..a07f4298d 100644 --- a/plugins/json/CMakeLists.txt +++ b/plugins/json/CMakeLists.txt @@ -36,7 +36,9 @@ find_package(nlohmann_json 3.9 REQUIRED) # The plugin add_library(pdi_json_plugin MODULE json.cxx) target_link_libraries(pdi_json_plugin PUBLIC PDI::PDI_plugins nlohmann_json::nlohmann_json ) - +if(WITH_TIMER_REPORT) + target_compile_definitions(pdi_json_plugin PUBLIC WITH_TIMER_REPORT) +endif() # Installation set(INSTALL_PDIPLUGINDIR "${PDI_DEFAULT_PLUGINDIR}" CACHE PATH "PDI plugins (${PDI_DEFAULT_PLUGINDIR})") install(TARGETS pdi_json_plugin diff --git a/plugins/json/json.cxx b/plugins/json/json.cxx index f2b1b94f6..c6662cf77 100644 --- a/plugins/json/json.cxx +++ b/plugins/json/json.cxx @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2023-2024 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2023-2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -69,6 +70,7 @@ class json_plugin: public PDI::Plugin ~json_plugin() { context().logger().info("Closing plugin"); } + static std::string pretty_name() { return "JSON"; } private: /** Read the configuration file @@ -328,6 +330,7 @@ class json_plugin: public PDI::Plugin */ void write_data(const std::string& data_name, Ref_r&& reference) { + START_TIMER(pretty_name()); Logger& logger = context().logger(); for (const auto& [condition, fpath]: m_data_to_path_map[data_name]) { @@ -374,6 +377,7 @@ class json_plugin: public PDI::Plugin } logger.debug("Done ! {} ", data_name); } + STOP_TIMER(pretty_name()); } }; From e6be2ed93728afbef7f338c31e5931e5ac3c5cb8 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 12 Mar 2026 15:49:45 +0100 Subject: [PATCH 08/38] add timer for serialize --- plugins/serialize/CMakeLists.txt | 4 +++- plugins/serialize/serialize.cxx | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/serialize/CMakeLists.txt b/plugins/serialize/CMakeLists.txt index 512c55c28..997be0d88 100644 --- a/plugins/serialize/CMakeLists.txt +++ b/plugins/serialize/CMakeLists.txt @@ -38,7 +38,9 @@ add_library(pdi_serialize_plugin MODULE serialize.cxx) target_link_libraries(pdi_serialize_plugin PUBLIC PDI::PDI_plugins) set_target_properties(pdi_serialize_plugin PROPERTIES CXX_VISIBILITY_PRESET hidden) - +if(WITH_TIMER_REPORT) + target_compile_definitions(pdi_serialize_plugin PUBLIC WITH_TIMER_REPORT) +endif() # installation set(INSTALL_PDIPLUGINDIR "${PDI_DEFAULT_PLUGINDIR}" CACHE PATH "PDI plugins (${PDI_DEFAULT_PLUGINDIR})") install(TARGETS pdi_serialize_plugin diff --git a/plugins/serialize/serialize.cxx b/plugins/serialize/serialize.cxx index 57b07e0cf..423bb00f7 100644 --- a/plugins/serialize/serialize.cxx +++ b/plugins/serialize/serialize.cxx @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2021 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2021-2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * Copyright (C) 2020-2021 Institute of Bioorganic Chemistry Polish Academy of Science (PSNC) * All rights reserved. * @@ -40,6 +40,7 @@ #include #include #include +#include #include namespace { @@ -272,6 +273,7 @@ struct serialize_plugin: PDI::Plugin { */ void share_serialized(const std::string& desc_name, PDI::Ref ref) { + START_TIMER(pretty_name()); std::string serialized_name = m_desc_to_serialize[desc_name]; context().logger().debug("Serializing `{}` as `{}`", desc_name, serialized_name); PDI::Datatype_sptr serialized_type = serialize_type(ref.type()); @@ -333,6 +335,7 @@ struct serialize_plugin: PDI::Plugin { ); m_serialized_remove_callback.emplace_back(serialized_name, remove_callback, PDI_IN); } + STOP_TIMER(pretty_name()); } void release_serialized(const std::string& desc_name, PDI::Ref ref) From a72d07d59521e909661a15b030be106d9c42e83e Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 12 Mar 2026 15:50:42 +0100 Subject: [PATCH 09/38] add timer for user_code --- plugins/user_code/CMakeLists.txt | 4 +++- plugins/user_code/user_code.cxx | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/user_code/CMakeLists.txt b/plugins/user_code/CMakeLists.txt index 1444fdb50..6566251a8 100644 --- a/plugins/user_code/CMakeLists.txt +++ b/plugins/user_code/CMakeLists.txt @@ -41,7 +41,9 @@ find_package(PDI REQUIRED COMPONENTS plugins) add_library(pdi_user_code_plugin MODULE user_code.cxx) target_link_libraries(pdi_user_code_plugin PDI::PDI_plugins) set_target_properties(pdi_user_code_plugin PROPERTIES CXX_VISIBILITY_PRESET hidden) - +if(WITH_TIMER_REPORT) + target_compile_definitions(pdi_user_code_plugin PUBLIC WITH_TIMER_REPORT) +endif() # installation set(INSTALL_PDIPLUGINDIR "${PDI_DEFAULT_PLUGINDIR}" CACHE PATH "PDI plugins (${PDI_DEFAULT_PLUGINDIR})") install(TARGETS pdi_user_code_plugin diff --git a/plugins/user_code/user_code.cxx b/plugins/user_code/user_code.cxx index 3c2b25daf..bb17fdd08 100644 --- a/plugins/user_code/user_code.cxx +++ b/plugins/user_code/user_code.cxx @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2015-2025 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2015-2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * Copyright (C) 2021 Institute of Bioorganic Chemistry Polish Academy of Science (PSNC) * All rights reserved. * @@ -38,6 +38,7 @@ #include #include #include +#include namespace { @@ -160,6 +161,7 @@ class Trigger /// call the function that has been registered void call(Context& ctx) { + START_TIMER("User-code"); // all exposed aliases that will be unexposed on destroy vector exposed_aliases; for (auto&& alias: m_aliases) { @@ -173,6 +175,7 @@ class Trigger } catch (...) { ctx.logger().error("While calling user code, caught exception"); } + STOP_TIMER("User-code"); } }; // class Trigger From fdbfc1891a11641d8ef45be6b42586ead8c888aa Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 12 Mar 2026 15:57:05 +0100 Subject: [PATCH 10/38] revert non-relevant change --- pdi/tests/CMakeLists.txt | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/pdi/tests/CMakeLists.txt b/pdi/tests/CMakeLists.txt index 9deadcbc6..8c0bd8606 100644 --- a/pdi/tests/CMakeLists.txt +++ b/pdi/tests/CMakeLists.txt @@ -75,32 +75,32 @@ add_executable(PDI_unit_tests PDI_tuple_datatype.cxx ) -# set(OPERAND_TYPES uint8_t int64_t float double) -# foreach(OPERAND1_TYPE IN LISTS OPERAND_TYPES) -# foreach(OPERAND2_TYPE IN LISTS OPERAND_TYPES) -# string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") -# configure_file(expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) -# target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") -# endforeach() -# endforeach() +set(OPERAND_TYPES uint8_t int64_t float double) +foreach(OPERAND1_TYPE IN LISTS OPERAND_TYPES) + foreach(OPERAND2_TYPE IN LISTS OPERAND_TYPES) + string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") + configure_file(expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) + target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") + endforeach() +endforeach() -# set(PARSEABLE_OPERAND_TYPES long double) -# foreach(OPERAND1_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) -# foreach(OPERAND2_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) -# string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") -# configure_file(parsed_expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) -# target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") -# endforeach() -# endforeach() +set(PARSEABLE_OPERAND_TYPES long double) +foreach(OPERAND1_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) + foreach(OPERAND2_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) + string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") + configure_file(parsed_expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) + target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") + endforeach() +endforeach() -# set(MODULABLE_OPERAND_TYPES uint8_t int64_t) -# foreach(OPERAND1_TYPE IN LISTS MODULABLE_OPERAND_TYPES) -# foreach(OPERAND2_TYPE IN LISTS MODULABLE_OPERAND_TYPES) -# string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") -# configure_file(modulo.cxx "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) -# target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") -# endforeach() -# endforeach() +set(MODULABLE_OPERAND_TYPES uint8_t int64_t) +foreach(OPERAND1_TYPE IN LISTS MODULABLE_OPERAND_TYPES) + foreach(OPERAND2_TYPE IN LISTS MODULABLE_OPERAND_TYPES) + string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") + configure_file(modulo.cxx "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) + target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") + endforeach() +endforeach() target_compile_features(PDI_unit_tests PRIVATE cxx_std_17) target_link_libraries(PDI_unit_tests PDI::PDI_plugins Threads::Threads GTest::gtest GTest::gtest_main GTest::gmock GTest::gmock_main) From bef38f9923a8b529c60f5fbee4b91f653f400947 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 12 Mar 2026 15:58:14 +0100 Subject: [PATCH 11/38] revert non-relevant change --- plugins/decl_hdf5/CMakeLists.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugins/decl_hdf5/CMakeLists.txt b/plugins/decl_hdf5/CMakeLists.txt index e25655e87..b7ce29dc2 100644 --- a/plugins/decl_hdf5/CMakeLists.txt +++ b/plugins/decl_hdf5/CMakeLists.txt @@ -51,16 +51,13 @@ find_package(HDF5 REQUIRED COMPONENTS C) if("${HDF5_VERSION}" VERSION_LESS 1.10) message(FATAL_ERROR "HDF5 version 1.10 at least required, HDF5 ${HDF5_VERSION} found.") endif() -if("${HDF5_VERSION}" VERSION_GREATER_EQUAL 2.0.0) - set(HDF5_IS_PARALLEL "${HDF5_PROVIDES_PARALLEL}") -endif() if("${BUILD_HDF5_PARALLEL}" AND NOT "${HDF5_IS_PARALLEL}") message(FATAL_ERROR "Parallel HDF5 required, sequential HDF5 only found. Please set -DBUILD_HDF5_PARALLEL=OFF to disable parallel HDF5") endif() set(HDF5_DEPS hdf5::hdf5) # MPI -if("${HDF5_IS_PARALLEL}" OR "${HDF5_PROVIDES_PARALLEL}") +if("${HDF5_IS_PARALLEL}") if("${BUILD_TESTING}" AND "${BUILD_FORTRAN}") set(MPI_COMPONENTS Fortran) endif() From b7f00e20c8a406d8a3d2529b2b560c54fdf90708 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 12 Mar 2026 15:59:11 +0100 Subject: [PATCH 12/38] revert non-relevant change --- plugins/decl_netcdf/cmake/FindNetCDF.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/decl_netcdf/cmake/FindNetCDF.cmake b/plugins/decl_netcdf/cmake/FindNetCDF.cmake index b1465e884..0cdd109d5 100644 --- a/plugins/decl_netcdf/cmake/FindNetCDF.cmake +++ b/plugins/decl_netcdf/cmake/FindNetCDF.cmake @@ -369,7 +369,7 @@ if("${NetCDF_FOUND}") if("${HDF5_VERSION}" VERSION_LESS 1.10) message(FATAL_ERROR "HDF5 version 1.10 at least required, HDF5 ${HDF5_VERSION} found.") endif() - if("PARALLEL4" IN_LIST NetCDF_FEATURES AND NOT ("${HDF5_PROVIDES_PARALLEL}" OR "${HDF5_IS_PARALLEL}")) + if("PARALLEL4" IN_LIST NetCDF_FEATURES AND NOT "${HDF5_IS_PARALLEL}") message(ERROR "Parallel HDF5 required by NetCDF, sequential HDF5 only found.") endif() list(APPEND NetCDF_LINK_LIBRARIES hdf5::hdf5) From 194aeec6d223b2cce90846ee24355efaabb927d0 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 12 Mar 2026 16:02:40 +0100 Subject: [PATCH 13/38] revert non-relevant change --- CMakeLists.txt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cbb7e45e..0e7d800bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -285,7 +285,6 @@ endif() ## HDF5 if("${BUILD_DECL_HDF5_PLUGIN}" OR "${BUILD_DECL_NETCDF_PLUGIN}") - find_package(HDF5 COMPONENTS C ) set(HDF5_CMAKE_CACHE_ARGS) if("${BUILD_HDF5_PARALLEL}") @@ -307,7 +306,7 @@ if("${BUILD_DECL_HDF5_PLUGIN}" OR "${BUILD_DECL_NETCDF_PLUGIN}") sbuild_add_dependency(HDF5 "${USE_DEFAULT}" EMBEDDED_PATH "vendor/hdf5-1.12.3" COMPONENTS ${HDF5_COMPONENTS} - MODULE_VARS HDF5_IS_PARALLEL HDF5_PROVIDES_PARALLEL HDF5_VERSION + MODULE_VARS HDF5_IS_PARALLEL HDF5_VERSION CMAKE_CACHE_ARGS -DBUILD_STATIC_LIBS:BOOL=OFF -DBUILD_TESTING:BOOL=OFF @@ -325,9 +324,6 @@ if("${BUILD_DECL_HDF5_PLUGIN}" OR "${BUILD_DECL_NETCDF_PLUGIN}") if("${HDF5_VERSION}" VERSION_LESS 1.10) message(FATAL_ERROR "HDF5 version 1.10 at least required, HDF5 ${HDF5_VERSION} found.") endif() - if("${HDF5_VERSION}" VERSION_GREATER_EQUAL 2.0.0) - set(HDF5_IS_PARALLEL "${HDF5_PROVIDES_PARALLEL}") - endif() if("${BUILD_HDF5_PARALLEL}" AND NOT "${HDF5_IS_PARALLEL}") message(FATAL_ERROR "You requested a parallel HDF5 build (-DBUILD_HDF5_PARALLEL=ON) but a sequential SYSTEM version has been found\n" From 0e08740a56072f2898f0e7029d78238fa9ca0968 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 12 Mar 2026 16:22:00 +0100 Subject: [PATCH 14/38] fix indent --- pdi/include/pdi/timer.h | 52 +++++++++++------------- pdi/src/timer.cxx | 87 ++++++++++++++++++++++------------------- 2 files changed, 70 insertions(+), 69 deletions(-) diff --git a/pdi/include/pdi/timer.h b/pdi/include/pdi/timer.h index ff456cfad..bd7e089a0 100644 --- a/pdi/include/pdi/timer.h +++ b/pdi/include/pdi/timer.h @@ -25,52 +25,46 @@ #ifndef PDI_TIMER_H_ #define PDI_TIMER_H_ +#include #include -// #include -#include #include -#include -// #include +#include #include -// #include -// #include - #include -// #include + namespace PDI { -class PDI_EXPORT TimerManager { +class PDI_EXPORT TimerManager +{ public: - // Delete copy constructor and assignment - TimerManager(const TimerManager&) = delete; - void operator=(const TimerManager&) = delete; + TimerManager(const TimerManager&) = delete; + void operator= (const TimerManager&) = delete; - static TimerManager& getInstance(); + static TimerManager& getInstance(); - void startTimer(const std::string& name); - void stopTimer(const std::string& name); - void printReport() const ; - void printReport(const std::string& name) const; + void startTimer(const std::string& name); + void stopTimer(const std::string& name); + void printReport() const; + void printReport(const std::string& name) const; - const std::map& getResults(); + const std::map& getResults(); private: - TimerManager() {} // Private Constructor + TimerManager() {} - std::map start_times; - std::map accumulated_times; + std::map start_times; + std::map accumulated_times; }; -} +} // namespace PDI #ifdef WITH_TIMER_REPORT - #define START_TIMER(name) PDI::TimerManager::getInstance().startTimer(name) - #define STOP_TIMER(name) PDI::TimerManager::getInstance().stopTimer(name) - #define PRINT_TIMER_REPORT() PDI::TimerManager::getInstance().printReport() +#define START_TIMER(name) PDI::TimerManager::getInstance().startTimer(name) +#define STOP_TIMER(name) PDI::TimerManager::getInstance().stopTimer(name) +#define PRINT_TIMER_REPORT() PDI::TimerManager::getInstance().printReport() #else - #define START_TIMER(name) - #define STOP_TIMER(name) - #define PRINT_TIMER_REPORT() +#define START_TIMER(name) +#define STOP_TIMER(name) +#define PRINT_TIMER_REPORT() #endif - #endif // PDI_TIMER_H_ diff --git a/pdi/src/timer.cxx b/pdi/src/timer.cxx index c65eda28d..e5d866018 100644 --- a/pdi/src/timer.cxx +++ b/pdi/src/timer.cxx @@ -23,50 +23,57 @@ ******************************************************************************/ #include + namespace PDI { - - TimerManager& TimerManager::getInstance() { - static TimerManager instance; - return instance; - } - // Start a timer by name - void TimerManager::startTimer(const std::string& name) { - start_times[name] = std::chrono::high_resolution_clock::now(); - } +TimerManager& TimerManager::getInstance() +{ + static TimerManager instance; + return instance; +} + +// Start a timer by name +void TimerManager::startTimer(const std::string& name) +{ + start_times[name] = std::chrono::high_resolution_clock::now(); +} + +// Stop a timer and accumulate the duration +void TimerManager::stopTimer(const std::string& name) +{ + auto end_time = std::chrono::high_resolution_clock::now(); + + if (start_times.find(name) != start_times.end()) { + std::chrono::duration elapsed = end_time - start_times[name]; + accumulated_times[name] += elapsed.count(); + } +} - // Stop a timer and accumulate the duration - void TimerManager::stopTimer(const std::string& name) { - auto end_time = std::chrono::high_resolution_clock::now(); - - if (start_times.find(name) != start_times.end()) { - std::chrono::duration elapsed = end_time - start_times[name]; - accumulated_times[name] += elapsed.count(); - } - } +// Export the results +void TimerManager::printReport() const +{ + std::cout << "\n--- Full Timer Report ---" << &accumulated_times << std::endl; + for (const auto& [name, duration]: accumulated_times) { + std::cout << name << ": " << duration << " seconds" << std::endl; + } +} - // Export the results - void TimerManager::printReport() const { - std::cout << "\n--- Full Timer Report ---"<<&accumulated_times<second << " seconds" << std::endl; - } else { - std::cout << name << " timer not found." << std::endl; - } - } + if (it != accumulated_times.end()) { + std::cout << name << " : " << it->second << " seconds" << std::endl; + } else { + std::cout << name << " timer not found." << std::endl; + } +} - // Get the map directly (useful for MPI export) - const std::map& TimerManager::getResults() { - return accumulated_times; - } -} \ No newline at end of file +// Get the map directly (useful for MPI export) +const std::map& TimerManager::getResults() +{ + return accumulated_times; +} +} // namespace PDI From 9d19822e8edd2bfc52b78159d0d88654009757ec Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 13 Mar 2026 11:33:33 +0100 Subject: [PATCH 15/38] output cleanup --- pdi/src/timer.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pdi/src/timer.cxx b/pdi/src/timer.cxx index e5d866018..a54d90d7c 100644 --- a/pdi/src/timer.cxx +++ b/pdi/src/timer.cxx @@ -53,7 +53,7 @@ void TimerManager::stopTimer(const std::string& name) // Export the results void TimerManager::printReport() const { - std::cout << "\n--- Full Timer Report ---" << &accumulated_times << std::endl; + std::cout << "\n--- Full Timer Report ---" << std::endl; for (const auto& [name, duration]: accumulated_times) { std::cout << name << ": " << duration << " seconds" << std::endl; } @@ -61,7 +61,7 @@ void TimerManager::printReport() const void TimerManager::printReport(const std::string& name) const { - std::cout << "\n--- Timer Report : " << &accumulated_times << std::endl; + std::cout << "\n--- Timer Report : " << std::endl; auto it = accumulated_times.find(name); if (it != accumulated_times.end()) { From 5f843feb2f88db1bd2d308cef2c437b7cd974cb5 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 13 Mar 2026 12:04:45 +0100 Subject: [PATCH 16/38] add example yaml for timing multiple plugins. use pretty_name instead of plain string --- example/example.yml | 57 ++++++++++++++++++++++++ plugins/decl_netcdf/dnc_file_context.cxx | 8 ++-- plugins/decl_netcdf/dnc_file_context.h | 2 + plugins/user_code/user_code.cxx | 10 ++--- 4 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 example/example.yml diff --git a/example/example.yml b/example/example.yml new file mode 100644 index 000000000..206dba749 --- /dev/null +++ b/example/example.yml @@ -0,0 +1,57 @@ +# duration in seconds +duration: 0.75 +# global [height, width] (excluding boundary conditions or ghosts) +datasize: [6, 2] +# degree of parallelism +parallelism: { height: 1, width: 1 } + +# only the following config is passed to PDI +pdi: + metadata: # type of small values for which PDI keeps a copy + iter: int # current iteration id + dsize: { size: 2, type: array, subtype: int } # local data size including ghosts/boundary + psize: { size: 2, type: array, subtype: int } # number of processes in each dimension + pcoord: { size: 2, type: array, subtype: int } # coordinate of the process + data: # type of values for which PDI does not keep a copy + main_field: { size: [ '$dsize[0]', '$dsize[1]' ], type: array, subtype: double } + + plugins: + mpi: + decl_hdf5: + file: data.h5 + communicator: $MPI_COMM_WORLD # the MPI communicator used for HDF5 parallel synchronized write + datasets: # type of the datasets to create in file + data: + type: array + subtype: double + size: [10, '$psize[0]*($dsize[0]-2)', '$psize[1]*($dsize[1]-2)'] + write: + main_field: # the name of the data to write + dataset: data + mpio: COLLECTIVE # or INDEPENDENT + when: '$iter<10' # do only write the first 10 iterations (0...9) + memory_selection: # exclude ghosts from the data in memory + size: ['$dsize[0]-2', '$dsize[1]-2'] + start: [1, 1] + dataset_selection: # only write into a single slice in time + size: [1, '$dsize[0]-2', '$dsize[1]-2'] + start: [$iter, '($dsize[0]-2)*$pcoord[0]', '($dsize[1]-2)*$pcoord[1]'] + decl_netcdf: + file: data.nc + communicator: $MPI_COMM_WORLD # the MPI communicator used for HDF5 parallel synchronized write + variables: # type of the datasets to create in file + data: + type: array + subtype: double + size: [10, '$psize[0]*$dsize[0]', '$psize[1]*$dsize[1]'] + write: + main_field: # the name of the data to write + variable: data + when: '$iter<10' # do only write the first 10 iterations (0...9) + variable_selection: # only write into a single slice in time + subsize: [1, '$dsize[0]', '$dsize[1]'] + start: [$iter, '$dsize[0]*$pcoord[0]', '$dsize[1]*$pcoord[1]'] + json: + file: data_${pcoord[0]}_${pcoord[1]}.json + when: '$iter<10' + write: [main_field] \ No newline at end of file diff --git a/plugins/decl_netcdf/dnc_file_context.cxx b/plugins/decl_netcdf/dnc_file_context.cxx index c02439faf..af89a826b 100644 --- a/plugins/decl_netcdf/dnc_file_context.cxx +++ b/plugins/decl_netcdf/dnc_file_context.cxx @@ -212,7 +212,7 @@ Dnc_variable* Dnc_file_context::variable(const std::string& desc_name, const std void Dnc_file_context::execute(const std::string& desc_name, PDI::Ref ref) { - START_TIMER("Decl'NetCDF"); + START_TIMER(pretty_name()); if (m_when.to_long(m_ctx)) { std::list variables_holder; // memory for Variables created from descriptor @@ -277,12 +277,12 @@ void Dnc_file_context::execute(const std::string& desc_name, PDI::Ref ref) nc_file.get_sizeof_variable(size_it->first, dataset_name, ref); } } - STOP_TIMER("Decl'NetCDF"); + STOP_TIMER(pretty_name()); } void Dnc_file_context::execute() { - START_TIMER("Decl'NetCDF"); + START_TIMER(pretty_name()); if (m_when.to_long(m_ctx)) { std::list variables_holder; std::vector variables_to_get; @@ -357,7 +357,7 @@ void Dnc_file_context::execute() i++; } } - STOP_TIMER("Decl'NetCDF"); + STOP_TIMER(pretty_name()); } } // namespace decl_netcdf diff --git a/plugins/decl_netcdf/dnc_file_context.h b/plugins/decl_netcdf/dnc_file_context.h index 56d99a23a..88811c4d3 100644 --- a/plugins/decl_netcdf/dnc_file_context.h +++ b/plugins/decl_netcdf/dnc_file_context.h @@ -110,6 +110,8 @@ class Dnc_file_context * \param other Dnc_file_context to move */ Dnc_file_context(Dnc_file_context&& other) noexcept; + + static std::string pretty_name() { return "Decl'NetCDF"; } }; } // namespace decl_netcdf diff --git a/plugins/user_code/user_code.cxx b/plugins/user_code/user_code.cxx index bb17fdd08..28a08da4f 100644 --- a/plugins/user_code/user_code.cxx +++ b/plugins/user_code/user_code.cxx @@ -159,9 +159,9 @@ class Trigger } /// call the function that has been registered - void call(Context& ctx) + void call(Context& ctx, const std::string& name) { - START_TIMER("User-code"); + START_TIMER(name); // all exposed aliases that will be unexposed on destroy vector exposed_aliases; for (auto&& alias: m_aliases) { @@ -175,7 +175,7 @@ class Trigger } catch (...) { ctx.logger().error("While calling user code, caught exception"); } - STOP_TIMER("User-code"); + STOP_TIMER(name); } }; // class Trigger @@ -192,7 +192,7 @@ struct user_code_plugin: Plugin { each(one_event, [&](PC_tree_t function_name, PC_tree_t parameters) { Trigger event_trigger{to_string(function_name), parameters}; ctx.callbacks().add_event_callback( - [&ctx, event_trigger](const std::string& name) mutable { event_trigger.call(ctx); }, + [&ctx, event_trigger](const std::string& name) mutable { event_trigger.call(ctx, pretty_name()); }, to_string(event_name) ); }); @@ -207,7 +207,7 @@ struct user_code_plugin: Plugin { each(one_data, [&](PC_tree_t function_name, PC_tree_t parameters) { Trigger data_trigger{to_string(function_name), parameters}; ctx.callbacks().add_data_callback( - [&ctx, data_trigger](const std::string& name, Ref ref) mutable { data_trigger.call(ctx); }, + [&ctx, data_trigger](const std::string& name, Ref ref) mutable { data_trigger.call(ctx, pretty_name()); }, to_string(data_name) ); }); From cfc462dc598b5397c333d0bfa147cccb42656f52 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 13 Mar 2026 13:53:28 +0100 Subject: [PATCH 17/38] add timer for pycall --- pdi/CMakeLists.txt | 3 +++ plugins/pycall/CMakeLists.txt | 7 ++++++- plugins/pycall/pycall.cxx | 11 +++++++---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/pdi/CMakeLists.txt b/pdi/CMakeLists.txt index 2e2809f6b..ad13c0062 100644 --- a/pdi/CMakeLists.txt +++ b/pdi/CMakeLists.txt @@ -243,6 +243,9 @@ if("${BUILD_PYTHON}") "$" PRIVATE "$" ) + if(APPLE) + target_link_options(PDI_pysupport PUBLIC "-undefined" "dynamic_lookup") + endif() target_link_libraries(PDI_pysupport PUBLIC pybind11::pybind11 PDI::PDI_plugins) set_property(TARGET PDI_pysupport PROPERTY LIBRARY_OUTPUT_NAME "pdi_pysupport") set_property(TARGET PDI_pysupport PROPERTY ENABLE_EXPORTS TRUE) diff --git a/plugins/pycall/CMakeLists.txt b/plugins/pycall/CMakeLists.txt index a3e2db624..65bc60b93 100644 --- a/plugins/pycall/CMakeLists.txt +++ b/plugins/pycall/CMakeLists.txt @@ -49,7 +49,12 @@ add_library(pdi_pycall_plugin MODULE pycall.cxx) # link against Python3::Python to workaround https://github.com/pybind/pybind11/issues/2664 target_link_libraries(pdi_pycall_plugin PDI::PDI_pysupport pybind11::embed Python3::Python) set_target_properties(pdi_pycall_plugin PROPERTIES CXX_VISIBILITY_PRESET hidden) - +if(WITH_TIMER_REPORT) + target_compile_definitions(pdi_pycall_plugin PUBLIC WITH_TIMER_REPORT) +endif() +if(APPLE) + target_link_options(pdi_pycall_plugin PRIVATE "-undefined" "dynamic_lookup") +endif() # installation set(INSTALL_PDIPLUGINDIR "${PDI_DEFAULT_PLUGINDIR}" CACHE PATH "PDI plugins (${PDI_DEFAULT_PLUGINDIR})") install(TARGETS pdi_pycall_plugin diff --git a/plugins/pycall/pycall.cxx b/plugins/pycall/pycall.cxx index 10539cb68..ff58f35c7 100644 --- a/plugins/pycall/pycall.cxx +++ b/plugins/pycall/pycall.cxx @@ -42,6 +42,7 @@ #include #include #include +#include namespace { @@ -142,7 +143,7 @@ class Trigger /** Call the function that has been registered * \param ctx the PDI context for this trigger */ - void call(Context& ctx) + void call(Context& ctx, const std::string& name) { // a python context we fill with exposed variables pydict pyscope = pymod::import("__main__").attr("__dict__"); @@ -153,7 +154,9 @@ class Trigger alias.expose(ctx, pyscope); } try { + START_TIMER(name); pybind11::exec(m_code, pyscope); + STOP_TIMER(name); } catch (const std::exception& e) { ctx.logger().error("while calling python, caught exception: {}", e.what()); } catch (...) { @@ -190,7 +193,7 @@ struct pycall_plugin: Plugin { ctx.callbacks().add_event_callback( [&ctx, triggers](const std::string&) mutable { for (auto&& trigger: triggers) { - trigger.call(ctx); + trigger.call(ctx, pretty_name()); } }, to_string(PC_get(on_event, "{%d}", map_id)) @@ -198,7 +201,7 @@ struct pycall_plugin: Plugin { } else { Trigger event_trigger{to_string(PC_get(event, ".exec")), PC_get(event, ".with")}; ctx.callbacks().add_event_callback( - [&ctx, event_trigger](const std::string&) mutable { event_trigger.call(ctx); }, + [&ctx, event_trigger](const std::string&) mutable { event_trigger.call(ctx, pretty_name()); }, to_string(PC_get(on_event, "{%d}", map_id)) ); } @@ -210,7 +213,7 @@ struct pycall_plugin: Plugin { for (int map_id = 0; map_id < nb_data; map_id++) { string data_name = to_string(PC_get(on_data, "{%d}", map_id)); Trigger data_trigger{to_string(PC_get(on_data, "<%d>", map_id)), data_name}; - ctx.callbacks().add_data_callback([&ctx, data_trigger](const std::string&, Ref) mutable { data_trigger.call(ctx); }, data_name); + ctx.callbacks().add_data_callback([&ctx, data_trigger](const std::string&, Ref) mutable { data_trigger.call(ctx, pretty_name()); }, data_name); } } From e851c0c9409864a5dbf112c50ee2499dac1b0ec6 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 13 Mar 2026 13:55:32 +0100 Subject: [PATCH 18/38] indent --- plugins/pycall/pycall.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/pycall/pycall.cxx b/plugins/pycall/pycall.cxx index ff58f35c7..cebf57467 100644 --- a/plugins/pycall/pycall.cxx +++ b/plugins/pycall/pycall.cxx @@ -213,7 +213,10 @@ struct pycall_plugin: Plugin { for (int map_id = 0; map_id < nb_data; map_id++) { string data_name = to_string(PC_get(on_data, "{%d}", map_id)); Trigger data_trigger{to_string(PC_get(on_data, "<%d>", map_id)), data_name}; - ctx.callbacks().add_data_callback([&ctx, data_trigger](const std::string&, Ref) mutable { data_trigger.call(ctx, pretty_name()); }, data_name); + ctx.callbacks().add_data_callback( + [&ctx, data_trigger](const std::string&, Ref) mutable { data_trigger.call(ctx, pretty_name()); }, + data_name + ); } } From 141647ea1a2d4b739f5beb7983d7576d98d84c3c Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 13 Mar 2026 14:32:51 +0100 Subject: [PATCH 19/38] fix copyright date --- pdi/include/pdi/timer.h | 2 +- pdi/src/timer.cxx | 2 +- plugins/pycall/pycall.cxx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pdi/include/pdi/timer.h b/pdi/include/pdi/timer.h index bd7e089a0..b2e7a2ce3 100644 --- a/pdi/include/pdi/timer.h +++ b/pdi/include/pdi/timer.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2015-2019 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/pdi/src/timer.cxx b/pdi/src/timer.cxx index a54d90d7c..a5f2dfafe 100644 --- a/pdi/src/timer.cxx +++ b/pdi/src/timer.cxx @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2015-2019 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/plugins/pycall/pycall.cxx b/plugins/pycall/pycall.cxx index cebf57467..5430cd53d 100644 --- a/plugins/pycall/pycall.cxx +++ b/plugins/pycall/pycall.cxx @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2015-2019 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2015-2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * All rights reserved. * * Redistribution and use in source and binary forms, with or without From a7fc397535e6a47781efb552f29bff2a68e19dfd Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 13 Mar 2026 14:35:31 +0100 Subject: [PATCH 20/38] update changelog --- pdi/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/pdi/CHANGELOG.md b/pdi/CHANGELOG.md index 82641778b..a83d3f5d0 100644 --- a/pdi/CHANGELOG.md +++ b/pdi/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to ### For users #### Added +* A compile option `WITH_TIMER_REPORT` is added to generate timer for all plugins. #### Changed From ee0508b702638f96c4f0fd85c49b433a85fc0e05 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 20 Mar 2026 13:56:36 +0100 Subject: [PATCH 21/38] make timer inside the context --- pdi/include/pdi/context.h | 6 +++ pdi/include/pdi/context_proxy.h | 9 ++++ pdi/include/pdi/timer.h | 20 +++++++++ pdi/src/context_proxy.cxx | 8 ++++ pdi/src/global_context.cxx | 5 +++ pdi/src/global_context.h | 6 +++ pdi/src/pdi.cxx | 6 +-- pdi/src/timer.cxx | 55 ++++++++++++++++++++++++ pdi/tests/CMakeLists.txt | 48 ++++++++++----------- plugins/decl_hdf5/CMakeLists.txt | 3 -- plugins/decl_hdf5/decl_hdf5.cxx | 9 ++-- plugins/decl_netcdf/CMakeLists.txt | 4 +- plugins/decl_netcdf/dnc_file_context.cxx | 4 +- plugins/decl_netcdf/dnc_file_context.h | 1 - plugins/json/CMakeLists.txt | 4 +- plugins/json/json.cxx | 5 +-- plugins/pycall/CMakeLists.txt | 4 +- plugins/pycall/pycall.cxx | 5 +-- plugins/serialize/CMakeLists.txt | 4 +- plugins/serialize/serialize.cxx | 5 +-- plugins/user_code/CMakeLists.txt | 4 +- plugins/user_code/user_code.cxx | 5 +-- 22 files changed, 155 insertions(+), 65 deletions(-) diff --git a/pdi/include/pdi/context.h b/pdi/include/pdi/context.h index b24b2f6cd..3970461dc 100644 --- a/pdi/include/pdi/context.h +++ b/pdi/include/pdi/context.h @@ -37,6 +37,7 @@ #include #include #include +#include namespace PDI { @@ -114,6 +115,11 @@ class PDI_EXPORT Context */ virtual Logger& logger() = 0; + /** Timer getter + * \return timer + */ + virtual Timer& timer() = 0; + /** Callbacks of the context * \return context callbacks */ diff --git a/pdi/include/pdi/context_proxy.h b/pdi/include/pdi/context_proxy.h index 2cefc9ed9..be79de82c 100644 --- a/pdi/include/pdi/context_proxy.h +++ b/pdi/include/pdi/context_proxy.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,8 @@ class PDI_EXPORT Context_proxy: public Context /// Logger of the plugin Logger m_plugin_logger; + Timer *m_plugin_timer; + public: /** Creates Context proxy without plugin logger * \param[in] ctx context to make a proxy @@ -101,6 +104,12 @@ class PDI_EXPORT Context_proxy: public Context */ Logger& logger() override; + /** Returns plugin timer + * + * \return plugin timer + */ + Timer& timer() override; + /** Returns pdi core logger * * \return pdi core logger diff --git a/pdi/include/pdi/timer.h b/pdi/include/pdi/timer.h index b2e7a2ce3..88317faac 100644 --- a/pdi/include/pdi/timer.h +++ b/pdi/include/pdi/timer.h @@ -35,6 +35,26 @@ namespace PDI { +class PDI_EXPORT Timer +{ +public: + Timer(const Timer&) = delete; + Timer() {} + + void operator= (const Timer&) = delete; + + void startTimer(const std::string& name); + void stopTimer(const std::string& name); + void printReport() const; + void printReport(const std::string& name) const; + + const std::map& getResults(); + +private: + std::map start_times; + std::map accumulated_times; +}; + class PDI_EXPORT TimerManager { public: diff --git a/pdi/src/context_proxy.cxx b/pdi/src/context_proxy.cxx index 1e6e2b5fa..c698d5916 100644 --- a/pdi/src/context_proxy.cxx +++ b/pdi/src/context_proxy.cxx @@ -26,6 +26,7 @@ #include "pdi/context.h" #include "pdi/context_proxy.h" #include "pdi/logger.h" +#include "pdi/timer.h" using std::move; using std::string; @@ -35,10 +36,12 @@ namespace PDI { Context_proxy::Context_proxy(Context& ctx) : m_real_context{ctx} + , m_plugin_timer{&(ctx.timer())} {} Context_proxy::Context_proxy(Context& ctx, const string& logger_name, PC_tree_t logging_tree) : m_real_context{ctx} + , m_plugin_timer{&(ctx.timer())} , m_plugin_logger{m_real_context.logger(), logger_name, logging_tree} {} @@ -92,6 +95,11 @@ Logger& Context_proxy::logger() return m_plugin_logger; } +Timer& Context_proxy::timer() +{ + return *m_plugin_timer; +} + Logger& Context_proxy::pdi_core_logger() { return m_real_context.logger(); diff --git a/pdi/src/global_context.cxx b/pdi/src/global_context.cxx index 0550fd248..d94c621ae 100644 --- a/pdi/src/global_context.cxx +++ b/pdi/src/global_context.cxx @@ -183,6 +183,11 @@ Logger& Global_context::logger() return m_logger; } +Timer& Global_context::timer() +{ + return m_timer; +} + Datatype_template_sptr Global_context::datatype(PC_tree_t node) { string type; diff --git a/pdi/src/global_context.h b/pdi/src/global_context.h index 42e6a560e..2aa827b43 100644 --- a/pdi/src/global_context.h +++ b/pdi/src/global_context.h @@ -41,6 +41,7 @@ #include "pdi/logger.h" #include "pdi/plugin.h" #include "pdi/ref_any.h" +#include "pdi/timer.h" #include "plugin_store.h" @@ -57,6 +58,9 @@ class PDI_EXPORT Global_context: public Context /// Global logger of PDI, should be constructed first, destroyed last Logger m_logger; + /// Global timer of PDI + Timer m_timer; + /// Datatype_template constructors available in PDI std::unordered_map m_datatype_parsers; @@ -118,6 +122,8 @@ class PDI_EXPORT Global_context: public Context void event(const char* name) override; Logger& logger() override; + + Timer& timer() override; Datatype_template_sptr datatype(PC_tree_t node) override; diff --git a/pdi/src/pdi.cxx b/pdi/src/pdi.cxx index 09c7336e8..f134a829d 100644 --- a/pdi/src/pdi.cxx +++ b/pdi/src/pdi.cxx @@ -168,11 +168,11 @@ PDI_errhandler_t PDI_errhandler(PDI_errhandler_t new_handler) PDI_status_t PDI_init(PC_tree_t conf) try { - START_TIMER("PDI"); Paraconf_wrapper fw; g_transaction.clear(); g_transaction_data.clear(); Global_context::init(conf); + Global_context::context().timer().startTimer("PDI"); return PDI_OK; } catch (const Error& e) { return g_error_context.return_err(e); @@ -187,9 +187,9 @@ try { Paraconf_wrapper fw; g_transaction.clear(); g_transaction_data.clear(); + Global_context::context().timer().stopTimer("PDI"); + Global_context::context().timer().printReport(); Global_context::finalize(); - STOP_TIMER("PDI"); - PRINT_TIMER_REPORT(); return PDI_OK; } catch (const Error& e) { return g_error_context.return_err(e); diff --git a/pdi/src/timer.cxx b/pdi/src/timer.cxx index a5f2dfafe..040b0032b 100644 --- a/pdi/src/timer.cxx +++ b/pdi/src/timer.cxx @@ -27,6 +27,61 @@ namespace PDI { + +// Stop a timer and accumulate the duration +void Timer::stopTimer(const std::string& name) +{ + #ifdef WITH_TIMER_REPORT + auto end_time = std::chrono::high_resolution_clock::now(); + + if (start_times.find(name) != start_times.end()) { + std::chrono::duration elapsed = end_time - start_times[name]; + accumulated_times[name] += elapsed.count(); + } + #endif +} +// Start a timer by name +void Timer::startTimer(const std::string& name) +{ + #ifdef WITH_TIMER_REPORT + start_times[name] = std::chrono::high_resolution_clock::now(); + #endif +} + +// Export the results +void Timer::printReport() const +{ + #ifdef WITH_TIMER_REPORT + std::cout << "\n--- Full Timer Report ---" << std::endl; + for (const auto& [name, duration]: accumulated_times) { + std::cout << name << ": " << duration << " seconds" << std::endl; + } + #endif +} + +void Timer::printReport(const std::string& name) const +{ + #ifdef WITH_TIMER_REPORT + std::cout << "\n--- Timer Report : " << std::endl; + auto it = accumulated_times.find(name); + + if (it != accumulated_times.end()) { + std::cout << name << " : " << it->second << " seconds" << std::endl; + } else { + std::cout << name << " timer not found." << std::endl; + } + #endif +} + +// Get the map directly (useful for MPI export) +const std::map& Timer::getResults() +{ + #ifdef WITH_TIMER_REPORT + return accumulated_times; + #endif +} + + TimerManager& TimerManager::getInstance() { static TimerManager instance; diff --git a/pdi/tests/CMakeLists.txt b/pdi/tests/CMakeLists.txt index 8c0bd8606..9deadcbc6 100644 --- a/pdi/tests/CMakeLists.txt +++ b/pdi/tests/CMakeLists.txt @@ -75,32 +75,32 @@ add_executable(PDI_unit_tests PDI_tuple_datatype.cxx ) -set(OPERAND_TYPES uint8_t int64_t float double) -foreach(OPERAND1_TYPE IN LISTS OPERAND_TYPES) - foreach(OPERAND2_TYPE IN LISTS OPERAND_TYPES) - string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") - configure_file(expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) - target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") - endforeach() -endforeach() +# set(OPERAND_TYPES uint8_t int64_t float double) +# foreach(OPERAND1_TYPE IN LISTS OPERAND_TYPES) +# foreach(OPERAND2_TYPE IN LISTS OPERAND_TYPES) +# string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") +# configure_file(expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) +# target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") +# endforeach() +# endforeach() -set(PARSEABLE_OPERAND_TYPES long double) -foreach(OPERAND1_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) - foreach(OPERAND2_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) - string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") - configure_file(parsed_expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) - target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") - endforeach() -endforeach() +# set(PARSEABLE_OPERAND_TYPES long double) +# foreach(OPERAND1_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) +# foreach(OPERAND2_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) +# string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") +# configure_file(parsed_expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) +# target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") +# endforeach() +# endforeach() -set(MODULABLE_OPERAND_TYPES uint8_t int64_t) -foreach(OPERAND1_TYPE IN LISTS MODULABLE_OPERAND_TYPES) - foreach(OPERAND2_TYPE IN LISTS MODULABLE_OPERAND_TYPES) - string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") - configure_file(modulo.cxx "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) - target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") - endforeach() -endforeach() +# set(MODULABLE_OPERAND_TYPES uint8_t int64_t) +# foreach(OPERAND1_TYPE IN LISTS MODULABLE_OPERAND_TYPES) +# foreach(OPERAND2_TYPE IN LISTS MODULABLE_OPERAND_TYPES) +# string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") +# configure_file(modulo.cxx "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) +# target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") +# endforeach() +# endforeach() target_compile_features(PDI_unit_tests PRIVATE cxx_std_17) target_link_libraries(PDI_unit_tests PDI::PDI_plugins Threads::Threads GTest::gtest GTest::gtest_main GTest::gmock GTest::gmock_main) diff --git a/plugins/decl_hdf5/CMakeLists.txt b/plugins/decl_hdf5/CMakeLists.txt index b7ce29dc2..3b3045c2d 100644 --- a/plugins/decl_hdf5/CMakeLists.txt +++ b/plugins/decl_hdf5/CMakeLists.txt @@ -80,9 +80,6 @@ add_library(pdi_decl_hdf5_plugin MODULE target_link_libraries(pdi_decl_hdf5_plugin PUBLIC PDI::PDI_plugins ${HDF5_DEPS}) set_target_properties(pdi_decl_hdf5_plugin PROPERTIES CXX_VISIBILITY_PRESET hidden) -if(WITH_TIMER_REPORT) - target_compile_definitions(pdi_decl_hdf5_plugin PUBLIC WITH_TIMER_REPORT) -endif() # installation set(INSTALL_PDIPLUGINDIR "${PDI_DEFAULT_PLUGINDIR}" CACHE PATH "PDI plugins (${PDI_DEFAULT_PLUGINDIR})") install(TARGETS pdi_decl_hdf5_plugin diff --git a/plugins/decl_hdf5/decl_hdf5.cxx b/plugins/decl_hdf5/decl_hdf5.cxx index 5af49cc39..7df7bcf88 100644 --- a/plugins/decl_hdf5/decl_hdf5.cxx +++ b/plugins/decl_hdf5/decl_hdf5.cxx @@ -39,7 +39,6 @@ #include #include #include -#include #include "file_op.h" #include "hdf5_wrapper.h" @@ -115,22 +114,22 @@ class decl_hdf5_plugin: public Plugin void data(const std::string& name, Ref ref) { - START_TIMER(pretty_name()); + context().timer().startTimer(pretty_name()); Hdf5_error_handler _; for (auto&& op: m_data[name]) { op.execute(context()); } - STOP_TIMER(pretty_name()); + context().timer().stopTimer(pretty_name()); } void event(const std::string& event) { - START_TIMER(pretty_name()); + context().timer().startTimer(pretty_name()); Hdf5_error_handler _; for (auto&& op: m_events[event]) { op.execute(context()); } - STOP_TIMER(pretty_name()); + context().timer().stopTimer(pretty_name()); } /** Pretty name for the plugin that will be shown in the logger diff --git a/plugins/decl_netcdf/CMakeLists.txt b/plugins/decl_netcdf/CMakeLists.txt index f28a85b05..96e14ed4d 100644 --- a/plugins/decl_netcdf/CMakeLists.txt +++ b/plugins/decl_netcdf/CMakeLists.txt @@ -70,9 +70,7 @@ if("${BUILD_NETCDF_PARALLEL}") target_link_libraries(pdi_decl_netcdf_plugin PUBLIC MPI::MPI_CXX) endif() set_target_properties(pdi_decl_netcdf_plugin PROPERTIES CXX_VISIBILITY_PRESET hidden) -if(WITH_TIMER_REPORT) - target_compile_definitions(pdi_decl_netcdf_plugin PUBLIC WITH_TIMER_REPORT) -endif() + # installation set(INSTALL_PDIPLUGINDIR "${PDI_DEFAULT_PLUGINDIR}" CACHE PATH "PDI plugins (${PDI_DEFAULT_PLUGINDIR})") install(TARGETS pdi_decl_netcdf_plugin diff --git a/plugins/decl_netcdf/dnc_file_context.cxx b/plugins/decl_netcdf/dnc_file_context.cxx index af89a826b..eb05f9bcc 100644 --- a/plugins/decl_netcdf/dnc_file_context.cxx +++ b/plugins/decl_netcdf/dnc_file_context.cxx @@ -212,7 +212,7 @@ Dnc_variable* Dnc_file_context::variable(const std::string& desc_name, const std void Dnc_file_context::execute(const std::string& desc_name, PDI::Ref ref) { - START_TIMER(pretty_name()); + m_ctx.timer().startTimer(pretty_name()); if (m_when.to_long(m_ctx)) { std::list variables_holder; // memory for Variables created from descriptor @@ -277,7 +277,7 @@ void Dnc_file_context::execute(const std::string& desc_name, PDI::Ref ref) nc_file.get_sizeof_variable(size_it->first, dataset_name, ref); } } - STOP_TIMER(pretty_name()); + m_ctx.timer().stopTimer(pretty_name()); } void Dnc_file_context::execute() diff --git a/plugins/decl_netcdf/dnc_file_context.h b/plugins/decl_netcdf/dnc_file_context.h index 88811c4d3..f57aee4fd 100644 --- a/plugins/decl_netcdf/dnc_file_context.h +++ b/plugins/decl_netcdf/dnc_file_context.h @@ -32,7 +32,6 @@ #include #include #include -#include #include "dnc_group.h" #include "dnc_io.h" diff --git a/plugins/json/CMakeLists.txt b/plugins/json/CMakeLists.txt index a07f4298d..7ca193ae5 100644 --- a/plugins/json/CMakeLists.txt +++ b/plugins/json/CMakeLists.txt @@ -36,9 +36,7 @@ find_package(nlohmann_json 3.9 REQUIRED) # The plugin add_library(pdi_json_plugin MODULE json.cxx) target_link_libraries(pdi_json_plugin PUBLIC PDI::PDI_plugins nlohmann_json::nlohmann_json ) -if(WITH_TIMER_REPORT) - target_compile_definitions(pdi_json_plugin PUBLIC WITH_TIMER_REPORT) -endif() + # Installation set(INSTALL_PDIPLUGINDIR "${PDI_DEFAULT_PLUGINDIR}" CACHE PATH "PDI plugins (${PDI_DEFAULT_PLUGINDIR})") install(TARGETS pdi_json_plugin diff --git a/plugins/json/json.cxx b/plugins/json/json.cxx index c6662cf77..ed7823759 100644 --- a/plugins/json/json.cxx +++ b/plugins/json/json.cxx @@ -36,7 +36,6 @@ #include #include #include -#include #include #include @@ -330,7 +329,7 @@ class json_plugin: public PDI::Plugin */ void write_data(const std::string& data_name, Ref_r&& reference) { - START_TIMER(pretty_name()); + context().timer().startTimer(pretty_name()); Logger& logger = context().logger(); for (const auto& [condition, fpath]: m_data_to_path_map[data_name]) { @@ -377,7 +376,7 @@ class json_plugin: public PDI::Plugin } logger.debug("Done ! {} ", data_name); } - STOP_TIMER(pretty_name()); + context().timer().stopTimer(pretty_name()); } }; diff --git a/plugins/pycall/CMakeLists.txt b/plugins/pycall/CMakeLists.txt index 65bc60b93..efcf3964f 100644 --- a/plugins/pycall/CMakeLists.txt +++ b/plugins/pycall/CMakeLists.txt @@ -49,9 +49,7 @@ add_library(pdi_pycall_plugin MODULE pycall.cxx) # link against Python3::Python to workaround https://github.com/pybind/pybind11/issues/2664 target_link_libraries(pdi_pycall_plugin PDI::PDI_pysupport pybind11::embed Python3::Python) set_target_properties(pdi_pycall_plugin PROPERTIES CXX_VISIBILITY_PRESET hidden) -if(WITH_TIMER_REPORT) - target_compile_definitions(pdi_pycall_plugin PUBLIC WITH_TIMER_REPORT) -endif() + if(APPLE) target_link_options(pdi_pycall_plugin PRIVATE "-undefined" "dynamic_lookup") endif() diff --git a/plugins/pycall/pycall.cxx b/plugins/pycall/pycall.cxx index 5430cd53d..8e5c6f84f 100644 --- a/plugins/pycall/pycall.cxx +++ b/plugins/pycall/pycall.cxx @@ -42,7 +42,6 @@ #include #include #include -#include namespace { @@ -154,9 +153,9 @@ class Trigger alias.expose(ctx, pyscope); } try { - START_TIMER(name); + ctx.timer().startTimer(name); pybind11::exec(m_code, pyscope); - STOP_TIMER(name); + ctx.timer().stopTimer(name); } catch (const std::exception& e) { ctx.logger().error("while calling python, caught exception: {}", e.what()); } catch (...) { diff --git a/plugins/serialize/CMakeLists.txt b/plugins/serialize/CMakeLists.txt index 997be0d88..512c55c28 100644 --- a/plugins/serialize/CMakeLists.txt +++ b/plugins/serialize/CMakeLists.txt @@ -38,9 +38,7 @@ add_library(pdi_serialize_plugin MODULE serialize.cxx) target_link_libraries(pdi_serialize_plugin PUBLIC PDI::PDI_plugins) set_target_properties(pdi_serialize_plugin PROPERTIES CXX_VISIBILITY_PRESET hidden) -if(WITH_TIMER_REPORT) - target_compile_definitions(pdi_serialize_plugin PUBLIC WITH_TIMER_REPORT) -endif() + # installation set(INSTALL_PDIPLUGINDIR "${PDI_DEFAULT_PLUGINDIR}" CACHE PATH "PDI plugins (${PDI_DEFAULT_PLUGINDIR})") install(TARGETS pdi_serialize_plugin diff --git a/plugins/serialize/serialize.cxx b/plugins/serialize/serialize.cxx index 423bb00f7..e37ea71bd 100644 --- a/plugins/serialize/serialize.cxx +++ b/plugins/serialize/serialize.cxx @@ -40,7 +40,6 @@ #include #include #include -#include #include namespace { @@ -273,7 +272,7 @@ struct serialize_plugin: PDI::Plugin { */ void share_serialized(const std::string& desc_name, PDI::Ref ref) { - START_TIMER(pretty_name()); + context().timer().startTimer(pretty_name()); std::string serialized_name = m_desc_to_serialize[desc_name]; context().logger().debug("Serializing `{}` as `{}`", desc_name, serialized_name); PDI::Datatype_sptr serialized_type = serialize_type(ref.type()); @@ -335,7 +334,7 @@ struct serialize_plugin: PDI::Plugin { ); m_serialized_remove_callback.emplace_back(serialized_name, remove_callback, PDI_IN); } - STOP_TIMER(pretty_name()); + context().timer().stopTimer(pretty_name()); } void release_serialized(const std::string& desc_name, PDI::Ref ref) diff --git a/plugins/user_code/CMakeLists.txt b/plugins/user_code/CMakeLists.txt index 6566251a8..1444fdb50 100644 --- a/plugins/user_code/CMakeLists.txt +++ b/plugins/user_code/CMakeLists.txt @@ -41,9 +41,7 @@ find_package(PDI REQUIRED COMPONENTS plugins) add_library(pdi_user_code_plugin MODULE user_code.cxx) target_link_libraries(pdi_user_code_plugin PDI::PDI_plugins) set_target_properties(pdi_user_code_plugin PROPERTIES CXX_VISIBILITY_PRESET hidden) -if(WITH_TIMER_REPORT) - target_compile_definitions(pdi_user_code_plugin PUBLIC WITH_TIMER_REPORT) -endif() + # installation set(INSTALL_PDIPLUGINDIR "${PDI_DEFAULT_PLUGINDIR}" CACHE PATH "PDI plugins (${PDI_DEFAULT_PLUGINDIR})") install(TARGETS pdi_user_code_plugin diff --git a/plugins/user_code/user_code.cxx b/plugins/user_code/user_code.cxx index 28a08da4f..41e302acc 100644 --- a/plugins/user_code/user_code.cxx +++ b/plugins/user_code/user_code.cxx @@ -38,7 +38,6 @@ #include #include #include -#include namespace { @@ -161,7 +160,7 @@ class Trigger /// call the function that has been registered void call(Context& ctx, const std::string& name) { - START_TIMER(name); + ctx.timer().startTimer(name); // all exposed aliases that will be unexposed on destroy vector exposed_aliases; for (auto&& alias: m_aliases) { @@ -175,7 +174,7 @@ class Trigger } catch (...) { ctx.logger().error("While calling user code, caught exception"); } - STOP_TIMER(name); + ctx.timer().stopTimer(name); } }; // class Trigger From 28e3bbc3c87ff6f5b300bc8ee5f2366b8e83d984 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 20 Mar 2026 14:08:25 +0100 Subject: [PATCH 22/38] update mock --- pdi/tests/mocks/context_mock.h | 1 + 1 file changed, 1 insertion(+) diff --git a/pdi/tests/mocks/context_mock.h b/pdi/tests/mocks/context_mock.h index 566c855c1..edd1b3e29 100644 --- a/pdi/tests/mocks/context_mock.h +++ b/pdi/tests/mocks/context_mock.h @@ -52,6 +52,7 @@ struct MockContext: public PDI::Context { MOCK_METHOD1(event, void(const char*)); MOCK_METHOD0(logger, PDI::Logger&()); + MOCK_METHOD0(timer, PDI::Timer&()); MOCK_METHOD1(datatype, PDI::Datatype_template_sptr(PC_tree_t)); MOCK_METHOD2(add_datatype, void(const std::string&, Datatype_template_parser)); From 261c89ef3bcc2a66682fe45902acbeee946605b4 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 20 Mar 2026 14:24:59 +0100 Subject: [PATCH 23/38] fix indent --- pdi/include/pdi/timer.h | 35 ++---------------- pdi/src/timer.cxx | 80 ++++++++--------------------------------- 2 files changed, 16 insertions(+), 99 deletions(-) diff --git a/pdi/include/pdi/timer.h b/pdi/include/pdi/timer.h index 88317faac..d190180b4 100644 --- a/pdi/include/pdi/timer.h +++ b/pdi/include/pdi/timer.h @@ -39,29 +39,10 @@ class PDI_EXPORT Timer { public: Timer(const Timer&) = delete; - Timer() {} - - void operator= (const Timer&) = delete; - - void startTimer(const std::string& name); - void stopTimer(const std::string& name); - void printReport() const; - void printReport(const std::string& name) const; - - const std::map& getResults(); - -private: - std::map start_times; - std::map accumulated_times; -}; -class PDI_EXPORT TimerManager -{ -public: - TimerManager(const TimerManager&) = delete; - void operator= (const TimerManager&) = delete; + Timer() {} - static TimerManager& getInstance(); + void operator= (const Timer&) = delete; void startTimer(const std::string& name); void stopTimer(const std::string& name); @@ -71,20 +52,8 @@ class PDI_EXPORT TimerManager const std::map& getResults(); private: - TimerManager() {} - std::map start_times; std::map accumulated_times; }; } // namespace PDI -#ifdef WITH_TIMER_REPORT -#define START_TIMER(name) PDI::TimerManager::getInstance().startTimer(name) -#define STOP_TIMER(name) PDI::TimerManager::getInstance().stopTimer(name) -#define PRINT_TIMER_REPORT() PDI::TimerManager::getInstance().printReport() -#else -#define START_TIMER(name) -#define STOP_TIMER(name) -#define PRINT_TIMER_REPORT() -#endif - #endif // PDI_TIMER_H_ diff --git a/pdi/src/timer.cxx b/pdi/src/timer.cxx index 040b0032b..8e3ab4078 100644 --- a/pdi/src/timer.cxx +++ b/pdi/src/timer.cxx @@ -26,96 +26,41 @@ namespace PDI { - - -// Stop a timer and accumulate the duration -void Timer::stopTimer(const std::string& name) -{ - #ifdef WITH_TIMER_REPORT - auto end_time = std::chrono::high_resolution_clock::now(); - - if (start_times.find(name) != start_times.end()) { - std::chrono::duration elapsed = end_time - start_times[name]; - accumulated_times[name] += elapsed.count(); - } - #endif -} // Start a timer by name void Timer::startTimer(const std::string& name) { - #ifdef WITH_TIMER_REPORT - start_times[name] = std::chrono::high_resolution_clock::now(); - #endif -} - -// Export the results -void Timer::printReport() const -{ - #ifdef WITH_TIMER_REPORT - std::cout << "\n--- Full Timer Report ---" << std::endl; - for (const auto& [name, duration]: accumulated_times) { - std::cout << name << ": " << duration << " seconds" << std::endl; - } - #endif -} - -void Timer::printReport(const std::string& name) const -{ - #ifdef WITH_TIMER_REPORT - std::cout << "\n--- Timer Report : " << std::endl; - auto it = accumulated_times.find(name); - - if (it != accumulated_times.end()) { - std::cout << name << " : " << it->second << " seconds" << std::endl; - } else { - std::cout << name << " timer not found." << std::endl; - } - #endif -} - -// Get the map directly (useful for MPI export) -const std::map& Timer::getResults() -{ - #ifdef WITH_TIMER_REPORT - return accumulated_times; - #endif -} - - -TimerManager& TimerManager::getInstance() -{ - static TimerManager instance; - return instance; -} - -// Start a timer by name -void TimerManager::startTimer(const std::string& name) -{ +#ifdef WITH_TIMER_REPORT start_times[name] = std::chrono::high_resolution_clock::now(); +#endif } // Stop a timer and accumulate the duration -void TimerManager::stopTimer(const std::string& name) +void Timer::stopTimer(const std::string& name) { +#ifdef WITH_TIMER_REPORT auto end_time = std::chrono::high_resolution_clock::now(); if (start_times.find(name) != start_times.end()) { std::chrono::duration elapsed = end_time - start_times[name]; accumulated_times[name] += elapsed.count(); } +#endif } // Export the results -void TimerManager::printReport() const +void Timer::printReport() const { +#ifdef WITH_TIMER_REPORT std::cout << "\n--- Full Timer Report ---" << std::endl; for (const auto& [name, duration]: accumulated_times) { std::cout << name << ": " << duration << " seconds" << std::endl; } +#endif } -void TimerManager::printReport(const std::string& name) const +void Timer::printReport(const std::string& name) const { +#ifdef WITH_TIMER_REPORT std::cout << "\n--- Timer Report : " << std::endl; auto it = accumulated_times.find(name); @@ -124,11 +69,14 @@ void TimerManager::printReport(const std::string& name) const } else { std::cout << name << " timer not found." << std::endl; } +#endif } // Get the map directly (useful for MPI export) -const std::map& TimerManager::getResults() +const std::map& Timer::getResults() { +#ifdef WITH_TIMER_REPORT return accumulated_times; +#endif } } // namespace PDI From f69fc66caea2c632cce2b336a68a9e0fb8457ac6 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 20 Mar 2026 14:26:18 +0100 Subject: [PATCH 24/38] indent --- pdi/include/pdi/context_proxy.h | 2 +- pdi/src/global_context.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pdi/include/pdi/context_proxy.h b/pdi/include/pdi/context_proxy.h index be79de82c..bca594672 100644 --- a/pdi/include/pdi/context_proxy.h +++ b/pdi/include/pdi/context_proxy.h @@ -45,7 +45,7 @@ class PDI_EXPORT Context_proxy: public Context /// Logger of the plugin Logger m_plugin_logger; - Timer *m_plugin_timer; + Timer* m_plugin_timer; public: /** Creates Context proxy without plugin logger diff --git a/pdi/src/global_context.h b/pdi/src/global_context.h index 2aa827b43..eeb275e36 100644 --- a/pdi/src/global_context.h +++ b/pdi/src/global_context.h @@ -122,7 +122,7 @@ class PDI_EXPORT Global_context: public Context void event(const char* name) override; Logger& logger() override; - + Timer& timer() override; Datatype_template_sptr datatype(PC_tree_t node) override; From 89f658cebb159ae4e53c3d846e1f97bd9da66603 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 20 Mar 2026 14:35:48 +0100 Subject: [PATCH 25/38] remove old calls --- plugins/decl_netcdf/dnc_file_context.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/decl_netcdf/dnc_file_context.cxx b/plugins/decl_netcdf/dnc_file_context.cxx index eb05f9bcc..9fa575fcc 100644 --- a/plugins/decl_netcdf/dnc_file_context.cxx +++ b/plugins/decl_netcdf/dnc_file_context.cxx @@ -282,7 +282,7 @@ void Dnc_file_context::execute(const std::string& desc_name, PDI::Ref ref) void Dnc_file_context::execute() { - START_TIMER(pretty_name()); + m_ctx.timer().startTimer(pretty_name()); if (m_when.to_long(m_ctx)) { std::list variables_holder; std::vector variables_to_get; @@ -357,7 +357,7 @@ void Dnc_file_context::execute() i++; } } - STOP_TIMER(pretty_name()); + m_ctx.timer().stopTimer(pretty_name()); } } // namespace decl_netcdf From e2c23d17557c9a386fddbd51c2406104061e8a70 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 20 Mar 2026 14:46:15 +0100 Subject: [PATCH 26/38] reactive unit tests --- pdi/tests/CMakeLists.txt | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/pdi/tests/CMakeLists.txt b/pdi/tests/CMakeLists.txt index 9deadcbc6..8c0bd8606 100644 --- a/pdi/tests/CMakeLists.txt +++ b/pdi/tests/CMakeLists.txt @@ -75,32 +75,32 @@ add_executable(PDI_unit_tests PDI_tuple_datatype.cxx ) -# set(OPERAND_TYPES uint8_t int64_t float double) -# foreach(OPERAND1_TYPE IN LISTS OPERAND_TYPES) -# foreach(OPERAND2_TYPE IN LISTS OPERAND_TYPES) -# string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") -# configure_file(expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) -# target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") -# endforeach() -# endforeach() +set(OPERAND_TYPES uint8_t int64_t float double) +foreach(OPERAND1_TYPE IN LISTS OPERAND_TYPES) + foreach(OPERAND2_TYPE IN LISTS OPERAND_TYPES) + string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") + configure_file(expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) + target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") + endforeach() +endforeach() -# set(PARSEABLE_OPERAND_TYPES long double) -# foreach(OPERAND1_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) -# foreach(OPERAND2_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) -# string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") -# configure_file(parsed_expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) -# target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") -# endforeach() -# endforeach() +set(PARSEABLE_OPERAND_TYPES long double) +foreach(OPERAND1_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) + foreach(OPERAND2_TYPE IN LISTS PARSEABLE_OPERAND_TYPES) + string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") + configure_file(parsed_expression.cxx "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) + target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/parsed_expression_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") + endforeach() +endforeach() -# set(MODULABLE_OPERAND_TYPES uint8_t int64_t) -# foreach(OPERAND1_TYPE IN LISTS MODULABLE_OPERAND_TYPES) -# foreach(OPERAND2_TYPE IN LISTS MODULABLE_OPERAND_TYPES) -# string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") -# configure_file(modulo.cxx "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) -# target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") -# endforeach() -# endforeach() +set(MODULABLE_OPERAND_TYPES uint8_t int64_t) +foreach(OPERAND1_TYPE IN LISTS MODULABLE_OPERAND_TYPES) + foreach(OPERAND2_TYPE IN LISTS MODULABLE_OPERAND_TYPES) + string(REPLACE "_" "U" CASE_NAME "${OPERAND1_TYPE}U${OPERAND2_TYPE}") + configure_file(modulo.cxx "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx" @ONLY) + target_sources(PDI_unit_tests PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/modulo_${OPERAND1_TYPE}_${OPERAND2_TYPE}.cxx") + endforeach() +endforeach() target_compile_features(PDI_unit_tests PRIVATE cxx_std_17) target_link_libraries(PDI_unit_tests PDI::PDI_plugins Threads::Threads GTest::gtest GTest::gtest_main GTest::gmock GTest::gmock_main) From b82a3fbc665b5085fa1aafa7fc898227c7405a05 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Tue, 31 Mar 2026 11:25:42 +0200 Subject: [PATCH 27/38] Remove Apple-specific link options from CMakeLists Removed conditional linking options for Apple. --- pdi/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/pdi/CMakeLists.txt b/pdi/CMakeLists.txt index ad13c0062..2e2809f6b 100644 --- a/pdi/CMakeLists.txt +++ b/pdi/CMakeLists.txt @@ -243,9 +243,6 @@ if("${BUILD_PYTHON}") "$" PRIVATE "$" ) - if(APPLE) - target_link_options(PDI_pysupport PUBLIC "-undefined" "dynamic_lookup") - endif() target_link_libraries(PDI_pysupport PUBLIC pybind11::pybind11 PDI::PDI_plugins) set_property(TARGET PDI_pysupport PROPERTY LIBRARY_OUTPUT_NAME "pdi_pysupport") set_property(TARGET PDI_pysupport PROPERTY ENABLE_EXPORTS TRUE) From a543aa532301679548acbbbb48bde26ce94348f3 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Tue, 31 Mar 2026 11:26:15 +0200 Subject: [PATCH 28/38] Remove Apple-specific link options from CMakeLists Removed conditional linking options for Apple. --- plugins/pycall/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/pycall/CMakeLists.txt b/plugins/pycall/CMakeLists.txt index efcf3964f..a3e2db624 100644 --- a/plugins/pycall/CMakeLists.txt +++ b/plugins/pycall/CMakeLists.txt @@ -50,9 +50,6 @@ add_library(pdi_pycall_plugin MODULE pycall.cxx) target_link_libraries(pdi_pycall_plugin PDI::PDI_pysupport pybind11::embed Python3::Python) set_target_properties(pdi_pycall_plugin PROPERTIES CXX_VISIBILITY_PRESET hidden) -if(APPLE) - target_link_options(pdi_pycall_plugin PRIVATE "-undefined" "dynamic_lookup") -endif() # installation set(INSTALL_PDIPLUGINDIR "${PDI_DEFAULT_PLUGINDIR}" CACHE PATH "PDI plugins (${PDI_DEFAULT_PLUGINDIR})") install(TARGETS pdi_pycall_plugin From 12ac8dac39e46e3ade9a91c44744027e343436fd Mon Sep 17 00:00:00 2001 From: yushan wang Date: Tue, 31 Mar 2026 11:42:18 +0200 Subject: [PATCH 29/38] update changelog --- CHANGELOG.md | 1 + pdi/CHANGELOG.md | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8217e8a71..a30a2b7ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] ### Added +* A compile option `WITH_TIMER_REPORT` is added to generate timer for all plugins. ### Changed diff --git a/pdi/CHANGELOG.md b/pdi/CHANGELOG.md index a83d3f5d0..82641778b 100644 --- a/pdi/CHANGELOG.md +++ b/pdi/CHANGELOG.md @@ -16,7 +16,6 @@ and this project adheres to ### For users #### Added -* A compile option `WITH_TIMER_REPORT` is added to generate timer for all plugins. #### Changed From f0f13ddc21a1b2d84b3076f602fec6806f5cae6f Mon Sep 17 00:00:00 2001 From: yushan wang Date: Tue, 31 Mar 2026 11:47:43 +0200 Subject: [PATCH 30/38] update copyright end date --- pdi/include/pdi/context.h | 2 +- pdi/include/pdi/context_proxy.h | 2 +- pdi/src/context_proxy.cxx | 2 +- pdi/src/global_context.cxx | 2 +- pdi/src/global_context.h | 2 +- pdi/src/pdi.cxx | 2 +- pdi/tests/mocks/context_mock.h | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pdi/include/pdi/context.h b/pdi/include/pdi/context.h index 3970461dc..7d2547b46 100644 --- a/pdi/include/pdi/context.h +++ b/pdi/include/pdi/context.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2015-2024 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2015-2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * Copyright (C) 2021 Institute of Bioorganic Chemistry Polish Academy of Science (PSNC) * All rights reserved. * diff --git a/pdi/include/pdi/context_proxy.h b/pdi/include/pdi/context_proxy.h index bca594672..2b080e92f 100644 --- a/pdi/include/pdi/context_proxy.h +++ b/pdi/include/pdi/context_proxy.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2021-2024 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2021-2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * Copyright (C) 2019-2021 Institute of Bioorganic Chemistry Polish Academy of Science (PSNC) * All rights reserved. * diff --git a/pdi/src/context_proxy.cxx b/pdi/src/context_proxy.cxx index c698d5916..efd363f96 100644 --- a/pdi/src/context_proxy.cxx +++ b/pdi/src/context_proxy.cxx @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2021-2024 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2021-2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * Copyright (C) 2019-2021 Institute of Bioorganic Chemistry Polish Academy of Science (PSNC) * All rights reserved. * diff --git a/pdi/src/global_context.cxx b/pdi/src/global_context.cxx index d94c621ae..377b3f6ae 100644 --- a/pdi/src/global_context.cxx +++ b/pdi/src/global_context.cxx @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2015-2024 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2015-2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * Copyright (C) 2021 Institute of Bioorganic Chemistry Polish Academy of Science (PSNC) * All rights reserved. * diff --git a/pdi/src/global_context.h b/pdi/src/global_context.h index eeb275e36..36d5c8253 100644 --- a/pdi/src/global_context.h +++ b/pdi/src/global_context.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2015-2025 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2015-2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * Copyright (C) 2021 Institute of Bioorganic Chemistry Polish Academy of Science (PSNC) * All rights reserved. * diff --git a/pdi/src/pdi.cxx b/pdi/src/pdi.cxx index f134a829d..26a3f5d99 100644 --- a/pdi/src/pdi.cxx +++ b/pdi/src/pdi.cxx @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2015-2025 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2015-2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * Copyright (C) 2021 Institute of Bioorganic Chemistry Polish Academy of Science (PSNC) * All rights reserved. * diff --git a/pdi/tests/mocks/context_mock.h b/pdi/tests/mocks/context_mock.h index edd1b3e29..52cc92b06 100644 --- a/pdi/tests/mocks/context_mock.h +++ b/pdi/tests/mocks/context_mock.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2021-2024 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * Copyright (C) 2021-2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) * Copyright (C) 2018-2021 Institute of Bioorganic Chemistry Polish Academy of Science (PSNC) * All rights reserved. * From 8875860ff692a345f673f9a570f56315aaa5fd7a Mon Sep 17 00:00:00 2001 From: Julian Auriac Date: Wed, 1 Apr 2026 15:40:17 +0200 Subject: [PATCH 31/38] Add optional yaml config member to enable timer, and add an integration test --- pdi/src/global_context.cxx | 8 ++++++++ pdi/src/global_context.h | 4 ++++ pdi/src/pdi.cxx | 9 +++++++-- tests/CMakeLists.txt | 4 ++++ tests/test_12.yml | 37 +++++++++++++++++++++++++++++++++++++ 5 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 tests/test_12.yml diff --git a/pdi/src/global_context.cxx b/pdi/src/global_context.cxx index 377b3f6ae..6774af73d 100644 --- a/pdi/src/global_context.cxx +++ b/pdi/src/global_context.cxx @@ -106,7 +106,15 @@ Global_context::Global_context(PC_tree_t conf) : m_logger{"PDI", PC_get(conf, ".logging")} , m_plugins{*this, conf} , m_callbacks{*this} + , m_timer_enabled{false} { + PC_tree_t timer_node = PC_get(conf, ".timer"); + if (!PC_status(timer_node)) { + long val = 0; + PC_int(timer_node, &val); + m_timer_enabled = (val != 0); + } + // load basic datatypes Datatype_template::load_basic_datatypes(*this); // load user datatypes diff --git a/pdi/src/global_context.h b/pdi/src/global_context.h index 36d5c8253..ae6995d8c 100644 --- a/pdi/src/global_context.h +++ b/pdi/src/global_context.h @@ -61,6 +61,8 @@ class PDI_EXPORT Global_context: public Context /// Global timer of PDI Timer m_timer; + bool m_timer_enabled; + /// Datatype_template constructors available in PDI std::unordered_map m_datatype_parsers; @@ -133,6 +135,8 @@ class PDI_EXPORT Global_context: public Context void finalize_and_exit() override; + bool timer_enabled() const { return m_timer_enabled; } + ~Global_context() override; }; diff --git a/pdi/src/pdi.cxx b/pdi/src/pdi.cxx index 26a3f5d99..8c41e5858 100644 --- a/pdi/src/pdi.cxx +++ b/pdi/src/pdi.cxx @@ -172,7 +172,9 @@ try { g_transaction.clear(); g_transaction_data.clear(); Global_context::init(conf); - Global_context::context().timer().startTimer("PDI"); + if (Global_context::context().timer_enabled()) { + Global_context::context().timer().startTimer("PDI"); + } return PDI_OK; } catch (const Error& e) { return g_error_context.return_err(e); @@ -187,7 +189,10 @@ try { Paraconf_wrapper fw; g_transaction.clear(); g_transaction_data.clear(); - Global_context::context().timer().stopTimer("PDI"); + if (Global_context::context().timer_enabled()) { + Global_context::context().timer().stopTimer("PDI"); + Global_context::context().timer().printReport(); + } Global_context::context().timer().printReport(); Global_context::finalize(); return PDI_OK; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 887f0fc97..c62094dfd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -54,6 +54,10 @@ add_executable(test_04_C test_04.c) target_link_libraries(test_04_C paraconf::paraconf PDI::PDI_C) add_test(NAME test_04_C COMMAND "$" "${CMAKE_CURRENT_SOURCE_DIR}/test_04.yml") +add_executable(test_12_C test_01.c) +target_link_libraries(test_12_C paraconf::paraconf PDI::PDI_C) +add_test(NAME test_12_C COMMAND "$" "${CMAKE_CURRENT_SOURCE_DIR}/test_12.yml") + endif("${BUILD_DECL_HDF5_PLUGIN}" AND "${BUILD_SERIALIZE_PLUGIN}") if("${BUILD_DECL_NETCDF_PLUGIN}" AND "${BUILD_SERIALIZE_PLUGIN}") diff --git a/tests/test_12.yml b/tests/test_12.yml new file mode 100644 index 000000000..a7e82c9ca --- /dev/null +++ b/tests/test_12.yml @@ -0,0 +1,37 @@ +timer: true +logging: trace +metadata: + input: int +data: + scalar_data: int + array_data: + type: array + subtype: int + size: 8 + subsize: 4 + start: 2 + record_data: + type: record + buffersize: 16 + members: + a: + disp: 0 + type: int + b: + disp: 8 + type: pointer + subtype: int + +plugins: + serialize: + scalar_data: scalar_data_serialized + array_data: array_data_serialized + record_data: record_data_serialized + decl_hdf5: + - file: serialize_test_06.h5 + when: $input=0 + write: [scalar_data_serialized, array_data_serialized, record_data_serialized] + - file: serialize_test_06.h5 + when: $input=1 + read: [scalar_data_serialized, array_data_serialized, record_data_serialized] + From 04d73e3f4bbc610d0fffce4c2c26b2bd6ccd6c93 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 2 Apr 2026 15:19:53 +0200 Subject: [PATCH 32/38] rename example.yml to timer.yml --- example/{example.yml => timer.yml} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename example/{example.yml => timer.yml} (95%) diff --git a/example/example.yml b/example/timer.yml similarity index 95% rename from example/example.yml rename to example/timer.yml index 206dba749..49ad3d80d 100644 --- a/example/example.yml +++ b/example/timer.yml @@ -1,9 +1,9 @@ # duration in seconds duration: 0.75 # global [height, width] (excluding boundary conditions or ghosts) -datasize: [6, 2] +datasize: [60, 12] # degree of parallelism -parallelism: { height: 1, width: 1 } +parallelism: { height: 3, width: 1 } # only the following config is passed to PDI pdi: @@ -14,7 +14,7 @@ pdi: pcoord: { size: 2, type: array, subtype: int } # coordinate of the process data: # type of values for which PDI does not keep a copy main_field: { size: [ '$dsize[0]', '$dsize[1]' ], type: array, subtype: double } - + timer: true plugins: mpi: decl_hdf5: @@ -40,13 +40,13 @@ pdi: file: data.nc communicator: $MPI_COMM_WORLD # the MPI communicator used for HDF5 parallel synchronized write variables: # type of the datasets to create in file - data: + v_data: type: array subtype: double size: [10, '$psize[0]*$dsize[0]', '$psize[1]*$dsize[1]'] write: main_field: # the name of the data to write - variable: data + variable: v_data when: '$iter<10' # do only write the first 10 iterations (0...9) variable_selection: # only write into a single slice in time subsize: [1, '$dsize[0]', '$dsize[1]'] From f3b62fad603984eb11ce76c4f5f94a3a62e3f6dd Mon Sep 17 00:00:00 2001 From: yushan wang Date: Thu, 2 Apr 2026 17:49:28 +0200 Subject: [PATCH 33/38] code cleanup based on review notes --- CHANGELOG.md | 1 - CMakeLists.txt | 7 ++++-- pdi/CHANGELOG.md | 1 + pdi/CMakeLists.txt | 3 --- pdi/include/pdi/timer.h | 3 +++ pdi/src/global_context.cxx | 5 +--- pdi/src/global_context.h | 4 ---- pdi/src/pdi.cxx | 9 ++----- pdi/src/timer.cxx | 48 +++++++++++++++++--------------------- tests/CMakeLists.txt | 4 ---- tests/test_12.yml | 37 ----------------------------- 11 files changed, 34 insertions(+), 88 deletions(-) delete mode 100644 tests/test_12.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index a30a2b7ed..8217e8a71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] ### Added -* A compile option `WITH_TIMER_REPORT` is added to generate timer for all plugins. ### Changed diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e7d800bb..c01cfabe2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,6 @@ option(BUILD_SHARED_LIBS "Build shared libraries rather than static ones" option(BUILD_TRACE_PLUGIN "Build Trace plugin" ON) option(BUILD_USER_CODE_PLUGIN "Build User-code plugin" ON) option(BUILD_JSON_PLUGIN "Build JSON plugin" OFF) -option(WITH_TIMER_REPORT "Enable timer" ON) ### Default build type @@ -285,6 +284,7 @@ endif() ## HDF5 if("${BUILD_DECL_HDF5_PLUGIN}" OR "${BUILD_DECL_NETCDF_PLUGIN}") + find_package(HDF5 COMPONENTS C ) set(HDF5_CMAKE_CACHE_ARGS) if("${BUILD_HDF5_PARALLEL}") @@ -306,7 +306,7 @@ if("${BUILD_DECL_HDF5_PLUGIN}" OR "${BUILD_DECL_NETCDF_PLUGIN}") sbuild_add_dependency(HDF5 "${USE_DEFAULT}" EMBEDDED_PATH "vendor/hdf5-1.12.3" COMPONENTS ${HDF5_COMPONENTS} - MODULE_VARS HDF5_IS_PARALLEL HDF5_VERSION + MODULE_VARS HDF5_IS_PARALLEL HDF5_PROVIDES_PARALLEL HDF5_VERSION CMAKE_CACHE_ARGS -DBUILD_STATIC_LIBS:BOOL=OFF -DBUILD_TESTING:BOOL=OFF @@ -324,6 +324,9 @@ if("${BUILD_DECL_HDF5_PLUGIN}" OR "${BUILD_DECL_NETCDF_PLUGIN}") if("${HDF5_VERSION}" VERSION_LESS 1.10) message(FATAL_ERROR "HDF5 version 1.10 at least required, HDF5 ${HDF5_VERSION} found.") endif() + if("${HDF5_VERSION}" VERSION_GREATER_EQUAL 2.0.0) + set(HDF5_IS_PARALLEL "${HDF5_PROVIDES_PARALLEL}") + endif() if("${BUILD_HDF5_PARALLEL}" AND NOT "${HDF5_IS_PARALLEL}") message(FATAL_ERROR "You requested a parallel HDF5 build (-DBUILD_HDF5_PARALLEL=ON) but a sequential SYSTEM version has been found\n" diff --git a/pdi/CHANGELOG.md b/pdi/CHANGELOG.md index 82641778b..34865d479 100644 --- a/pdi/CHANGELOG.md +++ b/pdi/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to ### For users #### Added +* A timer is added to reflect the time consumed by plugins. #### Changed diff --git a/pdi/CMakeLists.txt b/pdi/CMakeLists.txt index 2e2809f6b..0c6dfcc26 100644 --- a/pdi/CMakeLists.txt +++ b/pdi/CMakeLists.txt @@ -171,9 +171,6 @@ target_link_libraries(PDI_C PUBLIC paraconf::paraconf ${CMAKE_DL_LIBS} PRIVATE spdlog::spdlog) target_compile_features(PDI_C PRIVATE cxx_std_17 c_std_11) -if(WITH_TIMER_REPORT) - target_compile_definitions(PDI_C PUBLIC WITH_TIMER_REPORT) -endif() set_property(TARGET PDI_C PROPERTY LIBRARY_OUTPUT_NAME "pdi") set_property(TARGET PDI_C PROPERTY ENABLE_EXPORTS TRUE) set_property(TARGET PDI_C PROPERTY C_VISIBILITY_PRESET hidden) diff --git a/pdi/include/pdi/timer.h b/pdi/include/pdi/timer.h index d190180b4..375fc4112 100644 --- a/pdi/include/pdi/timer.h +++ b/pdi/include/pdi/timer.h @@ -51,9 +51,12 @@ class PDI_EXPORT Timer const std::map& getResults(); + void enable_timer(const bool choice) { timer_enabled = choice; } + private: std::map start_times; std::map accumulated_times; + bool timer_enabled = false; }; } // namespace PDI #endif // PDI_TIMER_H_ diff --git a/pdi/src/global_context.cxx b/pdi/src/global_context.cxx index 6774af73d..0afa18e17 100644 --- a/pdi/src/global_context.cxx +++ b/pdi/src/global_context.cxx @@ -106,13 +106,10 @@ Global_context::Global_context(PC_tree_t conf) : m_logger{"PDI", PC_get(conf, ".logging")} , m_plugins{*this, conf} , m_callbacks{*this} - , m_timer_enabled{false} { PC_tree_t timer_node = PC_get(conf, ".timer"); if (!PC_status(timer_node)) { - long val = 0; - PC_int(timer_node, &val); - m_timer_enabled = (val != 0); + m_timer.enable_timer(to_bool(timer_node)); } // load basic datatypes diff --git a/pdi/src/global_context.h b/pdi/src/global_context.h index ae6995d8c..36d5c8253 100644 --- a/pdi/src/global_context.h +++ b/pdi/src/global_context.h @@ -61,8 +61,6 @@ class PDI_EXPORT Global_context: public Context /// Global timer of PDI Timer m_timer; - bool m_timer_enabled; - /// Datatype_template constructors available in PDI std::unordered_map m_datatype_parsers; @@ -135,8 +133,6 @@ class PDI_EXPORT Global_context: public Context void finalize_and_exit() override; - bool timer_enabled() const { return m_timer_enabled; } - ~Global_context() override; }; diff --git a/pdi/src/pdi.cxx b/pdi/src/pdi.cxx index 8c41e5858..26a3f5d99 100644 --- a/pdi/src/pdi.cxx +++ b/pdi/src/pdi.cxx @@ -172,9 +172,7 @@ try { g_transaction.clear(); g_transaction_data.clear(); Global_context::init(conf); - if (Global_context::context().timer_enabled()) { - Global_context::context().timer().startTimer("PDI"); - } + Global_context::context().timer().startTimer("PDI"); return PDI_OK; } catch (const Error& e) { return g_error_context.return_err(e); @@ -189,10 +187,7 @@ try { Paraconf_wrapper fw; g_transaction.clear(); g_transaction_data.clear(); - if (Global_context::context().timer_enabled()) { - Global_context::context().timer().stopTimer("PDI"); - Global_context::context().timer().printReport(); - } + Global_context::context().timer().stopTimer("PDI"); Global_context::context().timer().printReport(); Global_context::finalize(); return PDI_OK; diff --git a/pdi/src/timer.cxx b/pdi/src/timer.cxx index 8e3ab4078..778a86027 100644 --- a/pdi/src/timer.cxx +++ b/pdi/src/timer.cxx @@ -22,61 +22,57 @@ * THE SOFTWARE. ******************************************************************************/ +#include #include +#include "global_context.h" + namespace PDI { // Start a timer by name void Timer::startTimer(const std::string& name) { -#ifdef WITH_TIMER_REPORT - start_times[name] = std::chrono::high_resolution_clock::now(); -#endif + if (timer_enabled) start_times[name] = std::chrono::high_resolution_clock::now(); } // Stop a timer and accumulate the duration void Timer::stopTimer(const std::string& name) { -#ifdef WITH_TIMER_REPORT - auto end_time = std::chrono::high_resolution_clock::now(); + if (timer_enabled) { + auto end_time = std::chrono::high_resolution_clock::now(); - if (start_times.find(name) != start_times.end()) { - std::chrono::duration elapsed = end_time - start_times[name]; - accumulated_times[name] += elapsed.count(); + if (start_times.find(name) != start_times.end()) { + std::chrono::duration elapsed = end_time - start_times[name]; + accumulated_times[name] += elapsed.count(); + } } -#endif } // Export the results void Timer::printReport() const { -#ifdef WITH_TIMER_REPORT - std::cout << "\n--- Full Timer Report ---" << std::endl; - for (const auto& [name, duration]: accumulated_times) { - std::cout << name << ": " << duration << " seconds" << std::endl; + if (timer_enabled) { + for (const auto& [name, duration]: accumulated_times) { + Global_context::context().logger().info("{} : {} seconds", name, duration); + } } -#endif } void Timer::printReport(const std::string& name) const { -#ifdef WITH_TIMER_REPORT - std::cout << "\n--- Timer Report : " << std::endl; - auto it = accumulated_times.find(name); - - if (it != accumulated_times.end()) { - std::cout << name << " : " << it->second << " seconds" << std::endl; - } else { - std::cout << name << " timer not found." << std::endl; + if (timer_enabled) { + auto it = accumulated_times.find(name); + if (it != accumulated_times.end()) { + Global_context::context().logger().info("{} : {} seconds", name, it->second); + } else { + Global_context::context().logger().info("{} timer not found.", name); + } } -#endif } // Get the map directly (useful for MPI export) const std::map& Timer::getResults() { -#ifdef WITH_TIMER_REPORT - return accumulated_times; -#endif + if (timer_enabled) return accumulated_times; } } // namespace PDI diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c62094dfd..887f0fc97 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -54,10 +54,6 @@ add_executable(test_04_C test_04.c) target_link_libraries(test_04_C paraconf::paraconf PDI::PDI_C) add_test(NAME test_04_C COMMAND "$" "${CMAKE_CURRENT_SOURCE_DIR}/test_04.yml") -add_executable(test_12_C test_01.c) -target_link_libraries(test_12_C paraconf::paraconf PDI::PDI_C) -add_test(NAME test_12_C COMMAND "$" "${CMAKE_CURRENT_SOURCE_DIR}/test_12.yml") - endif("${BUILD_DECL_HDF5_PLUGIN}" AND "${BUILD_SERIALIZE_PLUGIN}") if("${BUILD_DECL_NETCDF_PLUGIN}" AND "${BUILD_SERIALIZE_PLUGIN}") diff --git a/tests/test_12.yml b/tests/test_12.yml deleted file mode 100644 index a7e82c9ca..000000000 --- a/tests/test_12.yml +++ /dev/null @@ -1,37 +0,0 @@ -timer: true -logging: trace -metadata: - input: int -data: - scalar_data: int - array_data: - type: array - subtype: int - size: 8 - subsize: 4 - start: 2 - record_data: - type: record - buffersize: 16 - members: - a: - disp: 0 - type: int - b: - disp: 8 - type: pointer - subtype: int - -plugins: - serialize: - scalar_data: scalar_data_serialized - array_data: array_data_serialized - record_data: record_data_serialized - decl_hdf5: - - file: serialize_test_06.h5 - when: $input=0 - write: [scalar_data_serialized, array_data_serialized, record_data_serialized] - - file: serialize_test_06.h5 - when: $input=1 - read: [scalar_data_serialized, array_data_serialized, record_data_serialized] - From a6d2617b55137078a1765091fd31ed741290af7e Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 3 Apr 2026 08:49:57 +0200 Subject: [PATCH 34/38] code cleanup [skip ci] --- plugins/decl_hdf5/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/decl_hdf5/CMakeLists.txt b/plugins/decl_hdf5/CMakeLists.txt index 3b3045c2d..970eba144 100644 --- a/plugins/decl_hdf5/CMakeLists.txt +++ b/plugins/decl_hdf5/CMakeLists.txt @@ -51,6 +51,7 @@ find_package(HDF5 REQUIRED COMPONENTS C) if("${HDF5_VERSION}" VERSION_LESS 1.10) message(FATAL_ERROR "HDF5 version 1.10 at least required, HDF5 ${HDF5_VERSION} found.") endif() + if("${BUILD_HDF5_PARALLEL}" AND NOT "${HDF5_IS_PARALLEL}") message(FATAL_ERROR "Parallel HDF5 required, sequential HDF5 only found. Please set -DBUILD_HDF5_PARALLEL=OFF to disable parallel HDF5") endif() From 6b8b82995b1cd2fbd0345eedaa6dcf377ae771c7 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 3 Apr 2026 08:53:13 +0200 Subject: [PATCH 35/38] Modify HDF5 configuration in CMakeLists.txt --- CMakeLists.txt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c01cfabe2..76ffe4767 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -284,9 +284,9 @@ endif() ## HDF5 if("${BUILD_DECL_HDF5_PLUGIN}" OR "${BUILD_DECL_NETCDF_PLUGIN}") - find_package(HDF5 COMPONENTS C ) + set(HDF5_CMAKE_CACHE_ARGS) - + if("${BUILD_HDF5_PARALLEL}") set(HDF5_PREFER_PARALLEL ON) list(APPEND HDF5_CMAKE_CACHE_ARGS "-DHDF5_ENABLE_PARALLEL:BOOL=ON") @@ -306,7 +306,7 @@ if("${BUILD_DECL_HDF5_PLUGIN}" OR "${BUILD_DECL_NETCDF_PLUGIN}") sbuild_add_dependency(HDF5 "${USE_DEFAULT}" EMBEDDED_PATH "vendor/hdf5-1.12.3" COMPONENTS ${HDF5_COMPONENTS} - MODULE_VARS HDF5_IS_PARALLEL HDF5_PROVIDES_PARALLEL HDF5_VERSION + MODULE_VARS HDF5_IS_PARALLEL HDF5_VERSION CMAKE_CACHE_ARGS -DBUILD_STATIC_LIBS:BOOL=OFF -DBUILD_TESTING:BOOL=OFF @@ -324,9 +324,6 @@ if("${BUILD_DECL_HDF5_PLUGIN}" OR "${BUILD_DECL_NETCDF_PLUGIN}") if("${HDF5_VERSION}" VERSION_LESS 1.10) message(FATAL_ERROR "HDF5 version 1.10 at least required, HDF5 ${HDF5_VERSION} found.") endif() - if("${HDF5_VERSION}" VERSION_GREATER_EQUAL 2.0.0) - set(HDF5_IS_PARALLEL "${HDF5_PROVIDES_PARALLEL}") - endif() if("${BUILD_HDF5_PARALLEL}" AND NOT "${HDF5_IS_PARALLEL}") message(FATAL_ERROR "You requested a parallel HDF5 build (-DBUILD_HDF5_PARALLEL=ON) but a sequential SYSTEM version has been found\n" From 1717266c019d3d62e572cf6d29d869996fdd1eb5 Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 3 Apr 2026 08:58:30 +0200 Subject: [PATCH 36/38] variable rename --- pdi/include/pdi/context_proxy.h | 2 +- pdi/src/context_proxy.cxx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pdi/include/pdi/context_proxy.h b/pdi/include/pdi/context_proxy.h index 2b080e92f..f3bbbffa5 100644 --- a/pdi/include/pdi/context_proxy.h +++ b/pdi/include/pdi/context_proxy.h @@ -45,7 +45,7 @@ class PDI_EXPORT Context_proxy: public Context /// Logger of the plugin Logger m_plugin_logger; - Timer* m_plugin_timer; + Timer* m_timer; public: /** Creates Context proxy without plugin logger diff --git a/pdi/src/context_proxy.cxx b/pdi/src/context_proxy.cxx index efd363f96..64b2854e8 100644 --- a/pdi/src/context_proxy.cxx +++ b/pdi/src/context_proxy.cxx @@ -36,12 +36,12 @@ namespace PDI { Context_proxy::Context_proxy(Context& ctx) : m_real_context{ctx} - , m_plugin_timer{&(ctx.timer())} + , m_timer{&(ctx.timer())} {} Context_proxy::Context_proxy(Context& ctx, const string& logger_name, PC_tree_t logging_tree) : m_real_context{ctx} - , m_plugin_timer{&(ctx.timer())} + , m_timer{&(ctx.timer())} , m_plugin_logger{m_real_context.logger(), logger_name, logging_tree} {} @@ -97,7 +97,7 @@ Logger& Context_proxy::logger() Timer& Context_proxy::timer() { - return *m_plugin_timer; + return *m_timer; } Logger& Context_proxy::pdi_core_logger() From 11da4eef51dc21960ba7f3e854fbd1750d58605c Mon Sep 17 00:00:00 2001 From: yushan wang Date: Fri, 3 Apr 2026 10:15:10 +0200 Subject: [PATCH 37/38] better check for calling timer --- pdi/include/pdi/timer.h | 2 -- pdi/src/timer.cxx | 53 ++++++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/pdi/include/pdi/timer.h b/pdi/include/pdi/timer.h index 375fc4112..8fabbc611 100644 --- a/pdi/include/pdi/timer.h +++ b/pdi/include/pdi/timer.h @@ -49,8 +49,6 @@ class PDI_EXPORT Timer void printReport() const; void printReport(const std::string& name) const; - const std::map& getResults(); - void enable_timer(const bool choice) { timer_enabled = choice; } private: diff --git a/pdi/src/timer.cxx b/pdi/src/timer.cxx index 778a86027..44d7e3de6 100644 --- a/pdi/src/timer.cxx +++ b/pdi/src/timer.cxx @@ -32,47 +32,50 @@ namespace PDI { // Start a timer by name void Timer::startTimer(const std::string& name) { - if (timer_enabled) start_times[name] = std::chrono::high_resolution_clock::now(); + if (!timer_enabled) return; + if (start_times.find(name) != start_times.end()) { + Global_context::context().logger().error("Timer for {} is already running. Ignoring the start", name); + return; + } + start_times[name] = std::chrono::high_resolution_clock::now(); } // Stop a timer and accumulate the duration void Timer::stopTimer(const std::string& name) { - if (timer_enabled) { - auto end_time = std::chrono::high_resolution_clock::now(); - - if (start_times.find(name) != start_times.end()) { - std::chrono::duration elapsed = end_time - start_times[name]; - accumulated_times[name] += elapsed.count(); - } + if (!timer_enabled) return; + auto it = start_times.find(name); + if (it == start_times.end()) { + Global_context::context().logger().error("Error: Cannot end timer for {} because it was never started.", name); + return; } + + auto end_time = std::chrono::high_resolution_clock::now(); + std::chrono::duration elapsed = end_time - start_times[name]; + + accumulated_times[name] += elapsed.count(); + start_times.erase(it); } -// Export the results +// Output the results of all timers void Timer::printReport() const { - if (timer_enabled) { - for (const auto& [name, duration]: accumulated_times) { - Global_context::context().logger().info("{} : {} seconds", name, duration); - } + if (!timer_enabled) return; + for (const auto& [name, duration]: accumulated_times) { + Global_context::context().logger().info("Totale time spent for {} : {} seconds", name, duration); } } +// Output the results of timer with name void Timer::printReport(const std::string& name) const { - if (timer_enabled) { - auto it = accumulated_times.find(name); - if (it != accumulated_times.end()) { - Global_context::context().logger().info("{} : {} seconds", name, it->second); - } else { - Global_context::context().logger().info("{} timer not found.", name); - } + if (!timer_enabled) return; + auto it = accumulated_times.find(name); + if (it != accumulated_times.end()) { + Global_context::context().logger().info("Totale time spent for {} : {} seconds", name, it->second); + } else { + Global_context::context().logger().error("Cannot find timer for {}.", name); } } -// Get the map directly (useful for MPI export) -const std::map& Timer::getResults() -{ - if (timer_enabled) return accumulated_times; -} } // namespace PDI From 63f0ca70f728d3863fe1f2291e1f186f4587d7ab Mon Sep 17 00:00:00 2001 From: yushan wang Date: Tue, 21 Apr 2026 14:14:01 +0200 Subject: [PATCH 38/38] implement timer as plugin --- CMakeLists.txt | 8 ++++ plugins/timer/CMakeLists.txt | 48 +++++++++++++++++++++ plugins/timer/README.md | 13 ++++++ plugins/timer/timer.cxx | 81 ++++++++++++++++++++++++++++++++++++ 4 files changed, 150 insertions(+) create mode 100644 plugins/timer/CMakeLists.txt create mode 100644 plugins/timer/README.md create mode 100644 plugins/timer/timer.cxx diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a074571f..a4e4bb605 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,7 @@ option(BUILD_SHARED_LIBS "Build shared libraries rather than static ones" option(BUILD_TRACE_PLUGIN "Build Trace plugin" ON) option(BUILD_USER_CODE_PLUGIN "Build User-code plugin" ON) option(BUILD_JSON_PLUGIN "Build JSON plugin" OFF) +option(BUILD_TIMER_PLUGIN "Build Timer plugin" ON) option(ENABLE_BENCHMARKING "Activate benchmarks in the test suite" OFF) ### Default build type @@ -534,3 +535,10 @@ sbuild_add_module(PDI_TEST_API INSTALL_COMMAND "" SUBSTEPS test ) + +sbuild_add_module(TIMER_PLUGIN + ENABLE_BUILD_FLAG BUILD_TIMER_PLUGIN + SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/plugins/timer" + DEPENDS PDI + # SUBSTEPS indent test +) diff --git a/plugins/timer/CMakeLists.txt b/plugins/timer/CMakeLists.txt new file mode 100644 index 000000000..1be07867a --- /dev/null +++ b/plugins/timer/CMakeLists.txt @@ -0,0 +1,48 @@ +#============================================================================= +# Copyright (C) 2023-2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of CEA nor the names of its contributors may be used to +# endorse or promote products derived from this software without specific +# prior written permission. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +#============================================================================= + +cmake_minimum_required(VERSION 3.22...4.2) +project(pdi_timer_plugin LANGUAGES C CXX) + +# Includes +include(CTest) +include(GNUInstallDirs) + +# PDI +find_package(PDI REQUIRED COMPONENTS plugins) + +# The plugin +add_library(pdi_timer_plugin MODULE timer.cxx) +target_link_libraries(pdi_timer_plugin PUBLIC PDI::PDI_plugins ) + +# Installation +set(INSTALL_PDIPLUGINDIR "${PDI_DEFAULT_PLUGINDIR}" CACHE PATH "PDI plugins (${PDI_DEFAULT_PLUGINDIR})") +install(TARGETS pdi_timer_plugin + LIBRARY DESTINATION "${INSTALL_PDIPLUGINDIR}" +) + +# Tests +# if("${BUILD_TESTING}") +# add_subdirectory(tests/) +# endif() diff --git a/plugins/timer/README.md b/plugins/timer/README.md new file mode 100644 index 000000000..1bff9ea1e --- /dev/null +++ b/plugins/timer/README.md @@ -0,0 +1,13 @@ +data: + ... + +plugins: + timer: + - recording: [decl_hdf5_start_timer, decl_hdf5_end_timer] # decl_hdf5_start/end_timer are events in PDI, not visible to users + # - recording: [json_start_timer, json_end_timer] + decl_hdf5: + - file: output.h5 + write: data + json: + - file: out.json + write: [var1, var2] \ No newline at end of file diff --git a/plugins/timer/timer.cxx b/plugins/timer/timer.cxx new file mode 100644 index 000000000..d58da2f88 --- /dev/null +++ b/plugins/timer/timer.cxx @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (C) 2026 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of CEA nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +using namespace PDI; + +/** The timer plugin +*/ +class timer_plugin: public PDI::Plugin +{ + // Map between data variables and a pair between condition and the output filenames + std::map start_times; + std::map accumulated_times; + bool timer_enabled = false; + +public: + timer_plugin(Context& ctx, PC_tree_t spec_tree) + : Plugin{ctx} + { + // initialize m_data_to_path_map from config.yml + // read_config_tree(ctx.logger(), spec_tree); + + ctx.logger().info("Plugin loaded successfully"); + } + + ~timer_plugin() { context().logger().info("Closing plugin"); } + + static std::string pretty_name() { return "TIMER"; } + +private: + /** Read the configuration file + * + * \param logger PDI's logger instance + * \param spec_tree the yaml tree + */ + // void read_config_tree(Logger& logger, PC_tree_t spec_tree) + // { + // } + +}; + +} // namespace +PDI_PLUGIN(timer)