diff --git a/wpilibc/src/main/native/cpp/Tracer.cpp b/wpilibc/src/main/native/cpp/Tracer.cpp new file mode 100644 index 0000000000..9cb7910fbc --- /dev/null +++ b/wpilibc/src/main/native/cpp/Tracer.cpp @@ -0,0 +1,46 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "frc/Tracer.h" + +#include +#include + +using namespace frc; + +Tracer::Tracer() { ResetTimer(); } + +void Tracer::ResetTimer() { m_startTime = hal::fpga_clock::now(); } + +void Tracer::ClearEpochs() { + ResetTimer(); + m_epochs.clear(); +} + +void Tracer::AddEpoch(wpi::StringRef epochName) { + auto currentTime = hal::fpga_clock::now(); + m_epochs[epochName] = currentTime - m_startTime; + m_startTime = currentTime; +} + +void Tracer::PrintEpochs() { + using std::chrono::duration_cast; + using std::chrono::microseconds; + + auto now = hal::fpga_clock::now(); + if (now - m_lastEpochsPrintTime > kMinPrintPeriod) { + m_lastEpochsPrintTime = now; + for (const auto& epoch : m_epochs) { + wpi::outs() << '\t' << epoch.getKey() << ": " + << wpi::format( + "%.6f", + duration_cast(epoch.getValue()).count() / + 1.0e6) + << "s\n"; + } + } +} diff --git a/wpilibc/src/main/native/cpp/Watchdog.cpp b/wpilibc/src/main/native/cpp/Watchdog.cpp index 7a97f046a9..1db1cf866d 100644 --- a/wpilibc/src/main/native/cpp/Watchdog.cpp +++ b/wpilibc/src/main/native/cpp/Watchdog.cpp @@ -98,7 +98,7 @@ void Watchdog::SetTimeout(units::second_t timeout) { using std::chrono::microseconds; m_startTime = hal::fpga_clock::now(); - m_epochs.clear(); + m_tracer.ClearEpochs(); // Locks mutex auto thr = m_owner->GetThread(); @@ -128,28 +128,10 @@ bool Watchdog::IsExpired() const { } void Watchdog::AddEpoch(wpi::StringRef epochName) { - auto currentTime = hal::fpga_clock::now(); - m_epochs[epochName] = currentTime - m_startTime; - m_startTime = currentTime; + m_tracer.AddEpoch(epochName); } -void Watchdog::PrintEpochs() { - using std::chrono::duration_cast; - using std::chrono::microseconds; - - auto now = hal::fpga_clock::now(); - if (now - m_lastEpochsPrintTime > kMinPrintPeriod) { - m_lastEpochsPrintTime = now; - for (const auto& epoch : m_epochs) { - wpi::outs() << '\t' << epoch.getKey() << ": " - << wpi::format( - "%.6f", - duration_cast(epoch.getValue()).count() / - 1.0e6) - << "s\n"; - } - } -} +void Watchdog::PrintEpochs() { m_tracer.PrintEpochs(); } void Watchdog::Reset() { Enable(); } @@ -158,7 +140,7 @@ void Watchdog::Enable() { using std::chrono::microseconds; m_startTime = hal::fpga_clock::now(); - m_epochs.clear(); + m_tracer.ClearEpochs(); // Locks mutex auto thr = m_owner->GetThread(); diff --git a/wpilibc/src/main/native/include/frc/Tracer.h b/wpilibc/src/main/native/include/frc/Tracer.h new file mode 100644 index 0000000000..8b495713f9 --- /dev/null +++ b/wpilibc/src/main/native/include/frc/Tracer.h @@ -0,0 +1,66 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include + +#include +#include +#include +#include + +namespace frc { +/** + * A class for keeping track of how much time it takes for different parts of + * code to execute. This is done with epochs, that are added to calls to + * AddEpoch() and can be printed with a call to PrintEpochs(). + * + * Epochs are a way to partition the time elapsed so that when overruns occur, + * one can determine which parts of an operation consumed the most time. + */ +class Tracer { + public: + /** + * Constructs a Tracer instance. + */ + Tracer(); + + /** + * Restarts the epoch timer. + */ + void ResetTimer(); + + /** + * Clears all epochs. + */ + void ClearEpochs(); + + /** + * Adds time since last epoch to the list printed by PrintEpochs(). + * + * Epochs are a way to partition the time elapsed so that when overruns occur, + * one can determine which parts of an operation consumed the most time. + * + * @param epochName The name to associate with the epoch. + */ + void AddEpoch(wpi::StringRef epochName); + + /** + * Prints list of epochs added so far and their times. + */ + void PrintEpochs(); + + private: + static constexpr std::chrono::milliseconds kMinPrintPeriod{1000}; + + hal::fpga_clock::time_point m_startTime; + hal::fpga_clock::time_point m_lastEpochsPrintTime = hal::fpga_clock::epoch(); + + wpi::StringMap m_epochs; +}; +} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/Watchdog.h b/wpilibc/src/main/native/include/frc/Watchdog.h index 8452d98c08..127fe7373c 100644 --- a/wpilibc/src/main/native/include/frc/Watchdog.h +++ b/wpilibc/src/main/native/include/frc/Watchdog.h @@ -14,10 +14,11 @@ #include #include #include -#include #include #include +#include "frc/Tracer.h" + namespace frc { /** @@ -155,9 +156,8 @@ class Watchdog { hal::fpga_clock::time_point m_expirationTime; std::function m_callback; hal::fpga_clock::time_point m_lastTimeoutPrintTime = hal::fpga_clock::epoch(); - hal::fpga_clock::time_point m_lastEpochsPrintTime = hal::fpga_clock::epoch(); - wpi::StringMap m_epochs; + Tracer m_tracer; bool m_isExpired = false; bool m_suppressTimeoutMessage = false;