diff --git a/backends/p4tools/common/CMakeLists.txt b/backends/p4tools/common/CMakeLists.txt index bbd51c1a40f..e071df2abef 100644 --- a/backends/p4tools/common/CMakeLists.txt +++ b/backends/p4tools/common/CMakeLists.txt @@ -52,7 +52,6 @@ set( lib/model.cpp lib/symbolic_env.cpp lib/taint.cpp - lib/timer.cpp lib/trace_events.cpp lib/util.cpp lib/zombie.cpp diff --git a/backends/p4tools/common/core/z3_solver.cpp b/backends/p4tools/common/core/z3_solver.cpp index 0f8b0ea1a6d..555791a08aa 100644 --- a/backends/p4tools/common/core/z3_solver.cpp +++ b/backends/p4tools/common/core/z3_solver.cpp @@ -13,7 +13,6 @@ #include "backends/p4tools/common/lib/formulae.h" #include "backends/p4tools/common/lib/model.h" -#include "backends/p4tools/common/lib/timer.h" #include "gsl/gsl-lite.hpp" #include "ir/ir.h" #include "ir/irutils.h" @@ -25,6 +24,7 @@ #include "lib/exceptions.h" #include "lib/indent.h" #include "lib/log.h" +#include "lib/timer.h" namespace P4Tools { @@ -283,8 +283,8 @@ boost::optional Z3Solver::checkSat(const std::vector& a } Z3_LOG("checking satisfiability for %d assertions", isIncremental ? z3solver.assertions().size() : z3Assertions.size()); - ScopedTimer ctZ3("z3"); - ScopedTimer ctCheckSat("checkSat"); + Util::ScopedTimer ctZ3("z3"); + Util::ScopedTimer ctCheckSat("checkSat"); z3::check_result result = isIncremental ? z3solver.check() : z3solver.check(z3Assertions); switch (result) { case z3::sat: @@ -332,8 +332,8 @@ const Model* Z3Solver::getModel() const { } // Then, get the model and match each declaration in the model to its StateVariable. try { - ScopedTimer ctZ3("z3"); - ScopedTimer ctCheckSat("getModel"); + Util::ScopedTimer ctZ3("z3"); + Util::ScopedTimer ctCheckSat("getModel"); auto z3Model = z3solver.get_model(); Z3_LOG("z3 model:%s", toString(z3Model)); diff --git a/backends/p4tools/modules/testgen/core/exploration_strategy/exploration_strategy.cpp b/backends/p4tools/modules/testgen/core/exploration_strategy/exploration_strategy.cpp index 20423185c3f..3f48174e1a2 100644 --- a/backends/p4tools/modules/testgen/core/exploration_strategy/exploration_strategy.cpp +++ b/backends/p4tools/modules/testgen/core/exploration_strategy/exploration_strategy.cpp @@ -13,13 +13,13 @@ #include "backends/p4tools/common/core/solver.h" #include "backends/p4tools/common/lib/formulae.h" #include "backends/p4tools/common/lib/symbolic_env.h" -#include "backends/p4tools/common/lib/timer.h" #include "backends/p4tools/common/lib/util.h" #include "frontends/p4/optimizeExpressions.h" #include "gsl/gsl-lite.hpp" #include "ir/ir.h" #include "ir/irutils.h" #include "lib/error.h" +#include "lib/timer.h" #include "midend/coverage.h" #include "backends/p4tools/modules/testgen/core/program_info.h" @@ -52,7 +52,7 @@ ExplorationStrategy::Branch::Branch(boost::optional c, } ExplorationStrategy::StepResult ExplorationStrategy::step(ExecutionState& state) { - ScopedTimer st("step"); + Util::ScopedTimer st("step"); StepResult successors = evaluator.step(state); // Assign branch ids to the branches. These integer branch ids are used by track-branches // and selected (input) branches features. diff --git a/backends/p4tools/modules/testgen/lib/test_backend.cpp b/backends/p4tools/modules/testgen/lib/test_backend.cpp index debf1717325..25e3baf2c6f 100644 --- a/backends/p4tools/modules/testgen/lib/test_backend.cpp +++ b/backends/p4tools/modules/testgen/lib/test_backend.cpp @@ -17,7 +17,6 @@ #include "backends/p4tools/common/lib/model.h" #include "backends/p4tools/common/lib/symbolic_env.h" #include "backends/p4tools/common/lib/taint.h" -#include "backends/p4tools/common/lib/timer.h" #include "backends/p4tools/common/lib/trace_events.h" #include "backends/p4tools/common/lib/util.h" #include "frontends/p4/optimizeExpressions.h" @@ -25,6 +24,7 @@ #include "lib/error.h" #include "lib/exceptions.h" #include "lib/null.h" +#include "lib/timer.h" #include "midend/coverage.h" #include "backends/p4tools/modules/testgen/core/exploration_strategy/exploration_strategy.h" @@ -158,8 +158,9 @@ bool TestBackEnd::run(const FinalState& state) { P4::Coverage::logCoverage(allStatements, visitedStatements, executionState->getVisited()); // Output the test. - withTimer("backend", - [&] { testWriter->outputTest(testSpec, selectedBranches, testCount, coverage); }); + Util::withTimer("backend", [&] { + testWriter->outputTest(testSpec, selectedBranches, testCount, coverage); + }); printTraces("============ End Test %1% ============\n", testCount); testCount++; @@ -267,7 +268,7 @@ bool TestBackEnd::printTestInfo(const ExecutionState* executionState, const Test void TestBackEnd::printPerformanceReport() { printFeature("performance", 4, "============ Timers ============"); - for (const auto& c : getTimers()) { + for (const auto& c : Util::getTimers()) { if (c.timerName.empty()) { printFeature("performance", 4, "Total: %i ms", c.milliseconds); } else { diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index e34193ea981..376ff346d37 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -34,6 +34,7 @@ set (LIBP4CTOOLKIT_SRCS path.cpp source_file.cpp stringify.cpp + timer.cpp ) set (LIBP4CTOOLKIT_HDRS @@ -77,6 +78,7 @@ set (LIBP4CTOOLKIT_HDRS stringify.h stringref.h symbitmatrix.h + timer.h ) build_unified(LIBP4CTOOLKIT_SRCS ALL) diff --git a/backends/p4tools/common/lib/timer.cpp b/lib/timer.cpp similarity index 78% rename from backends/p4tools/common/lib/timer.cpp rename to lib/timer.cpp index f60eb8d8ac0..0b143497a6a 100644 --- a/backends/p4tools/common/lib/timer.cpp +++ b/lib/timer.cpp @@ -1,4 +1,4 @@ -#include "backends/p4tools/common/lib/timer.h" +#include "lib/timer.h" #include #include // NOLINT linter forbids using chrono, but we don't have alternatives @@ -6,7 +6,7 @@ #include #include -namespace P4Tools { +namespace Util { namespace { @@ -19,10 +19,10 @@ using Clock = std::chrono::high_resolution_clock; struct CounterEntry { const char* name; std::unordered_map> counters; - Clock::duration duration; + Clock::duration duration{}; /// Lookup existing or create new child counter. - CounterEntry* open_subcounter(const char* name) { + CounterEntry* openSubcounter(const char* name) { auto it = counters.find(name); if (it == counters.end()) { it = counters.emplace(name, new CounterEntry(name)).first; @@ -50,9 +50,9 @@ struct RootCounter { // // however libgc cannot scan thread local data, which can lead to premature object // garbage collection. - static RootCounter root; - root.counter.duration = Clock::now() - root.start; - return root; + static RootCounter ROOT; + ROOT.counter.duration = Clock::now() - ROOT.start; + return ROOT; } CounterEntry* getCurrent() const { return current; } @@ -60,42 +60,46 @@ struct RootCounter { void setCurrent(CounterEntry* c) { current = c; } private: - RootCounter() : counter("") { - current = &counter; - start = Clock::now(); - } + RootCounter() : counter(""), current(&counter) { start = Clock::now(); } }; } // namespace +#pragma GCC diagnostic push +#if defined(__has_warning) +#if __has_warning("-Wsubobject-linkage") +#pragma GCC diagnostic ignored "-Wsubobject-linkage" +#endif +#endif // RAII helper which manages lifetime of one timer invocation. -struct ScopedTimer::Ctx { +struct ScopedTimerCtx { CounterEntry* parent = nullptr; CounterEntry* self = nullptr; - Clock::time_point start_time; + Clock::time_point startTime; - explicit Ctx(const char* counter_name) { - start_time = Clock::now(); + explicit ScopedTimerCtx(const char* timerName) + : parent(RootCounter::get().getCurrent()), self(parent->openSubcounter(timerName)) { + startTime = Clock::now(); // Push new active counter - the current active counter becomes the parent of this // counter, and this counter becomes the current active counter. - parent = RootCounter::get().getCurrent(); - self = parent->open_subcounter(counter_name); RootCounter::get().setCurrent(self); } - ~Ctx() { + ~ScopedTimerCtx() { // Close the current timer invocation, measure time and add it to the counter. - auto duration = Clock::now() - start_time; + auto duration = Clock::now() - startTime; self->add(duration); // Restore previous counter as current. RootCounter::get().setCurrent(parent); } }; +#pragma GCC diagnostic pop + +ScopedTimer::ScopedTimer(const char* name) : ctx(new ScopedTimerCtx(name)) {} -ScopedTimer::ScopedTimer(const char* name) : ctx(new ScopedTimer::Ctx(name)) {} ScopedTimer::~ScopedTimer() = default; -void withTimer(const char* counter_name, std::function fn) { - ScopedTimer timer(counter_name); +void withTimer(const char* timerName, const std::function& fn) { + ScopedTimer timer(timerName); fn(); } @@ -127,9 +131,9 @@ static void formatCounters(std::vector& out, CounterEntry& current, std::vector getTimers() { std::vector ret; - std::string namePrefix = ""; + std::string namePrefix; formatCounters(ret, RootCounter::get().counter, namePrefix, 0); return ret; } -} // namespace P4Tools +} // namespace Util diff --git a/backends/p4tools/common/lib/timer.h b/lib/timer.h similarity index 78% rename from backends/p4tools/common/lib/timer.h rename to lib/timer.h index 19e193f1537..22cfa3ad373 100644 --- a/backends/p4tools/common/lib/timer.h +++ b/lib/timer.h @@ -1,14 +1,13 @@ -#ifndef BACKENDS_P4TOOLS_COMMON_LIB_TIMER_H_ -#define BACKENDS_P4TOOLS_COMMON_LIB_TIMER_H_ - -#include +#ifndef _LIB_TIMER_H_ +#define _LIB_TIMER_H_ +#include #include #include #include #include -namespace P4Tools { +namespace Util { /// Runs specified function and measures it's execution duration under specified timer name. /// Timers can be nested. Measured durations are added under given timer name. In case of nested @@ -23,7 +22,7 @@ namespace P4Tools { /// }); /// /// uses two separate counters denoted as "A.C" and "B.C". -void withTimer(const char* timer_name, std::function fn); +void withTimer(const char* timerName, const std::function& fn); struct TimerEntry { /// Counter name. If a timer "Y" was invoked inside timer "X", its timer name is "X.Y". @@ -37,6 +36,9 @@ struct TimerEntry { /// Returns list of all timers for and their current values. std::vector getTimers(); +// Internal implementation. +struct ScopedTimerCtx; + /// Similar to withTimer function, measures execution time elapsed from instance creation to /// destruction. class ScopedTimer { @@ -46,12 +48,9 @@ class ScopedTimer { ~ScopedTimer(); private: - // Internal implementation. - struct Ctx; - - std::unique_ptr ctx; + std::unique_ptr ctx; }; -} // namespace P4Tools +} // namespace Util -#endif /* BACKENDS_P4TOOLS_COMMON_LIB_TIMER_H_ */ +#endif /* _LIB_TIMER_H_ */