From 9beae3dc0e16a1f0898ff05f85eb21eb989d4244 Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Mon, 6 May 2024 15:16:14 +0200 Subject: [PATCH] Simplify code for timer (#2032) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit close #2014 - Remove `IDurationCollector` and `NullDurationCollector`, keep only `DurationCollector` - Add new syntax - Add unit tests --------- Co-authored-by: Florian OMNES <26088210+flomnes@users.noreply.github.com> Co-authored-by: Florian Omnès --- src/libs/antares/CMakeLists.txt | 2 +- .../benchmarking/DurationCollector.cpp | 31 ++++++- .../antares/benchmarking/DurationCollector.h | 38 ++++----- .../include/antares/benchmarking/timer.h | 2 +- src/libs/antares/checks/CMakeLists.txt | 2 +- .../antares/study/include/antares/study/fwd.h | 2 +- src/libs/antares/writer/in_memory_writer.cpp | 24 +++++- .../include/antares/writer/in_memory_writer.h | 4 +- .../include/antares/writer/writer_factory.h | 4 +- src/libs/antares/writer/private/zip_writer.h | 8 +- src/libs/antares/writer/writer_factory.cpp | 2 +- src/libs/antares/writer/zip_writer.cpp | 4 +- src/packaging/CMakeLists.txt | 2 +- src/solver/application/application.cpp | 18 ++-- .../include/antares/application/application.h | 2 +- src/solver/main.cpp | 4 +- src/solver/main/economy.cpp | 49 +++++++++++ src/solver/simulation/CMakeLists.txt | 2 +- src/solver/simulation/adequacy_mode.cpp | 9 +- src/solver/simulation/economy_mode.cpp | 9 +- .../antares/solver/simulation/adequacy_mode.h | 4 +- .../antares/solver/simulation/economy_mode.h | 4 +- .../antares/solver/simulation/solver.h | 4 +- .../antares/solver/simulation/solver.hxx | 84 +++++++++---------- src/tests/end-to-end/utils/utils.cpp | 2 +- src/tests/end-to-end/utils/utils.h | 3 +- src/tests/src/libs/antares/CMakeLists.txt | 1 + .../libs/antares/benchmarking/CMakeLists.txt | 13 +++ .../benchmarking/test_duration_collector.cpp | 79 +++++++++++++++++ .../src/libs/antares/study/test_study.cpp | 2 +- .../src/libs/antares/writer/test_writer.cpp | 10 +-- .../test-store-timeseries-number.cpp | 12 +-- src/tools/ts-generator/main.cpp | 4 +- src/ui/simulator/application/application.cpp | 2 +- 34 files changed, 309 insertions(+), 133 deletions(-) create mode 100644 src/solver/main/economy.cpp create mode 100644 src/tests/src/libs/antares/benchmarking/CMakeLists.txt create mode 100644 src/tests/src/libs/antares/benchmarking/test_duration_collector.cpp diff --git a/src/libs/antares/CMakeLists.txt b/src/libs/antares/CMakeLists.txt index 05cc04769e..4eed2337db 100644 --- a/src/libs/antares/CMakeLists.txt +++ b/src/libs/antares/CMakeLists.txt @@ -66,4 +66,4 @@ import_std_libs(antares-core) install(DIRECTORY include/antares DESTINATION "include" -) \ No newline at end of file +) diff --git a/src/libs/antares/benchmarking/DurationCollector.cpp b/src/libs/antares/benchmarking/DurationCollector.cpp index 6d6dfe4db7..a226b8edc3 100644 --- a/src/libs/antares/benchmarking/DurationCollector.cpp +++ b/src/libs/antares/benchmarking/DurationCollector.cpp @@ -34,9 +34,38 @@ void DurationCollector::toFileContent(FileContent& file_content) { for (const auto& [name, durations] : duration_items_) { - const int64_t duration_sum = accumulate(durations.begin(), durations.end(), (int64_t)0); + const int64_t duration_sum = accumulate(durations.begin(), durations.end(), 0); file_content.addDurationItem(name, (unsigned int)duration_sum, (int)durations.size()); } } + +DurationCollector::OperationTimer DurationCollector::operator()(const std::string& key) +{ + return OperationTimer(*this, key); +} + +void DurationCollector::OperationTimer::addDuration(int64_t duration_ms) const +{ + const std::scoped_lock lock(collector.mutex_); + collector.duration_items_[key].push_back(duration_ms); +} + +void operator<<(const DurationCollector::OperationTimer& op, const std::function& f) +{ + using clock = std::chrono::steady_clock; + auto start_ = clock::now(); + f(); + auto end_ = clock::now(); + auto duration_ms = std::chrono::duration_cast(end_ - start_).count(); + op.addDuration(duration_ms); +} + +int64_t DurationCollector::getTime(const std::string& name) const +{ + const auto& v = duration_items_.at(name); + + return accumulate(v.begin(), v.end(), 0); +} + } // namespace Benchmarking diff --git a/src/libs/antares/benchmarking/include/antares/benchmarking/DurationCollector.h b/src/libs/antares/benchmarking/include/antares/benchmarking/DurationCollector.h index fbbe7ce873..9ca5800aaa 100644 --- a/src/libs/antares/benchmarking/include/antares/benchmarking/DurationCollector.h +++ b/src/libs/antares/benchmarking/include/antares/benchmarking/DurationCollector.h @@ -20,6 +20,8 @@ */ #pragma once +#include +#include #include #include #include @@ -30,31 +32,27 @@ namespace Benchmarking { -class IDurationCollector +class DurationCollector { public: - virtual ~IDurationCollector() = default; - virtual void addDuration(const std::string& name, int64_t duration) = 0; -}; + void toFileContent(FileContent& file_content); + void addDuration(const std::string& name, int64_t duration); -class NullDurationCollector : public IDurationCollector -{ -public: - NullDurationCollector() = default; - virtual ~NullDurationCollector() = default; - void addDuration(const std::string& /* name */, int64_t /* duration */) override - { /* Do nothing */ - } -}; + struct OperationTimer + { + OperationTimer(DurationCollector& collector, const std::string& key): + collector(collector), key(key) {} + void addDuration(int64_t duration_ms) const; -class DurationCollector : public IDurationCollector -{ -public: - DurationCollector() = default; - virtual ~DurationCollector() = default; + DurationCollector& collector; + const std::string key; + }; - void toFileContent(FileContent& file_content); - void addDuration(const std::string& name, int64_t duration) override; + OperationTimer operator()(const std::string& key); + + friend void operator<<(const OperationTimer& op, const std::function& f); + + int64_t getTime(const std::string& name) const; private: std::map> duration_items_; diff --git a/src/libs/antares/benchmarking/include/antares/benchmarking/timer.h b/src/libs/antares/benchmarking/include/antares/benchmarking/timer.h index e94d6ed9c9..42c6ad4679 100644 --- a/src/libs/antares/benchmarking/include/antares/benchmarking/timer.h +++ b/src/libs/antares/benchmarking/include/antares/benchmarking/timer.h @@ -21,7 +21,7 @@ #ifndef __ANTARES_LIBS_TIME_ELAPSED__TIME_ELAPSED_H__ #define __ANTARES_LIBS_TIME_ELAPSED__TIME_ELAPSED_H__ -#include +#include namespace Benchmarking { diff --git a/src/libs/antares/checks/CMakeLists.txt b/src/libs/antares/checks/CMakeLists.txt index 1bf013b871..e301b8b548 100644 --- a/src/libs/antares/checks/CMakeLists.txt +++ b/src/libs/antares/checks/CMakeLists.txt @@ -25,4 +25,4 @@ target_link_libraries(checks install(DIRECTORY include/antares DESTINATION "include" -) \ No newline at end of file +) diff --git a/src/libs/antares/study/include/antares/study/fwd.h b/src/libs/antares/study/include/antares/study/fwd.h index c5e5933691..857e0087f8 100644 --- a/src/libs/antares/study/include/antares/study/fwd.h +++ b/src/libs/antares/study/include/antares/study/fwd.h @@ -555,7 +555,7 @@ class Sets; namespace Benchmarking { -class IDurationCollector; +class DurationCollector; } #endif // __ANTARES_LIBS_STUDY_FWD_H__ diff --git a/src/libs/antares/writer/in_memory_writer.cpp b/src/libs/antares/writer/in_memory_writer.cpp index 32fc6ff000..1aa849d8e7 100644 --- a/src/libs/antares/writer/in_memory_writer.cpp +++ b/src/libs/antares/writer/in_memory_writer.cpp @@ -1,3 +1,23 @@ +/* +** Copyright 2007-2024, RTE (https://www.rte-france.com) +** See AUTHORS.txt +** SPDX-License-Identifier: MPL-2.0 +** This file is part of Antares-Simulator, +** Adequacy and Performance assessment for interconnected energy networks. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the Mozilla Public Licence 2.0 as published by +** the Mozilla Foundation, either version 2 of the License, or +** (at your option) any later version. +** +** Antares_Simulator is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** Mozilla Public Licence 2.0 for more details. +** +** You should have received a copy of the Mozilla Public Licence 2.0 +** along with Antares_Simulator. If not, see . +*/ #include #include @@ -23,7 +43,7 @@ void logErrorAndThrow [[noreturn]] (const std::string& errorMessage) const std::string& entryPath, ContentT& content, std::mutex& mutex, - Benchmarking::IDurationCollector& duration_collector) + Benchmarking::DurationCollector& duration_collector) { std::string entryPathSanitized = entryPath; std::replace(entryPathSanitized.begin(), @@ -44,7 +64,7 @@ void logErrorAndThrow [[noreturn]] (const std::string& errorMessage) } -InMemoryWriter::InMemoryWriter(Benchmarking::IDurationCollector& duration_collector) : pDurationCollector(duration_collector) {} +InMemoryWriter::InMemoryWriter(Benchmarking::DurationCollector& duration_collector) : pDurationCollector(duration_collector) {} InMemoryWriter::~InMemoryWriter() = default; diff --git a/src/libs/antares/writer/include/antares/writer/in_memory_writer.h b/src/libs/antares/writer/include/antares/writer/in_memory_writer.h index b48e909dd5..f373dba4cf 100644 --- a/src/libs/antares/writer/include/antares/writer/in_memory_writer.h +++ b/src/libs/antares/writer/include/antares/writer/in_memory_writer.h @@ -35,7 +35,7 @@ class InMemoryWriter : public IResultWriter { public: using MapType = std::map>; - explicit InMemoryWriter(Benchmarking::IDurationCollector& duration_collector); + explicit InMemoryWriter(Benchmarking::DurationCollector& duration_collector); virtual ~InMemoryWriter(); void addEntryFromBuffer(const std::string& entryPath, Yuni::Clob& entryContent) override; void addEntryFromBuffer(const std::string& entryPath, std::string& entryContent) override; @@ -49,7 +49,7 @@ class InMemoryWriter : public IResultWriter // minizip-ng requires a void* as a zip handle. MapType pEntries; // State, to allow/prevent new jobs being added to the queue - Benchmarking::IDurationCollector& pDurationCollector; + Benchmarking::DurationCollector& pDurationCollector; }; } // namespace Antares::Solver diff --git a/src/libs/antares/writer/include/antares/writer/writer_factory.h b/src/libs/antares/writer/include/antares/writer/writer_factory.h index 8036d40f78..601ee6c5dc 100644 --- a/src/libs/antares/writer/include/antares/writer/writer_factory.h +++ b/src/libs/antares/writer/include/antares/writer/writer_factory.h @@ -28,7 +28,7 @@ #include "result_format.h" namespace Benchmarking { - class IDurationCollector; + class DurationCollector; } namespace Antares::Solver @@ -36,6 +36,6 @@ namespace Antares::Solver IResultWriter::Ptr resultWriterFactory(Antares::Data::ResultFormat fmt, const YString& folderOutput, std::shared_ptr qs, - Benchmarking::IDurationCollector& duration_collector); + Benchmarking::DurationCollector& duration_collector); } diff --git a/src/libs/antares/writer/private/zip_writer.h b/src/libs/antares/writer/private/zip_writer.h index 3dc8f5057d..3c83671cd4 100644 --- a/src/libs/antares/writer/private/zip_writer.h +++ b/src/libs/antares/writer/private/zip_writer.h @@ -52,7 +52,7 @@ class ZipWriteJob ZipWriteJob(ZipWriter& writer, std::string entryPath, ContentT& content, - Benchmarking::IDurationCollector& duration_collector); + Benchmarking::DurationCollector& duration_collector); void writeEntry(); void operator()() { writeEntry(); @@ -70,7 +70,7 @@ class ZipWriteJob // Content of the new file ContentT pContent; // Benchmarking. How long do we wait ? How long does the zip write take ? - Benchmarking::IDurationCollector& pDurationCollector; + Benchmarking::DurationCollector& pDurationCollector; }; class ZipWriter : public IResultWriter @@ -78,7 +78,7 @@ class ZipWriter : public IResultWriter public: ZipWriter(std::shared_ptr qs, const char* archivePath, - Benchmarking::IDurationCollector& duration_collector); + Benchmarking::DurationCollector& duration_collector); virtual ~ZipWriter(); void addEntryFromBuffer(const std::string& entryPath, Yuni::Clob& entryContent) override; void addEntryFromBuffer(const std::string& entryPath, std::string& entryContent) override; @@ -101,7 +101,7 @@ class ZipWriter : public IResultWriter // Absolute path to the archive const std::string pArchivePath; // Benchmarking. Passed to jobs - Benchmarking::IDurationCollector& pDurationCollector; + Benchmarking::DurationCollector& pDurationCollector; Concurrency::FutureSet pendingTasks_; diff --git a/src/libs/antares/writer/writer_factory.cpp b/src/libs/antares/writer/writer_factory.cpp index 38097829eb..5d32778d5f 100644 --- a/src/libs/antares/writer/writer_factory.cpp +++ b/src/libs/antares/writer/writer_factory.cpp @@ -30,7 +30,7 @@ namespace Antares::Solver IResultWriter::Ptr resultWriterFactory(Antares::Data::ResultFormat fmt, const YString& folderOutput, std::shared_ptr qs, - Benchmarking::IDurationCollector& duration_collector) + Benchmarking::DurationCollector& duration_collector) { using namespace Antares::Data; switch (fmt) diff --git a/src/libs/antares/writer/zip_writer.cpp b/src/libs/antares/writer/zip_writer.cpp index 3f1170e63b..175086e73f 100644 --- a/src/libs/antares/writer/zip_writer.cpp +++ b/src/libs/antares/writer/zip_writer.cpp @@ -55,7 +55,7 @@ template ZipWriteJob::ZipWriteJob(ZipWriter& writer, std::string entryPath, ContentT& content, - Benchmarking::IDurationCollector& duration_collector) : + Benchmarking::DurationCollector& duration_collector) : pZipHandle(writer.pZipHandle), pZipMutex(writer.pZipMutex), pState(writer.pState), @@ -110,7 +110,7 @@ void ZipWriteJob::writeEntry() // Class ZipWriter ZipWriter::ZipWriter(std::shared_ptr qs, const char* archivePath, - Benchmarking::IDurationCollector& duration_collector) : + Benchmarking::DurationCollector& duration_collector) : pQueueService(qs), pState(ZipState::can_receive_data), pArchivePath(std::string(archivePath) + ".zip"), diff --git a/src/packaging/CMakeLists.txt b/src/packaging/CMakeLists.txt index 24cf064496..7f609baa0e 100644 --- a/src/packaging/CMakeLists.txt +++ b/src/packaging/CMakeLists.txt @@ -84,4 +84,4 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/AntaresConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/AntaresConfigVersion.cmake" DESTINATION lib/cmake/Antares -) \ No newline at end of file +) diff --git a/src/solver/application/application.cpp b/src/solver/application/application.cpp index 35ec63f022..fe456bf545 100644 --- a/src/solver/application/application.cpp +++ b/src/solver/application/application.cpp @@ -296,7 +296,7 @@ void Application::resetLogFilename() const } void Application::prepareWriter(const Antares::Data::Study& study, - Benchmarking::IDurationCollector& duration_collector) + Benchmarking::DurationCollector& duration_collector) { ioQueueService = std::make_shared(); ioQueueService->maximumThreadCount(1); @@ -324,14 +324,13 @@ void Application::readDataForTheStudy(Data::StudyLoadOptions& options) std::exception_ptr loadingException; try { - if (study.loadFromFolder(pSettings.studyFolder, options)) - { - logs.info() << "The study is loaded."; - logs.info() << LOG_UI_DISPLAY_MESSAGES_OFF; - } - - timer.stop(); - pDurationCollector.addDuration("study_loading", timer.get_duration()); + pDurationCollector("study_loading") << [&] { + if (study.loadFromFolder(pSettings.studyFolder, options)) + { + logs.info() << "The study is loaded."; + logs.info() << LOG_UI_DISPLAY_MESSAGES_OFF; + } + }; if (study.areas.empty()) { @@ -460,7 +459,6 @@ void Application::writeExectutionInfo() if (!pStudy) return; - // Last missing duration to get : measure of total simulation duration pTotalTimer.stop(); pDurationCollector.addDuration("total", pTotalTimer.get_duration()); diff --git a/src/solver/application/include/antares/application/application.h b/src/solver/application/include/antares/application/application.h index 923094c642..bf3b07a74d 100644 --- a/src/solver/application/include/antares/application/application.h +++ b/src/solver/application/include/antares/application/application.h @@ -110,7 +110,7 @@ class Application final : public Yuni::IEventObserver. +*/ + + +#include +#include +#include "antares/application/application.h" +#include "antares/solver/simulation/solver.h" +#include "antares/solver/simulation/economy.h" + +namespace Antares::Solver +{ +void Application::runSimulationInEconomicMode() +{ + // Type of the simulation + typedef Solver::Simulation::ISimulation SimulationType; + SimulationType simulation(*pStudy, pSettings, pDurationCollector, *resultWriter); + simulation.checkWriter(); + simulation.run(); + + if (!(pSettings.noOutput || pSettings.tsGeneratorsOnly)) + { + pDurationCollector("synthesis_export") << [&simulation] { + simulation.writeResults(/*synthesis:*/ true); + }; + + this->pOptimizationInfo = simulation.getOptimizationInfo(); + } +} +} // namespace Antares::Solver + diff --git a/src/solver/simulation/CMakeLists.txt b/src/solver/simulation/CMakeLists.txt index 1a95fe9fba..3c59c59d55 100644 --- a/src/solver/simulation/CMakeLists.txt +++ b/src/solver/simulation/CMakeLists.txt @@ -84,4 +84,4 @@ target_link_libraries(antares-solver-simulation install(DIRECTORY include/antares DESTINATION "include" -) \ No newline at end of file +) diff --git a/src/solver/simulation/adequacy_mode.cpp b/src/solver/simulation/adequacy_mode.cpp index 7903c19144..1bc0122436 100644 --- a/src/solver/simulation/adequacy_mode.cpp +++ b/src/solver/simulation/adequacy_mode.cpp @@ -27,7 +27,7 @@ namespace Antares::Solver { void runSimulationInAdequacyMode(Antares::Data::Study& study, const Settings& settings, - Benchmarking::IDurationCollector& durationCollector, + Benchmarking::DurationCollector& durationCollector, IResultWriter& resultWriter, Benchmarking::OptimizationInfo& info) { @@ -39,10 +39,9 @@ void runSimulationInAdequacyMode(Antares::Data::Study& study, if (!(settings.noOutput || settings.tsGeneratorsOnly)) { - Benchmarking::Timer timer; - simulation.writeResults(/*synthesis:*/ true); - timer.stop(); - durationCollector.addDuration("synthesis_export", timer.get_duration()); + durationCollector("synthesis_export") << [&simulation] { + simulation.writeResults(/*synthesis:*/ true); + }; info = simulation.getOptimizationInfo(); } diff --git a/src/solver/simulation/economy_mode.cpp b/src/solver/simulation/economy_mode.cpp index 08bd842015..baa5c69f5a 100644 --- a/src/solver/simulation/economy_mode.cpp +++ b/src/solver/simulation/economy_mode.cpp @@ -27,7 +27,7 @@ namespace Antares::Solver { void runSimulationInEconomicMode(Antares::Data::Study& study, const Settings& settings, - Benchmarking::IDurationCollector& durationCollector, + Benchmarking::DurationCollector& durationCollector, IResultWriter& resultWriter, Benchmarking::OptimizationInfo& info) { @@ -39,10 +39,9 @@ void runSimulationInEconomicMode(Antares::Data::Study& study, if (!(settings.noOutput || settings.tsGeneratorsOnly)) { - Benchmarking::Timer timer; - simulation.writeResults(/*synthesis:*/ true); - timer.stop(); - durationCollector.addDuration("synthesis_export", timer.get_duration()); + durationCollector("synthesis_export") << [&simulation] { + simulation.writeResults(/*synthesis:*/ true); + }; info = simulation.getOptimizationInfo(); } diff --git a/src/solver/simulation/include/antares/solver/simulation/adequacy_mode.h b/src/solver/simulation/include/antares/solver/simulation/adequacy_mode.h index 1c476a83f4..260ba2c92f 100644 --- a/src/solver/simulation/include/antares/solver/simulation/adequacy_mode.h +++ b/src/solver/simulation/include/antares/solver/simulation/adequacy_mode.h @@ -30,7 +30,7 @@ namespace Antares::Solver { void runSimulationInAdequacyMode(Antares::Data::Study& study, const Settings& settings, - Benchmarking::IDurationCollector& durationCollector, + Benchmarking::DurationCollector& durationCollector, IResultWriter& resultWriter, Benchmarking::OptimizationInfo& info); -} \ No newline at end of file +} diff --git a/src/solver/simulation/include/antares/solver/simulation/economy_mode.h b/src/solver/simulation/include/antares/solver/simulation/economy_mode.h index 76be452c27..5e1f454884 100644 --- a/src/solver/simulation/include/antares/solver/simulation/economy_mode.h +++ b/src/solver/simulation/include/antares/solver/simulation/economy_mode.h @@ -30,7 +30,7 @@ namespace Antares::Solver { void runSimulationInEconomicMode(Antares::Data::Study& study, const Settings& settings, - Benchmarking::IDurationCollector& durationCollector, + Benchmarking::DurationCollector& durationCollector, IResultWriter& resultWriter, Benchmarking::OptimizationInfo& info); -} \ No newline at end of file +} diff --git a/src/solver/simulation/include/antares/solver/simulation/solver.h b/src/solver/simulation/include/antares/solver/simulation/solver.h index d99f994c41..a507f3957f 100644 --- a/src/solver/simulation/include/antares/solver/simulation/solver.h +++ b/src/solver/simulation/include/antares/solver/simulation/solver.h @@ -54,7 +54,7 @@ class ISimulation : public Impl */ ISimulation(Data::Study& study, const ::Settings& settings, - Benchmarking::IDurationCollector& duration_collector, + Benchmarking::DurationCollector& duration_collector, IResultWriter& resultWriter); //! Destructor ~ISimulation(); @@ -156,7 +156,7 @@ class ISimulation : public Impl annualCostsStatistics pAnnualStatistics; // Collecting durations inside the simulation - Benchmarking::IDurationCollector& pDurationCollector; + Benchmarking::DurationCollector& pDurationCollector; public: //! The queue service that runs every set of parallel years diff --git a/src/solver/simulation/include/antares/solver/simulation/solver.hxx b/src/solver/simulation/include/antares/solver/simulation/solver.hxx index 8fda89a92e..56023b3b85 100644 --- a/src/solver/simulation/include/antares/solver/simulation/solver.hxx +++ b/src/solver/simulation/include/antares/solver/simulation/solver.hxx @@ -58,7 +58,7 @@ public: Data::Study& pStudy, std::vector& pState, bool pYearByYear, - Benchmarking::IDurationCollector& durationCollector, + Benchmarking::DurationCollector& durationCollector, IResultWriter& resultWriter) : simulation_(simulation), y(pY), @@ -100,7 +100,7 @@ private: std::vector& state; bool yearByYear; bool hydroHotStart; - Benchmarking::IDurationCollector& pDurationCollector; + Benchmarking::DurationCollector& pDurationCollector; IResultWriter& pResultWriter; HydroManagement hydroManagement; Antares::Data::Area::ScratchMap scratchmap; @@ -166,10 +166,10 @@ public: simulation_->prepareClustersInMustRunMode(scratchmap, y); // 4 - Hydraulic ventilation - Benchmarking::Timer timer; - hydroManagement.makeVentilation(randomReservoirLevel, state[numSpace], y, scratchmap); - timer.stop(); - pDurationCollector.addDuration("hydro_ventilation", timer.get_duration()); + pDurationCollector("hydro_ventilation") << [&] + { + hydroManagement.makeVentilation(randomReservoirLevel, state[numSpace], y, scratchmap); + }; // Updating the state state[numSpace].year = y; @@ -211,13 +211,13 @@ public: // 9 - Write results for the current year if (yearByYear) { - Benchmarking::Timer timerYear; - // Before writing, some variable may require minor modifications - simulation_->variables.beforeYearByYearExport(y, numSpace); - // writing the results for the current year into the output - simulation_->writeResults(false, y, numSpace); // false for synthesis - timerYear.stop(); - pDurationCollector.addDuration("yby_export", timerYear.get_duration()); + pDurationCollector("yby_export") << [&] + { + // Before writing, some variable may require minor modifications + simulation_->variables.beforeYearByYearExport(y, numSpace); + // writing the results for the current year into the output + simulation_->writeResults(false, y, numSpace); // false for synthesis + }; } } else @@ -237,7 +237,7 @@ public: template inline ISimulation::ISimulation(Data::Study& study, const ::Settings& settings, - Benchmarking::IDurationCollector& duration_collector, + Benchmarking::DurationCollector& duration_collector, IResultWriter& resultWriter) : ImplementationType(study, resultWriter), study(study), @@ -361,22 +361,18 @@ void ISimulation::run() logs.info() << " Starting the simulation"; uint finalYear = 1 + study.runtime->rangeLimits.year[Data::rangeEnd]; { - Benchmarking::Timer timer; - loopThroughYears(0, finalYear, state); - timer.stop(); - pDurationCollector.addDuration("mc_years", timer.get_duration()); + pDurationCollector("mc_years") << [&] { + loopThroughYears(0, finalYear, state); + }; } // Destroy the TS Generators if any // It will export the time-series into the output in the same time TSGenerator::DestroyAll(study); // Post operations - { - Benchmarking::Timer timer; + pDurationCollector("post_processing") << [&] { ImplementationType::simulationEnd(); - timer.stop(); - pDurationCollector.addDuration("post_processing", timer.get_duration()); - } + }; ImplementationType::variables.simulationEnd(); @@ -451,49 +447,45 @@ void ISimulation::regenerateTimeSeries(uint year) // Load if (pData.haveToRefreshTSLoad && (year % pData.refreshIntervalLoad == 0)) { - Benchmarking::Timer timer; - GenerateTimeSeries(study, year, pResultWriter); - timer.stop(); - pDurationCollector.addDuration("tsgen_load", timer.get_duration()); + pDurationCollector("tsgen_load") << [&] { + GenerateTimeSeries(study, year, pResultWriter); + }; } // Solar if (pData.haveToRefreshTSSolar && (year % pData.refreshIntervalSolar == 0)) { - Benchmarking::Timer timer; - GenerateTimeSeries(study, year, pResultWriter); - timer.stop(); - pDurationCollector.addDuration("tsgen_solar", timer.get_duration()); + pDurationCollector("tsgen_solar") << [&] { + GenerateTimeSeries(study, year, pResultWriter); + }; } // Wind if (pData.haveToRefreshTSWind && (year % pData.refreshIntervalWind == 0)) { - Benchmarking::Timer timer; - GenerateTimeSeries(study, year, pResultWriter); - timer.stop(); - pDurationCollector.addDuration("tsgen_wind", timer.get_duration()); + pDurationCollector("tsgen_wind") << [&] { + GenerateTimeSeries(study, year, pResultWriter); + }; } // Hydro if (pData.haveToRefreshTSHydro && (year % pData.refreshIntervalHydro == 0)) { - Benchmarking::Timer timer; - GenerateTimeSeries(study, year, pResultWriter); - timer.stop(); - pDurationCollector.addDuration("tsgen_hydro", timer.get_duration()); + pDurationCollector("tsgen_hydro") << [&] { + GenerateTimeSeries(study, year, pResultWriter); + }; } // Thermal const bool refreshTSonCurrentYear = (year % pData.refreshIntervalThermal == 0); - Benchmarking::Timer timer; - if (refreshTSonCurrentYear) + pDurationCollector("tsgen_thermal") << [&] { - auto clusters = getAllClustersToGen(study.areas, pData.haveToRefreshTSThermal); + if (refreshTSonCurrentYear) + { + auto clusters = getAllClustersToGen(study.areas, pData.haveToRefreshTSThermal); - GenerateThermalTimeSeries(study, clusters, year, pResultWriter); - } + GenerateThermalTimeSeries(study, clusters, year, pResultWriter); + } + }; - timer.stop(); - pDurationCollector.addDuration("tsgen_thermal", timer.get_duration()); } template diff --git a/src/tests/end-to-end/utils/utils.cpp b/src/tests/end-to-end/utils/utils.cpp index b9c2f00500..ba4214c0ac 100644 --- a/src/tests/end-to-end/utils/utils.cpp +++ b/src/tests/end-to-end/utils/utils.cpp @@ -184,7 +184,7 @@ void SimulationHandler::create() simulation_ = std::make_shared>(study_, settings_, - nullDurationCollector_, + durationCollector_, resultWriter_); SIM_AllocationTableaux(study_); } diff --git a/src/tests/end-to-end/utils/utils.h b/src/tests/end-to-end/utils/utils.h index a2df7b1b50..de831b9e91 100644 --- a/src/tests/end-to-end/utils/utils.h +++ b/src/tests/end-to-end/utils/utils.h @@ -150,7 +150,6 @@ class ScenarioBuilderRule // ===================== // Simulation handler // ===================== -using namespace Benchmarking; class SimulationHandler { @@ -165,7 +164,7 @@ class SimulationHandler private: std::shared_ptr> simulation_; - NullDurationCollector nullDurationCollector_; + Benchmarking::DurationCollector durationCollector_; Settings settings_; Study& study_; NullResultWriter resultWriter_; diff --git a/src/tests/src/libs/antares/CMakeLists.txt b/src/tests/src/libs/antares/CMakeLists.txt index fd4666cc29..7fb113066c 100644 --- a/src/tests/src/libs/antares/CMakeLists.txt +++ b/src/tests/src/libs/antares/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(concurrency) add_subdirectory(writer) add_subdirectory(study) +add_subdirectory(benchmarking) set(src_libs_antares "${CMAKE_SOURCE_DIR}/libs/antares") diff --git a/src/tests/src/libs/antares/benchmarking/CMakeLists.txt b/src/tests/src/libs/antares/benchmarking/CMakeLists.txt new file mode 100644 index 0000000000..930bc5228b --- /dev/null +++ b/src/tests/src/libs/antares/benchmarking/CMakeLists.txt @@ -0,0 +1,13 @@ +set(PROJ test-duration-collector) + +add_executable(${PROJ}) +target_sources(${PROJ} PRIVATE test_duration_collector.cpp) +target_link_libraries(${PROJ} + PRIVATE + Antares::benchmarking + Boost::unit_test_framework +) + +add_test(NAME ${PROJ} COMMAND ${PROJ}) + +set_property(TEST ${PROJ} PROPERTY LABELS unit) diff --git a/src/tests/src/libs/antares/benchmarking/test_duration_collector.cpp b/src/tests/src/libs/antares/benchmarking/test_duration_collector.cpp new file mode 100644 index 0000000000..5b5a22cf27 --- /dev/null +++ b/src/tests/src/libs/antares/benchmarking/test_duration_collector.cpp @@ -0,0 +1,79 @@ +/* +** Copyright 2007-2024, RTE (https://www.rte-france.com) +** See AUTHORS.txt +** SPDX-License-Identifier: MPL-2.0 +** This file is part of Antares-Simulator, +** Adequacy and Performance assessment for interconnected energy networks. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the Mozilla Public Licence 2.0 as published by +** the Mozilla Foundation, either version 2 of the License, or +** (at your option) any later version. +** +** Antares_Simulator is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** Mozilla Public Licence 2.0 for more details. +** +** You should have received a copy of the Mozilla Public Licence 2.0 +** along with Antares_Simulator. If not, see . +*/ + +#define BOOST_TEST_MODULE study +#define BOOST_TEST_DYN_LINK +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include +#include + +BOOST_AUTO_TEST_SUITE(durationCollector) + +using namespace std::literals::chrono_literals; + +constexpr double threshold = 30; +BOOST_AUTO_TEST_CASE(lambda) +{ + Benchmarking::DurationCollector d; + + d("test1") << [] { [[maybe_unused]] int a; }; + BOOST_CHECK_CLOSE((double)d.getTime("test1"), 0., threshold); + + d("test2") << [] { std::this_thread::sleep_for(200ms); }; + BOOST_CHECK_CLOSE((double)d.getTime("test2"), 200., threshold); + + d("test3") << [&d] + { + d("test4") << [] { std::this_thread::sleep_for(100ms); }; + std::this_thread::sleep_for(100ms); + }; + + BOOST_CHECK_CLOSE((double)d.getTime("test3"), 200., threshold); + BOOST_CHECK_CLOSE((double)d.getTime("test4"), 100., threshold); +} + +BOOST_AUTO_TEST_CASE(exceptionHandling) +{ + Benchmarking::DurationCollector d; + + auto IShouldThrowAnInt = [&d]() { + d("test1") << [] { throw int(2); }; + }; + + BOOST_CHECK_THROW (IShouldThrowAnInt(), int); +} + +BOOST_AUTO_TEST_CASE(addDuration) +{ + Benchmarking::DurationCollector d; + Benchmarking::Timer t; + + std::this_thread::sleep_for(100ms); + t.stop(); + d.addDuration("test1", t.get_duration()); + + BOOST_CHECK_CLOSE((double)d.getTime("test1"), 100., threshold); +} + +BOOST_AUTO_TEST_SUITE_END() //DurationCollector diff --git a/src/tests/src/libs/antares/study/test_study.cpp b/src/tests/src/libs/antares/study/test_study.cpp index f805c631a8..8afb633ae7 100644 --- a/src/tests/src/libs/antares/study/test_study.cpp +++ b/src/tests/src/libs/antares/study/test_study.cpp @@ -292,5 +292,5 @@ BOOST_AUTO_TEST_CASE(version_parsing) BOOST_CHECK(v == StudyVersion::unknown()); } - BOOST_AUTO_TEST_SUITE_END() //version + diff --git a/src/tests/src/libs/antares/writer/test_writer.cpp b/src/tests/src/libs/antares/writer/test_writer.cpp index 696f07ee86..a5da2fe5b4 100644 --- a/src/tests/src/libs/antares/writer/test_writer.cpp +++ b/src/tests/src/libs/antares/writer/test_writer.cpp @@ -39,15 +39,15 @@ extern "C" } using namespace Yuni::Job; -using Benchmarking::NullDurationCollector; -using Benchmarking::IDurationCollector; +using Benchmarking::DurationCollector; +using Benchmarking::DurationCollector; using Antares::Solver::IResultWriter; // Handles lifetime of necessary objects struct TestContext { std::shared_ptr threadPool; - std::unique_ptr durationCollector; + std::unique_ptr durationCollector; std::shared_ptr writer; }; @@ -72,7 +72,7 @@ std::string removeExtension(const std::string& name, const std::string& ext) TestContext createContext(const std::filesystem::path zipPath, int threadCount, Antares::Data::ResultFormat fmt) { auto threadPool = createThreadPool(threadCount); - std::unique_ptr durationCollector = std::make_unique(); + std::unique_ptr durationCollector = std::make_unique(); std::string archiveName = zipPath.string(); auto writer = Antares::Solver::resultWriterFactory( fmt, @@ -129,7 +129,7 @@ BOOST_AUTO_TEST_CASE(test_in_memory_concrete) std::string content1 = "test-content1"; std::string content2 = "test-content2"; - Benchmarking::NullDurationCollector durationCollector; + Benchmarking::DurationCollector durationCollector; Antares::Solver::InMemoryWriter writer(durationCollector); writer.addEntryFromBuffer("folder/test", content1); diff --git a/src/tests/src/solver/simulation/test-store-timeseries-number.cpp b/src/tests/src/solver/simulation/test-store-timeseries-number.cpp index cdd26a923f..c949a9ae17 100644 --- a/src/tests/src/solver/simulation/test-store-timeseries-number.cpp +++ b/src/tests/src/solver/simulation/test-store-timeseries-number.cpp @@ -64,9 +64,9 @@ BOOST_AUTO_TEST_CASE(BC_group_TestGroup_has_output_file) { auto working_tmp_dir = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); - Benchmarking::NullDurationCollector nullDurationCollector; + Benchmarking::DurationCollector durationCollector; auto resultWriter = resultWriterFactory(ResultFormat::legacyFilesDirectories, working_tmp_dir.string().c_str(), - nullptr, nullDurationCollector); + nullptr, durationCollector); fs::path bc_path = working_tmp_dir / "ts-numbers" / "bindingconstraints" / "TestGroup.txt"; initializeStudy(*study); @@ -87,9 +87,9 @@ BOOST_AUTO_TEST_CASE(BC_output_ts_numbers_file_for_each_group) { auto working_tmp_dir = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); - Benchmarking::NullDurationCollector nullDurationCollector; + Benchmarking::DurationCollector durationCollector; auto resultWriter = resultWriterFactory(ResultFormat::legacyFilesDirectories, working_tmp_dir.string().c_str(), - nullptr, nullDurationCollector); + nullptr, durationCollector); initializeStudy(*study); TimeSeriesNumbers::Generate(*study); @@ -113,9 +113,9 @@ BOOST_AUTO_TEST_CASE(BC_timeseries_numbers_store_values) { auto working_tmp_dir = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); - Benchmarking::NullDurationCollector nullDurationCollector; + Benchmarking::DurationCollector durationCollector; auto resultWriter = resultWriterFactory(ResultFormat::legacyFilesDirectories, working_tmp_dir.string().c_str(), - nullptr, nullDurationCollector); + nullptr, durationCollector); initializeStudy(*study); TimeSeriesNumbers::Generate(*study); diff --git a/src/tools/ts-generator/main.cpp b/src/tools/ts-generator/main.cpp index 519d9ddb3b..cb16342ce8 100644 --- a/src/tools/ts-generator/main.cpp +++ b/src/tools/ts-generator/main.cpp @@ -136,10 +136,10 @@ int main(int argc, char *argv[]) Antares::logs.error() << ex.what(); } - Benchmarking::NullDurationCollector nullDurationCollector; + Benchmarking::DurationCollector durationCollector; auto resultWriter = Solver::resultWriterFactory( - Data::ResultFormat::legacyFilesDirectories, study->folderOutput, nullptr, nullDurationCollector); + Data::ResultFormat::legacyFilesDirectories, study->folderOutput, nullptr, durationCollector); std::vector clusters; diff --git a/src/ui/simulator/application/application.cpp b/src/ui/simulator/application/application.cpp index 1554ad6828..e05505fc49 100644 --- a/src/ui/simulator/application/application.cpp +++ b/src/ui/simulator/application/application.cpp @@ -152,7 +152,7 @@ static void AbortProgram(int code) } else { - Benchmarking::NullDurationCollector duration_collector; + Benchmarking::DurationCollector duration_collector; auto resultWriter = Antares::Solver::resultWriterFactory( currentStudy->parameters.resultFormat, currentStudy->folderOutput,