Cppcheck
timer.cpp
Go to the documentation of this file.
1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2023 Cppcheck team.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "timer.h"
20 
21 #include "utils.h"
22 
23 #include <algorithm>
24 #include <iostream>
25 #include <utility>
26 #include <vector>
27 
28 namespace {
29  using dataElementType = std::pair<std::string, TimerResultsData>;
30  bool more_second_sec(const dataElementType& lhs, const dataElementType& rhs)
31  {
32  return lhs.second.seconds() > rhs.second.seconds();
33  }
34 
35  // TODO: remove and print through (synchronized) ErrorLogger instead
36  std::mutex stdCoutLock;
37 }
38 
39 // TODO: this does not include any file context when SHOWTIME_FILE thus rendering it useless - should we include the logging with the progress logging?
40 // that could also get rid of the broader locking
42 {
44  return;
45 
46  TimerResultsData overallData;
47  std::vector<dataElementType> data;
48 
49  {
50  std::lock_guard<std::mutex> l(mResultsSync);
51 
52  data.reserve(mResults.size());
53  data.insert(data.begin(), mResults.cbegin(), mResults.cend());
54  }
55  std::sort(data.begin(), data.end(), more_second_sec);
56 
57  // lock the whole logging operation to avoid multiple threads printing their results at the same time
58  std::lock_guard<std::mutex> l(stdCoutLock);
59 
60  std::cout << std::endl;
61 
62  size_t ordinal = 1; // maybe it would be nice to have an ordinal in output later!
63  for (std::vector<dataElementType>::const_iterator iter=data.cbegin(); iter!=data.cend(); ++iter) {
64  const double sec = iter->second.seconds();
65  const double secAverage = sec / (double)(iter->second.mNumberOfResults);
66  bool hasParent = false;
67  {
68  // Do not use valueFlow.. in "Overall time" because those are included in Tokenizer already
69  if (startsWith(iter->first,"valueFlow"))
70  hasParent = true;
71 
72  // Do not use inner timers in "Overall time"
73  const std::string::size_type pos = iter->first.rfind("::");
74  if (pos != std::string::npos)
75  hasParent = std::any_of(data.cbegin(), data.cend(), [iter,pos](const dataElementType& d) {
76  return d.first.size() == pos && iter->first.compare(0, d.first.size(), d.first) == 0;
77  });
78  }
79  if (!hasParent)
80  overallData.mClocks += iter->second.mClocks;
81  if ((mode != SHOWTIME_MODES::SHOWTIME_TOP5_FILE && mode != SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY) || (ordinal<=5)) {
82  std::cout << iter->first << ": " << sec << "s (avg. " << secAverage << "s - " << iter->second.mNumberOfResults << " result(s))" << std::endl;
83  }
84  ++ordinal;
85  }
86 
87  const double secOverall = overallData.seconds();
88  std::cout << "Overall time: " << secOverall << "s" << std::endl;
89 }
90 
91 void TimerResults::addResults(const std::string& str, std::clock_t clocks)
92 {
93  std::lock_guard<std::mutex> l(mResultsSync);
94 
95  mResults[str].mClocks += clocks;
96  mResults[str].mNumberOfResults++;
97 }
98 
100 {
101  std::lock_guard<std::mutex> l(mResultsSync);
102  mResults.clear();
103 }
104 
105 Timer::Timer(std::string str, SHOWTIME_MODES showtimeMode, TimerResultsIntf* timerResults)
106  : mStr(std::move(str))
107  , mTimerResults(timerResults)
108  , mStart(std::clock())
109  , mShowTimeMode(showtimeMode)
110  , mStopped(showtimeMode == SHOWTIME_MODES::SHOWTIME_NONE || showtimeMode == SHOWTIME_MODES::SHOWTIME_FILE_TOTAL)
111 {}
112 
113 Timer::Timer(bool fileTotal, std::string filename)
114  : mStr(std::move(filename))
115  , mStopped(!fileTotal)
116 {}
117 
119 {
120  stop();
121 }
122 
124 {
126  const std::clock_t end = std::clock();
127  const std::clock_t diff = end - mStart;
128 
130  const double sec = (double)diff / CLOCKS_PER_SEC;
131  std::lock_guard<std::mutex> l(stdCoutLock);
132  std::cout << mStr << ": " << sec << "s" << std::endl;
134  const double sec = (double)diff / CLOCKS_PER_SEC;
135  std::lock_guard<std::mutex> l(stdCoutLock);
136  std::cout << "Check time: " << mStr << ": " << sec << "s" << std::endl;
137  } else {
138  if (mTimerResults)
139  mTimerResults->addResults(mStr, diff);
140  }
141  }
142 
143  mStopped = true;
144 }
virtual void addResults(const std::string &str, std::clock_t clocks)=0
void addResults(const std::string &str, std::clock_t clocks) override
Definition: timer.cpp:91
void showResults(SHOWTIME_MODES mode) const
Definition: timer.cpp:41
void reset()
Definition: timer.cpp:99
std::map< std::string, TimerResultsData > mResults
Definition: timer.h:66
std::mutex mResultsSync
Definition: timer.h:67
TimerResultsIntf * mTimerResults
Definition: timer.h:83
bool mStopped
Definition: timer.h:86
~Timer()
Definition: timer.cpp:118
const SHOWTIME_MODES mShowTimeMode
Definition: timer.h:85
void stop()
Definition: timer.cpp:123
const std::string mStr
Definition: timer.h:82
Timer(std::string str, SHOWTIME_MODES showtimeMode, TimerResultsIntf *timerResults=nullptr)
Definition: timer.cpp:105
std::clock_t mStart
Definition: timer.h:84
std::clock_t mClocks
Definition: timer.h:47
double seconds() const
Definition: timer.h:50
SHOWTIME_MODES
Definition: timer.h:30
bool startsWith(const std::string &str, const char start[], std::size_t startlen)
Definition: utils.h:94