-
Notifications
You must be signed in to change notification settings - Fork 611
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[wpilib] Tracer Overhaul #7099
base: main
Are you sure you want to change the base?
[wpilib] Tracer Overhaul #7099
Conversation
I don't think Tracer should be a static global, as it is used in multiple places that shouldn't have mixed outputs. |
If performance is a concern we can make it so after a certain number of nests it is sent to only datalog instead. |
Ok, that's pretty cool. A couple things:
|
Performance wise it's quite good, we ran a version close to this all of the 2024 season based on some cursory testing it seems to use less than a ms per loop. The current implementation is more refined with 1/3 as many string allocs so it should be retested. I don't like doing 1 topic per duration but there isn't really a way around it. In terms of displaying to user im unsure of better ways to convey information. The watchdog will still print when overruns happen but not the epoch times. With glass, ascope and maybe elastic being packaged with wpilib I think teams should be expected to be able to use a dashboard to take full advantage of wpilib. |
In terms of deprecation of the old tracer api, we could just name this something else while still removing tracer from watchdog. Profiler isn't a terrible name but also not great. Whats the etiquette on just leaving the old api with deprecation warnings and just having all the functions no-op or smthn until we can remove it. |
That's worse than removing it without deprecation. |
Generally the route for changing to a new API is that you make the new API with a different name and deprecate the old one (without doing any other changes to the old version)- The point of deprecation is that you can still use it without breakage. When it comes time to remove the old API (usually a year after deprecation), you completely remove it. |
So I guess this is a broader question but what is the worry of changing the public API for something when adding it in a new major version? Especially something that is currently not used very much by users. |
Ostensibly, it lets teams migrate their code gradually over the course of a year rather than breaking it all at once. In my experience though, teams either fix the deprecation warnings immediately because they think they're errors, or they don't migrate until we force them to by removing the old API. At least deprecation warnings provide guidance on how to upgrade though; immediate removal or API change gives no guidance whatsoever and can be frustrating, especially if we broke working code from the previous year. I'm not sure what we'd name the new class instead though, because Tracer is the most obvious name. |
This class's functionality is now static, it wouldn't be hard to make an instance of it to keep the functionality of the old tracer. It would just be confusing but using proper docs and deprecation warnings could help with that. |
Ok I added more overloads to I need help porting the changes I made to Another thought I had was that each periodic |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need help porting the changes I made to TimedRobot.Callback over to C++
You can use std::optional
instead of java.util.Optional
, with the exception that you can't use map()
or ifPresentOrElse()
(which aren't supported on the compiler versions we use)- Instead, you'll have to write the logic manually. (name.map(SubstitutiveTracer::new)
-> name ? frc::Tracer::SubstitutiveTracer{name} : std::nullopt
or m_tracer.ifPresentOrElse(sub -> sub.subWith(m_func), m_func)
-> if (m_tracer) { sub.subWith(m_func); } else { m_func(); }
)
wpilibj/src/main/java/edu/wpi/first/wpilibj/TimesliceRobot.java
Outdated
Show resolved
Hide resolved
Co-authored-by: Joseph Eng <[email protected]>
Co-authored-by: Joseph Eng <[email protected]>
* Decorates this Command with a name. Is an inline function for | ||
* Command::SetName(std::string_view); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated?
|
||
if constexpr (IsSimulation()) { | ||
HAL_SimPeriodicBefore(); | ||
SimulationPeriodic(); | ||
Tracer::TraceFunc("SimulationPeriodic", | ||
std::bind(&IterativeRobotBase::SimulationPeriodic, this)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is techinically a behavior change. Previously, everything in the if statement would be timed, but now it's only SimulationPeriodic. Not necessarily bad, just noting.
// Warn on loop time overruns | ||
if (m_watchdog.IsExpired()) { | ||
m_watchdog.PrintEpochs(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there functionality to alert the user when an overrun happens?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The watchdog already does that with the callback
} | ||
|
||
std::string Tracer::TracerState::PopTraceStack() { | ||
m_stackSize > 0 ? m_stackSize-- : m_stackSize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could use an if statement here.
EXPECT_TRUE(test1Entry.GetDouble(0.0) - 500.0 < 1.0); | ||
EXPECT_TRUE(test2Entry.GetDouble(0.0) - 400.0 < 1.0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the default value is zero, the value will be negative and will satisfy the condition. If you need some tolerance, use EXPECT_NEAR
, or just EXPECT_EQ
if you want to be exact.
auto test2Entry = nt::NetworkTableInstance::GetDefault().GetEntry( | ||
"/Tracer/" + newThreadName + "/ThreadTest1"); | ||
|
||
EXPECT_TRUE(test2Entry.GetDouble(0.0) - 400.0 < 1.0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto
auto test1Entry = nt::NetworkTableInstance::GetDefault().GetEntry( | ||
"/Tracer/SingleThreadTest1"); | ||
|
||
EXPECT_TRUE(test1Entry.GetDouble(0.0) - 100.0 < 1.0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
@@ -421,18 +432,11 @@ protected void loopFunc() { | |||
NetworkTableInstance.getDefault().flushLocal(); | |||
} | |||
|
|||
// Warn on loop time overruns | |||
if (m_watchdog.isExpired()) { | |||
m_watchdog.printEpochs(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there functionality to alert the user of overruns?
wpilibj/src/main/java/edu/wpi/first/wpilibj/TimesliceRobot.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any documentation for the time units Tracer publishes in?
Where would the best place to document those be? maybe it should even be placed in NT? |
Documentation in NT and the class doc would be good. |
Example usage kinda
resolves #6583