From c14b87b228b841bc6fd6f089681baadbe364ea42 Mon Sep 17 00:00:00 2001 From: Starlight220 <53231611+Starlight220@users.noreply.github.com> Date: Thu, 2 Apr 2020 06:09:40 +0300 Subject: [PATCH] [wpilibj] Refactor Tracer functionality out of Watchdog class (#2452) --- .../java/edu/wpi/first/wpilibj/Tracer.java | 95 +++++++++++++++++++ .../java/edu/wpi/first/wpilibj/Watchdog.java | 26 ++--- 2 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/Tracer.java diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Tracer.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Tracer.java new file mode 100644 index 0000000000..3518023479 --- /dev/null +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Tracer.java @@ -0,0 +1,95 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2018-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. */ +/*----------------------------------------------------------------------------*/ + +package edu.wpi.first.wpilibj; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +/** + * 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 by calls to {@link #addEpoch(String)}, + * and can be printed with a call to {@link #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. + */ +public class Tracer { + private static final long kMinPrintPeriod = 1000000; // microseconds + + private long m_lastEpochsPrintTime; // microseconds + private long m_startTime; // microseconds + + @SuppressWarnings("PMD.UseConcurrentHashMap") + private final Map m_epochs = new HashMap<>(); // microseconds + + /** + * Tracer constructor. + */ + public Tracer() { + resetTimer(); + } + + /** + * Clears all epochs. + */ + public void clearEpochs() { + m_epochs.clear(); + resetTimer(); + } + + /** + * Restarts the epoch timer. + */ + public void resetTimer() { + m_startTime = RobotController.getFPGATime(); + } + + /** + * 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. + * + *

This should be called immediately after execution has finished, + * with a call to this method or {@link #resetTimer()} before execution. + * + * @param epochName The name to associate with the epoch. + */ + public void addEpoch(String epochName) { + long currentTime = RobotController.getFPGATime(); + m_epochs.put(epochName, currentTime - m_startTime); + m_startTime = currentTime; + } + + /** + * Prints list of epochs added so far and their times to the DriverStation. + */ + public void printEpochs() { + printEpochs(out -> DriverStation.reportWarning(out, false)); + } + + /** + * Prints list of epochs added so far and their times to the entered String consumer. + * + *

This overload can be useful for logging to a file, etc. + * + * @param output the stream that the output is sent to + */ + public void printEpochs(Consumer output) { + long now = RobotController.getFPGATime(); + StringBuilder sb = new StringBuilder(); + if (now - m_lastEpochsPrintTime > kMinPrintPeriod) { + m_lastEpochsPrintTime = now; + m_epochs.forEach((key, value) -> { + sb.append(String.format("\t%s: %.6fs\n", key, value / 1.0e6)); + }); + } + output.accept(sb.toString()); + } +} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Watchdog.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Watchdog.java index dae53ee69f..fe5d0b98c9 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Watchdog.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Watchdog.java @@ -8,8 +8,6 @@ package edu.wpi.first.wpilibj; import java.io.Closeable; -import java.util.HashMap; -import java.util.Map; import java.util.PriorityQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; @@ -33,14 +31,13 @@ public class Watchdog implements Closeable, Comparable { private long m_expirationTime; // microseconds private final Runnable m_callback; private long m_lastTimeoutPrintTime; // microseconds - private long m_lastEpochsPrintTime; // microseconds - @SuppressWarnings("PMD.UseConcurrentHashMap") - private final Map m_epochs = new HashMap<>(); // microseconds boolean m_isExpired; boolean m_suppressTimeoutMessage; + private final Tracer m_tracer; + static { startDaemonThread(Watchdog::schedulerFunc); } @@ -58,6 +55,7 @@ public class Watchdog implements Closeable, Comparable { public Watchdog(double timeout, Runnable callback) { m_timeout = (long) (timeout * 1.0e6); m_callback = callback; + m_tracer = new Tracer(); } @Override @@ -87,7 +85,7 @@ public class Watchdog implements Closeable, Comparable { */ public void setTimeout(double timeout) { m_startTime = RobotController.getFPGATime(); - m_epochs.clear(); + m_tracer.clearEpochs(); m_queueMutex.lock(); try { @@ -130,26 +128,20 @@ public class Watchdog implements Closeable, Comparable { /** * 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. + * @see Tracer#addEpoch(String) * * @param epochName The name to associate with the epoch. */ public void addEpoch(String epochName) { - long currentTime = RobotController.getFPGATime(); - m_epochs.put(epochName, currentTime - m_startTime); - m_startTime = currentTime; + m_tracer.addEpoch(epochName); } /** * Prints list of epochs added so far and their times. + * @see Tracer#printEpochs() */ public void printEpochs() { - long now = RobotController.getFPGATime(); - if (now - m_lastEpochsPrintTime > kMinPrintPeriod) { - m_lastEpochsPrintTime = now; - m_epochs.forEach((key, value) -> System.out.format("\t%s: %.6fs\n", key, value / 1.0e6)); - } + m_tracer.printEpochs(); } /** @@ -166,7 +158,7 @@ public class Watchdog implements Closeable, Comparable { */ public void enable() { m_startTime = RobotController.getFPGATime(); - m_epochs.clear(); + m_tracer.clearEpochs(); m_queueMutex.lock(); try {