Author: Fangrui Song Date: 2025-01-10T17:59:28-08:00 New Revision: af4d76d909b0df79494ca19b7c289c2a5b18c816
URL: https://github.com/llvm/llvm-project/commit/af4d76d909b0df79494ca19b7c289c2a5b18c816 DIFF: https://github.com/llvm/llvm-project/commit/af4d76d909b0df79494ca19b7c289c2a5b18c816.diff LOG: [Support] Reduce globaal variable overhead after #121663 * Construct frequently-accessed TimerLock/DefaultTimerGroup early to reduce overhead. * Rename `aquireDefaultGroup` to `acquireTimerGlobals` and restore ManagedStatic::claim. https://reviews.llvm.org/D76099 * Drop mtg::. We use internal linkage, so mtg:: is unneeded and might mislead users. In addition, llvm/ code almost never introduces a named namespace not in llvm::. Drop mtg::. * Replace some unique_ptr with optional to reduce overhead. * Switch to `functionName()`. * Simplify `llvm::initTimerOptions` and `TimerGroup::constructForStatistics()` Pull Request: https://github.com/llvm/llvm-project/pull/122429 Added: Modified: clang/tools/driver/driver.cpp llvm/include/llvm/Support/Timer.h llvm/lib/Support/Timer.cpp Removed: ################################################################################ diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index ffd157e60997cd..74923247b7ee16 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -439,7 +439,7 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) { if (!UseNewCC1Process && IsCrash) { // When crashing in -fintegrated-cc1 mode, bury the timer pointers, because // the internal linked list might point to already released stack frames. - llvm::BuryPointer(llvm::TimerGroup::aquireDefaultGroup()); + llvm::BuryPointer(llvm::TimerGroup::acquireTimerGlobals()); } else { // If any timers were active but haven't been destroyed yet, print their // results now. This happens in -disable-free mode. diff --git a/llvm/include/llvm/Support/Timer.h b/llvm/include/llvm/Support/Timer.h index c05389332b8045..d21859905d4a7b 100644 --- a/llvm/include/llvm/Support/Timer.h +++ b/llvm/include/llvm/Support/Timer.h @@ -240,9 +240,9 @@ class TimerGroup { /// global constructors and destructors. static void constructForStatistics(); - /// This makes the default group unmanaged, and lets the user manage the - /// group's lifetime. - static std::unique_ptr<TimerGroup> aquireDefaultGroup(); + /// This makes the timer globals unmanaged, and lets the user manage the + /// lifetime. + static void *acquireTimerGlobals(); private: friend class Timer; diff --git a/llvm/lib/Support/Timer.cpp b/llvm/lib/Support/Timer.cpp index 3f0926ae0f3cbe..1fa2cdf297aae6 100644 --- a/llvm/lib/Support/Timer.cpp +++ b/llvm/lib/Support/Timer.cpp @@ -27,6 +27,7 @@ #include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" #include <limits> +#include <optional> #if HAVE_UNISTD_H #include <unistd.h> @@ -39,7 +40,7 @@ using namespace llvm; //===----------------------------------------------------------------------===// -// Forward declarations for Managed Timer Globals (mtg) getters. +// Forward declarations for Managed Timer Globals getters. // // Globals have been placed at the end of the file to restrict direct // access. Use of getters also has the benefit of making it a bit more explicit @@ -49,29 +50,20 @@ namespace { class Name2PairMap; } -namespace mtg { -static std::string &LibSupportInfoOutputFilename(); -static const std::string &InfoOutputFilename(); -static bool TrackSpace(); -static bool SortTimers(); -static SignpostEmitter &Signposts(); -static sys::SmartMutex<true> &TimerLock(); -static TimerGroup &DefaultTimerGroup(); -static TimerGroup *claimDefaultTimerGroup(); -static Name2PairMap &NamedGroupedTimers(); -} // namespace mtg +static std::string &libSupportInfoOutputFilename(); +static bool trackSpace(); +static bool sortTimers(); +static SignpostEmitter &signposts(); +static sys::SmartMutex<true> &timerLock(); +static TimerGroup &defaultTimerGroup(); +static Name2PairMap &namedGroupedTimers(); //===----------------------------------------------------------------------===// // //===----------------------------------------------------------------------===// -void llvm::initTimerOptions() { - mtg::TrackSpace(); - mtg::InfoOutputFilename(); - mtg::SortTimers(); -} std::unique_ptr<raw_ostream> llvm::CreateInfoOutputFile() { - const std::string &OutputFilename = mtg::LibSupportInfoOutputFilename(); + const std::string &OutputFilename = libSupportInfoOutputFilename(); if (OutputFilename.empty()) return std::make_unique<raw_fd_ostream>(2, false); // stderr. if (OutputFilename == "-") @@ -97,7 +89,7 @@ std::unique_ptr<raw_ostream> llvm::CreateInfoOutputFile() { //===----------------------------------------------------------------------===// void Timer::init(StringRef TimerName, StringRef TimerDescription) { - init(TimerName, TimerDescription, mtg::DefaultTimerGroup()); + init(TimerName, TimerDescription, defaultTimerGroup()); } void Timer::init(StringRef TimerName, StringRef TimerDescription, @@ -116,7 +108,7 @@ Timer::~Timer() { } static inline size_t getMemUsage() { - if (!mtg::TrackSpace()) + if (!trackSpace()) return 0; return sys::Process::GetMallocUsage(); } @@ -157,7 +149,7 @@ TimeRecord TimeRecord::getCurrentTime(bool Start) { void Timer::startTimer() { assert(!Running && "Cannot start a running timer"); Running = Triggered = true; - mtg::Signposts().startInterval(this, getName()); + signposts().startInterval(this, getName()); StartTime = TimeRecord::getCurrentTime(true); } @@ -166,7 +158,7 @@ void Timer::stopTimer() { Running = false; Time += TimeRecord::getCurrentTime(false); Time -= StartTime; - mtg::Signposts().endInterval(this, getName()); + signposts().endInterval(this, getName()); } void Timer::clear() { @@ -218,7 +210,7 @@ class Name2PairMap { Timer &get(StringRef Name, StringRef Description, StringRef GroupName, StringRef GroupDescription) { - sys::SmartScopedLock<true> L(mtg::TimerLock()); + sys::SmartScopedLock<true> L(timerLock()); std::pair<TimerGroup*, Name2TimerMap> &GroupEntry = Map[GroupName]; @@ -237,17 +229,17 @@ class Name2PairMap { NamedRegionTimer::NamedRegionTimer(StringRef Name, StringRef Description, StringRef GroupName, StringRef GroupDescription, bool Enabled) - : TimeRegion(!Enabled ? nullptr - : &mtg::NamedGroupedTimers().get(Name, Description, - GroupName, - GroupDescription)) {} + : TimeRegion(!Enabled + ? nullptr + : &namedGroupedTimers().get(Name, Description, GroupName, + GroupDescription)) {} //===----------------------------------------------------------------------===// // TimerGroup Implementation //===----------------------------------------------------------------------===// /// This is the global list of TimerGroups, maintained by the TimerGroup -/// ctor/dtor and is protected by the TimerLock lock. +/// ctor/dtor and is protected by the timerLock lock. static TimerGroup *TimerGroupList = nullptr; TimerGroup::TimerGroup(StringRef Name, StringRef Description, @@ -264,7 +256,7 @@ TimerGroup::TimerGroup(StringRef Name, StringRef Description, } TimerGroup::TimerGroup(StringRef Name, StringRef Description) - : TimerGroup(Name, Description, mtg::TimerLock()) {} + : TimerGroup(Name, Description, timerLock()) {} TimerGroup::TimerGroup(StringRef Name, StringRef Description, const StringMap<TimeRecord> &Records) @@ -283,7 +275,7 @@ TimerGroup::~TimerGroup() { removeTimer(*FirstTimer); // Remove the group from the TimerGroupList. - sys::SmartScopedLock<true> L(mtg::TimerLock()); + sys::SmartScopedLock<true> L(timerLock()); *Prev = Next; if (Next) Next->Prev = Prev; @@ -291,7 +283,7 @@ TimerGroup::~TimerGroup() { void TimerGroup::removeTimer(Timer &T) { - sys::SmartScopedLock<true> L(mtg::TimerLock()); + sys::SmartScopedLock<true> L(timerLock()); // If the timer was started, move its data to TimersToPrint. if (T.hasTriggered()) @@ -314,7 +306,7 @@ void TimerGroup::removeTimer(Timer &T) { } void TimerGroup::addTimer(Timer &T) { - sys::SmartScopedLock<true> L(mtg::TimerLock()); + sys::SmartScopedLock<true> L(timerLock()); // Add the timer to our list. if (FirstTimer) @@ -326,7 +318,7 @@ void TimerGroup::addTimer(Timer &T) { void TimerGroup::PrintQueuedTimers(raw_ostream &OS) { // Perhaps sort the timers in descending order by amount of time taken. - if (mtg::SortTimers()) + if (sortTimers()) llvm::sort(TimersToPrint); TimeRecord Total; @@ -344,7 +336,7 @@ void TimerGroup::PrintQueuedTimers(raw_ostream &OS) { // If this is not an collection of ungrouped times, print the total time. // Ungrouped timers don't really make sense to add up. We still print the // TOTAL line to make the percentages make sense. - if (this != &mtg::DefaultTimerGroup()) + if (this != &defaultTimerGroup()) OS << format(" Total Execution Time: %5.4f seconds (%5.4f wall clock)\n", Total.getProcessTime(), Total.getWallTime()); OS << '\n'; @@ -396,7 +388,7 @@ void TimerGroup::prepareToPrintList(bool ResetTime) { void TimerGroup::print(raw_ostream &OS, bool ResetAfterPrint) { { // After preparing the timers we can free the lock - sys::SmartScopedLock<true> L(mtg::TimerLock()); + sys::SmartScopedLock<true> L(timerLock()); prepareToPrintList(ResetAfterPrint); } @@ -406,20 +398,20 @@ void TimerGroup::print(raw_ostream &OS, bool ResetAfterPrint) { } void TimerGroup::clear() { - sys::SmartScopedLock<true> L(mtg::TimerLock()); + sys::SmartScopedLock<true> L(timerLock()); for (Timer *T = FirstTimer; T; T = T->Next) T->clear(); } void TimerGroup::printAll(raw_ostream &OS) { - sys::SmartScopedLock<true> L(mtg::TimerLock()); + sys::SmartScopedLock<true> L(timerLock()); for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next) TG->print(OS); } void TimerGroup::clearAll() { - sys::SmartScopedLock<true> L(mtg::TimerLock()); + sys::SmartScopedLock<true> L(timerLock()); for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next) TG->clear(); } @@ -436,7 +428,7 @@ void TimerGroup::printJSONValue(raw_ostream &OS, const PrintRecord &R, } const char *TimerGroup::printJSONValues(raw_ostream &OS, const char *delim) { - sys::SmartScopedLock<true> L(mtg::TimerLock()); + sys::SmartScopedLock<true> L(timerLock()); prepareToPrintList(false); for (const PrintRecord &R : TimersToPrint) { @@ -463,21 +455,12 @@ const char *TimerGroup::printJSONValues(raw_ostream &OS, const char *delim) { } const char *TimerGroup::printAllJSONValues(raw_ostream &OS, const char *delim) { - sys::SmartScopedLock<true> L(mtg::TimerLock()); + sys::SmartScopedLock<true> L(timerLock()); for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next) delim = TG->printJSONValues(OS, delim); return delim; } -void TimerGroup::constructForStatistics() { - mtg::LibSupportInfoOutputFilename(); - mtg::NamedGroupedTimers(); -} - -std::unique_ptr<TimerGroup> TimerGroup::aquireDefaultGroup() { - return std::unique_ptr<TimerGroup>(mtg::claimDefaultTimerGroup()); -} - //===----------------------------------------------------------------------===// // Timer Globals // @@ -499,83 +482,59 @@ std::unique_ptr<TimerGroup> TimerGroup::aquireDefaultGroup() { class llvm::TimerGlobals { public: std::string LibSupportInfoOutputFilename; - cl::opt<std::string, true> InfoOutputFilename; - cl::opt<bool> TrackSpace; - cl::opt<bool> SortTimers; + cl::opt<std::string, true> InfoOutputFilename{ + "info-output-file", cl::value_desc("filename"), + cl::desc("File to append -stats and -timer output to"), cl::Hidden, + cl::location(LibSupportInfoOutputFilename)}; + cl::opt<bool> TrackSpace{ + "track-memory", + cl::desc("Enable -time-passes memory tracking (this may be slow)"), + cl::Hidden}; + cl::opt<bool> SortTimers{ + "sort-timers", + cl::desc("In the report, sort the timers in each group in wall clock" + " time order"), + cl::init(true), cl::Hidden}; + + sys::SmartMutex<true> TimerLock; + TimerGroup DefaultTimerGroup{"misc", "Miscellaneous Ungrouped Timers", + TimerLock}; + SignpostEmitter Signposts; -private: // Order of these members and initialization below is important. For example - // the DefaultTimerGroup uses the TimerLock. Most of these also depend on the + // the defaultTimerGroup uses the timerLock. Most of these also depend on the // options above. std::once_flag InitDeferredFlag; - std::unique_ptr<SignpostEmitter> SignpostsPtr; - std::unique_ptr<sys::SmartMutex<true>> TimerLockPtr; - std::unique_ptr<TimerGroup> DefaultTimerGroupPtr; - std::unique_ptr<Name2PairMap> NamedGroupedTimersPtr; + std::optional<Name2PairMap> NamedGroupedTimersPtr; + TimerGlobals &initDeferred() { - std::call_once(InitDeferredFlag, [this]() { - SignpostsPtr = std::make_unique<SignpostEmitter>(); - TimerLockPtr = std::make_unique<sys::SmartMutex<true>>(); - DefaultTimerGroupPtr.reset(new TimerGroup( - "misc", "Miscellaneous Ungrouped Timers", *TimerLockPtr)); - NamedGroupedTimersPtr = std::make_unique<Name2PairMap>(); - }); + std::call_once(InitDeferredFlag, + [this]() { NamedGroupedTimersPtr.emplace(); }); return *this; } - -public: - SignpostEmitter &Signposts() { return *initDeferred().SignpostsPtr; } - sys::SmartMutex<true> &TimerLock() { return *initDeferred().TimerLockPtr; } - TimerGroup &DefaultTimerGroup() { - return *initDeferred().DefaultTimerGroupPtr; - } - TimerGroup *claimDefaultTimerGroup() { - return initDeferred().DefaultTimerGroupPtr.release(); - } - Name2PairMap &NamedGroupedTimers() { - return *initDeferred().NamedGroupedTimersPtr; - } - -public: - TimerGlobals() - : InfoOutputFilename( - "info-output-file", cl::value_desc("filename"), - cl::desc("File to append -stats and -timer output to"), cl::Hidden, - cl::location(LibSupportInfoOutputFilename)), - TrackSpace( - "track-memory", - cl::desc("Enable -time-passes memory tracking (this may be slow)"), - cl::Hidden), - SortTimers( - "sort-timers", - cl::desc( - "In the report, sort the timers in each group in wall clock" - " time order"), - cl::init(true), cl::Hidden) {} }; static ManagedStatic<TimerGlobals> ManagedTimerGlobals; -static std::string &mtg::LibSupportInfoOutputFilename() { +static std::string &libSupportInfoOutputFilename() { return ManagedTimerGlobals->LibSupportInfoOutputFilename; } -static const std::string &mtg::InfoOutputFilename() { - return ManagedTimerGlobals->InfoOutputFilename.getValue(); -} -static bool mtg::TrackSpace() { return ManagedTimerGlobals->TrackSpace; } -static bool mtg::SortTimers() { return ManagedTimerGlobals->SortTimers; } -static SignpostEmitter &mtg::Signposts() { - return ManagedTimerGlobals->Signposts(); +static bool trackSpace() { return ManagedTimerGlobals->TrackSpace; } +static bool sortTimers() { return ManagedTimerGlobals->SortTimers; } +static SignpostEmitter &signposts() { return ManagedTimerGlobals->Signposts; } +static sys::SmartMutex<true> &timerLock() { + return ManagedTimerGlobals->TimerLock; } -static sys::SmartMutex<true> &mtg::TimerLock() { - return ManagedTimerGlobals->TimerLock(); +static TimerGroup &defaultTimerGroup() { + return ManagedTimerGlobals->DefaultTimerGroup; } -static TimerGroup &mtg::DefaultTimerGroup() { - return ManagedTimerGlobals->DefaultTimerGroup(); +static Name2PairMap &namedGroupedTimers() { + return *ManagedTimerGlobals->initDeferred().NamedGroupedTimersPtr; } -static TimerGroup *mtg::claimDefaultTimerGroup() { - return ManagedTimerGlobals->claimDefaultTimerGroup(); -} -static Name2PairMap &mtg::NamedGroupedTimers() { - return ManagedTimerGlobals->NamedGroupedTimers(); + +void llvm::initTimerOptions() { *ManagedTimerGlobals; } +void TimerGroup::constructForStatistics() { + ManagedTimerGlobals->initDeferred(); } + +void *TimerGroup::acquireTimerGlobals() { return ManagedTimerGlobals.claim(); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits