/src/cppcheck/lib/timer.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | TODO: |
29 | | - rename "file" to "single" |
30 | | - add unit tests |
31 | | - for --showtime (needs input file) |
32 | | - for Timer* classes |
33 | | */ |
34 | | |
35 | | namespace { |
36 | | using dataElementType = std::pair<std::string, struct TimerResultsData>; |
37 | | bool more_second_sec(const dataElementType& lhs, const dataElementType& rhs) |
38 | 0 | { |
39 | 0 | return lhs.second.seconds() > rhs.second.seconds(); |
40 | 0 | } |
41 | | } |
42 | | |
43 | | void TimerResults::showResults(SHOWTIME_MODES mode) const |
44 | 1.36k | { |
45 | 1.36k | if (mode == SHOWTIME_MODES::SHOWTIME_NONE || mode == SHOWTIME_MODES::SHOWTIME_FILE_TOTAL) |
46 | 1.36k | return; |
47 | | |
48 | 0 | std::cout << std::endl; |
49 | 0 | TimerResultsData overallData; |
50 | |
|
51 | 0 | std::vector<dataElementType> data; |
52 | 0 | { |
53 | 0 | std::lock_guard<std::mutex> l(mResultsSync); |
54 | 0 | data.reserve(mResults.size()); |
55 | 0 | data.insert(data.begin(), mResults.cbegin(), mResults.cend()); |
56 | 0 | } |
57 | 0 | std::sort(data.begin(), data.end(), more_second_sec); |
58 | |
|
59 | 0 | size_t ordinal = 1; // maybe it would be nice to have an ordinal in output later! |
60 | 0 | for (std::vector<dataElementType>::const_iterator iter=data.cbegin(); iter!=data.cend(); ++iter) { |
61 | 0 | const double sec = iter->second.seconds(); |
62 | 0 | const double secAverage = sec / (double)(iter->second.mNumberOfResults); |
63 | 0 | bool hasParent = false; |
64 | 0 | { |
65 | | // Do not use valueFlow.. in "Overall time" because those are included in Tokenizer already |
66 | 0 | if (startsWith(iter->first,"valueFlow")) |
67 | 0 | hasParent = true; |
68 | | |
69 | | // Do not use inner timers in "Overall time" |
70 | 0 | const std::string::size_type pos = iter->first.rfind("::"); |
71 | 0 | if (pos != std::string::npos) |
72 | 0 | hasParent = std::any_of(data.cbegin(), data.cend(), [iter,pos](const dataElementType& d) { |
73 | 0 | return d.first.size() == pos && iter->first.compare(0, d.first.size(), d.first) == 0; |
74 | 0 | }); |
75 | 0 | } |
76 | 0 | if (!hasParent) |
77 | 0 | overallData.mClocks += iter->second.mClocks; |
78 | 0 | if ((mode != SHOWTIME_MODES::SHOWTIME_TOP5) || (ordinal<=5)) { |
79 | 0 | std::cout << iter->first << ": " << sec << "s (avg. " << secAverage << "s - " << iter->second.mNumberOfResults << " result(s))" << std::endl; |
80 | 0 | } |
81 | 0 | ++ordinal; |
82 | 0 | } |
83 | |
|
84 | 0 | const double secOverall = overallData.seconds(); |
85 | 0 | std::cout << "Overall time: " << secOverall << "s" << std::endl; |
86 | 0 | } |
87 | | |
88 | | void TimerResults::addResults(const std::string& str, std::clock_t clocks) |
89 | 0 | { |
90 | 0 | std::lock_guard<std::mutex> l(mResultsSync); |
91 | |
|
92 | 0 | mResults[str].mClocks += clocks; |
93 | 0 | mResults[str].mNumberOfResults++; |
94 | 0 | } |
95 | | |
96 | | Timer::Timer(std::string str, SHOWTIME_MODES showtimeMode, TimerResultsIntf* timerResults) |
97 | | : mStr(std::move(str)) |
98 | | , mTimerResults(timerResults) |
99 | | , mStart(std::clock()) |
100 | | , mShowTimeMode(showtimeMode) |
101 | | , mStopped(showtimeMode == SHOWTIME_MODES::SHOWTIME_NONE || showtimeMode == SHOWTIME_MODES::SHOWTIME_FILE_TOTAL) |
102 | 39.4k | {} |
103 | | |
104 | | Timer::Timer(bool fileTotal, std::string filename) |
105 | | : mStr(std::move(filename)) |
106 | | , mStopped(!fileTotal) |
107 | 1.36k | {} |
108 | | |
109 | | Timer::~Timer() |
110 | 40.8k | { |
111 | 40.8k | stop(); |
112 | 40.8k | } |
113 | | |
114 | | void Timer::stop() |
115 | 40.8k | { |
116 | 40.8k | if ((mShowTimeMode != SHOWTIME_MODES::SHOWTIME_NONE) && !mStopped) { |
117 | 0 | const std::clock_t end = std::clock(); |
118 | 0 | const std::clock_t diff = end - mStart; |
119 | |
|
120 | 0 | if (mShowTimeMode == SHOWTIME_MODES::SHOWTIME_FILE) { |
121 | 0 | const double sec = (double)diff / CLOCKS_PER_SEC; |
122 | 0 | std::cout << mStr << ": " << sec << "s" << std::endl; |
123 | 0 | } else if (mShowTimeMode == SHOWTIME_MODES::SHOWTIME_FILE_TOTAL) { |
124 | 0 | const double sec = (double)diff / CLOCKS_PER_SEC; |
125 | 0 | std::cout << "Check time: " << mStr << ": " << sec << "s" << std::endl; |
126 | 0 | } else { |
127 | 0 | if (mTimerResults) |
128 | 0 | mTimerResults->addResults(mStr, diff); |
129 | 0 | } |
130 | 0 | } |
131 | | |
132 | 40.8k | mStopped = true; |
133 | 40.8k | } |