llvm.org GIT mirror llvm / 50adb3d
Support resetting STATISTIC() values using llvm::ResetStatistics() Summary: Most of the time, compiler statistics can be obtained using a process that performs a single compilation and terminates such as llc. However, this isn't always the case. JITs for example, perform multiple compilations over their lifetime and STATISTIC() will record cumulative values across all of them. Provide tools like this with the facilities needed to measure individual compilations by allowing them to reset the STATISTIC() values back to zero using llvm::ResetStatistics(). It's still the tools responsibility to ensure that they perform compilations in such a way that the results are meaningful to their intended use. Reviewers: qcolombet, rtereshin, bogner, aditya_nandakumar Reviewed By: bogner Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D44181 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@326981 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Sanders 2 years ago
3 changed file(s) with 130 addition(s) and 35 deletion(s). Raw diff Collapse all Expand all
198198 /// completes.
199199 const std::vector> GetStatistics();
200200
201 /// \brief Reset the statistics. This can be used to zero and de-register the
202 /// statistics in order to measure a compilation.
203 ///
204 /// When this function begins to call destructors prior to returning, all
205 /// statistics will be zero and unregistered. However, that might not remain the
206 /// case by the time this function finishes returning. Whether update from other
207 /// threads are lost or merely deferred until during the function return is
208 /// timing sensitive.
209 ///
210 /// Callers who intend to use this to measure statistics for a single
211 /// compilation should ensure that no compilations are in progress at the point
212 /// this function is called and that only one compilation executes until calling
213 /// GetStatistics().
214 void ResetStatistics();
215
201216 } // end namespace llvm
202217
203218 #endif // LLVM_ADT_STATISTIC_H
5757 /// This class is also used to look up statistic values from applications that
5858 /// use LLVM.
5959 class StatisticInfo {
60 std::vector<const Statistic*> Stats;
60 std::vector<Statistic*> Stats;
6161
6262 friend void llvm::PrintStatistics();
6363 friend void llvm::PrintStatistics(raw_ostream &OS);
6666 /// Sort statistics by debugtype,name,description.
6767 void sort();
6868 public:
69 using const_iterator = std::vector<const Statistic *>::const_iterator;
69 using const_iterator = std::vector<Statistic *>::const_iterator;
7070
7171 StatisticInfo();
7272 ~StatisticInfo();
7373
74 void addStatistic(const Statistic *S) {
74 void addStatistic(Statistic *S) {
7575 Stats.push_back(S);
7676 }
7777
8080 iterator_range statistics() const {
8181 return {begin(), end()};
8282 }
83
84 void reset();
8385 };
8486 } // end anonymous namespace
8587
132134
133135 return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
134136 });
137 }
138
139 void StatisticInfo::reset() {
140 sys::SmartScopedLock Writer(*StatLock);
141
142 // Tell each statistic that it isn't registered so it has to register
143 // again. We're holding the lock so it won't be able to do so until we're
144 // finished. Once we've forced it to re-register (after we return), then zero
145 // the value.
146 for (auto *Stat : Stats) {
147 // Value updates to a statistic that complete before this statement in the
148 // iteration for that statistic will be lost as intended.
149 Stat->Initialized = false;
150 Stat->Value = 0;
151 }
152
153 // Clear the registration list and release the lock once we're done. Any
154 // pending updates from other threads will safely take effect after we return.
155 // That might not be what the user wants if they're measuring a compilation
156 // but it's their responsibility to prevent concurrent compilations to make
157 // a single compilation measurable.
158 Stats.clear();
135159 }
136160
137161 void llvm::PrintStatistics(raw_ostream &OS) {
226250 ReturnStats.emplace_back(Stat->getName(), Stat->getValue());
227251 return ReturnStats;
228252 }
253
254 void llvm::ResetStatistics() {
255 StatInfo->reset();
256 }
1111 #include "gtest/gtest.h"
1212 using namespace llvm;
1313
14 using OptionalStatistic = Optional>;
15
1416 namespace {
1517 #define DEBUG_TYPE "unittest"
1618 STATISTIC(Counter, "Counts things");
1719 STATISTIC(Counter2, "Counts other things");
20
21 static void
22 extractCounters(const std::vector> &Range,
23 OptionalStatistic &S1, OptionalStatistic &S2) {
24 for (const auto &S : Range) {
25 if (S.first == "Counter")
26 S1 = S;
27 if (S.first == "Counter2")
28 S2 = S;
29 }
30 }
1831
1932 TEST(StatisticTest, Count) {
2033 EnableStatistics();
5568 #endif
5669
5770 #if LLVM_ENABLE_STATS
58 const auto Range1 = GetStatistics();
59 EXPECT_NE(Range1.begin(), Range1.end());
60 EXPECT_EQ(Range1.begin() + 1, Range1.end());
71 {
72 const auto Range1 = GetStatistics();
73 EXPECT_NE(Range1.begin(), Range1.end());
74 EXPECT_EQ(Range1.begin() + 1, Range1.end());
6175
62 Optional> S1;
63 Optional> S2;
64 for (const auto &S : Range1) {
65 if (std::string(S.first) == "Counter")
66 S1 = S;
67 if (std::string(S.first) == "Counter2")
68 S2 = S;
76 OptionalStatistic S1;
77 OptionalStatistic S2;
78 extractCounters(Range1, S1, S2);
79
80 EXPECT_EQ(S1.hasValue(), true);
81 EXPECT_EQ(S2.hasValue(), false);
6982 }
70
71 EXPECT_NE(S1.hasValue(), false);
72 EXPECT_EQ(S2.hasValue(), false);
7383
7484 // Counter2 will be registered when it's first touched.
7585 Counter2++;
7686
77 const auto Range2 = GetStatistics();
78 EXPECT_NE(Range2.begin(), Range2.end());
79 EXPECT_EQ(Range2.begin() + 2, Range2.end());
87 {
88 const auto Range = GetStatistics();
89 EXPECT_NE(Range.begin(), Range.end());
90 EXPECT_EQ(Range.begin() + 2, Range.end());
8091
81 S1 = None;
82 S2 = None;
83 for (const auto &S : Range2) {
84 if (std::string(S.first) == "Counter")
85 S1 = S;
86 if (std::string(S.first) == "Counter2")
87 S2 = S;
92 OptionalStatistic S1;
93 OptionalStatistic S2;
94 extractCounters(Range, S1, S2);
95
96 EXPECT_EQ(S1.hasValue(), true);
97 EXPECT_EQ(S2.hasValue(), true);
98
99 EXPECT_EQ(S1->first, "Counter");
100 EXPECT_EQ(S1->second, 2u);
101
102 EXPECT_EQ(S2->first, "Counter2");
103 EXPECT_EQ(S2->second, 1u);
88104 }
89
90 EXPECT_NE(S1.hasValue(), false);
91 EXPECT_NE(S2.hasValue(), false);
92
93 EXPECT_EQ(S1->first, "Counter");
94 EXPECT_EQ(S1->second, 2u);
95
96 EXPECT_EQ(S2->first, "Counter2");
97 EXPECT_EQ(S2->second, 1u);
98105 #else
99106 Counter2++;
100107 auto &Range = GetStatistics();
101108 EXPECT_EQ(Range.begin(), Range.end());
102109 #endif
110
111 #if LLVM_ENABLE_STATS
112 // Check that resetting the statistics works correctly.
113 // It should empty the list and zero the counters.
114 ResetStatistics();
115 {
116 auto &Range = GetStatistics();
117 EXPECT_EQ(Range.begin(), Range.end());
118 EXPECT_EQ(Counter, 0u);
119 EXPECT_EQ(Counter2, 0u);
120 OptionalStatistic S1;
121 OptionalStatistic S2;
122 extractCounters(Range, S1, S2);
123 EXPECT_EQ(S1.hasValue(), false);
124 EXPECT_EQ(S2.hasValue(), false);
125 }
126
127 // Now check that they successfully re-register and count.
128 Counter++;
129 Counter2++;
130
131 {
132 auto &Range = GetStatistics();
133 EXPECT_EQ(Range.begin() + 2, Range.end());
134 EXPECT_EQ(Counter, 1u);
135 EXPECT_EQ(Counter2, 1u);
136
137 OptionalStatistic S1;
138 OptionalStatistic S2;
139 extractCounters(Range, S1, S2);
140
141 EXPECT_EQ(S1.hasValue(), true);
142 EXPECT_EQ(S2.hasValue(), true);
143
144 EXPECT_EQ(S1->first, "Counter");
145 EXPECT_EQ(S1->second, 1u);
146
147 EXPECT_EQ(S2->first, "Counter2");
148 EXPECT_EQ(S2->second, 1u);
149 }
150 #else
151 // No need to test the output ResetStatistics(), there's nothing to reset so
152 // we can't tell if it failed anyway.
153 ResetStatistics();
154 #endif
103155 }
104156
105157 } // end anonymous namespace