From 3a7ab8845f4bcd67207e73fef57c8b17225c4685 Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Tue, 22 Dec 2015 17:36:17 +0000 Subject: [PATCH] [Support] Allow multiple paired calls to {start,stop}Timer() Differential Revision: http://reviews.llvm.org/D15619 Reviewed-by: rafael git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256258 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/Timer.h | 29 ++++++++++++------- lib/Support/Timer.cpp | 32 +++++++++------------ unittests/Support/CMakeLists.txt | 1 + unittests/Support/TimerTest.cpp | 49 ++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 28 deletions(-) create mode 100644 unittests/Support/TimerTest.cpp diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h index 2d9b0e24841..499fe7b7e70 100644 --- a/include/llvm/Support/Timer.h +++ b/include/llvm/Support/Timer.h @@ -62,8 +62,8 @@ public: MemUsed -= RHS.MemUsed; } - /// print - Print the current timer to standard error, and reset the "Started" - /// flag. + /// Print the current time record to \p OS, with a breakdown showing + /// contributions to the \p Total time record. void print(const TimeRecord &Total, raw_ostream &OS) const; }; @@ -76,9 +76,11 @@ public: /// if they are never started. /// class Timer { - TimeRecord Time; + TimeRecord Time; // The total time captured + TimeRecord StartTime; // The time startTimer() was last called std::string Name; // The name of this time variable. - bool Started; // Has this time variable ever been started? + bool Running; // Is the timer currently running? + bool Triggered; // Has the timer ever been triggered? TimerGroup *TG; // The TimerGroup this Timer is in. Timer **Prev, *Next; // Doubly linked list of timers in the group. @@ -102,16 +104,23 @@ public: const std::string &getName() const { return Name; } bool isInitialized() const { return TG != nullptr; } - /// startTimer - Start the timer running. Time between calls to - /// startTimer/stopTimer is counted by the Timer class. Note that these calls - /// must be correctly paired. - /// + /// Check if startTimer() has ever been called on this timer. + bool hasTriggered() const { return Triggered; } + + /// Start the timer running. Time between calls to startTimer/stopTimer is + /// counted by the Timer class. Note that these calls must be correctly + /// paired. void startTimer(); - /// stopTimer - Stop the timer. - /// + /// Stop the timer. void stopTimer(); + /// Clear the timer state. + void clear(); + + /// Return the duration for which this timer has been running. + TimeRecord getTotalTime() const { return Time; } + private: friend class TimerGroup; }; diff --git a/lib/Support/Timer.cpp b/lib/Support/Timer.cpp index f8ab214bfbf..414f559f8f0 100644 --- a/lib/Support/Timer.cpp +++ b/lib/Support/Timer.cpp @@ -102,7 +102,7 @@ void Timer::init(StringRef N) { void Timer::init(StringRef N, TimerGroup &tg) { assert(!TG && "Timer already initialized"); Name.assign(N.begin(), N.end()); - Started = false; + Running = Triggered = false; TG = &tg; TG->addTimer(*this); } @@ -135,25 +135,22 @@ TimeRecord TimeRecord::getCurrentTime(bool Start) { return Result; } -static ManagedStatic > ActiveTimers; - void Timer::startTimer() { - Started = true; - ActiveTimers->push_back(this); - Time -= TimeRecord::getCurrentTime(true); + assert(!Running && "Cannot start a running timer"); + Running = Triggered = true; + StartTime = TimeRecord::getCurrentTime(true); } void Timer::stopTimer() { + assert(Running && "Cannot stop a paused timer"); + Running = false; Time += TimeRecord::getCurrentTime(false); + Time -= StartTime; +} - if (ActiveTimers->back() == this) { - ActiveTimers->pop_back(); - } else { - std::vector::iterator I = - std::find(ActiveTimers->begin(), ActiveTimers->end(), this); - assert(I != ActiveTimers->end() && "stop but no startTimer?"); - ActiveTimers->erase(I); - } +void Timer::clear() { + Running = Triggered = false; + Time = StartTime = TimeRecord(); } static void printVal(double Val, double Total, raw_ostream &OS) { @@ -271,7 +268,7 @@ void TimerGroup::removeTimer(Timer &T) { sys::SmartScopedLock L(*TimerLock); // If the timer was started, move its data to TimersToPrint. - if (T.Started) + if (T.hasTriggered()) TimersToPrint.emplace_back(T.Time, T.Name); T.TG = nullptr; @@ -357,12 +354,11 @@ void TimerGroup::print(raw_ostream &OS) { // See if any of our timers were started, if so add them to TimersToPrint and // reset them. for (Timer *T = FirstTimer; T; T = T->Next) { - if (!T->Started) continue; + if (!T->hasTriggered()) continue; TimersToPrint.emplace_back(T->Time, T->Name); // Clear out the time. - T->Started = 0; - T->Time = TimeRecord(); + T->clear(); } // If any timers were started, print the group. diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index 9bd685759ed..3ab98d58d5f 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -42,6 +42,7 @@ add_llvm_unittest(SupportTests TargetRegistry.cpp ThreadLocalTest.cpp ThreadPool.cpp + TimerTest.cpp TimeValueTest.cpp TrailingObjectsTest.cpp UnicodeTest.cpp diff --git a/unittests/Support/TimerTest.cpp b/unittests/Support/TimerTest.cpp new file mode 100644 index 00000000000..ac7c52db6d1 --- /dev/null +++ b/unittests/Support/TimerTest.cpp @@ -0,0 +1,49 @@ +//===- unittests/TimerTest.cpp - Timer tests ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Timer.h" +#include "gtest/gtest.h" +#include +#include + +using namespace llvm; + +namespace { + +TEST(Timer, Additivity) { + Timer T1("T1"); + + EXPECT_TRUE(T1.isInitialized()); + + T1.startTimer(); + T1.stopTimer(); + auto TR1 = T1.getTotalTime(); + + T1.startTimer(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + T1.stopTimer(); + auto TR2 = T1.getTotalTime(); + + EXPECT_TRUE(TR1 < TR2); +} + +TEST(Timer, CheckIfTriggered) { + Timer T1("T1"); + + EXPECT_FALSE(T1.hasTriggered()); + T1.startTimer(); + EXPECT_TRUE(T1.hasTriggered()); + T1.stopTimer(); + EXPECT_TRUE(T1.hasTriggered()); + + T1.clear(); + EXPECT_FALSE(T1.hasTriggered()); +} + +} // end anon namespace -- 2.34.1