blob: 7e10097175fe23a67253a7732d0b1012ac46130f [file] [log] [blame]
alexander3c798932021-03-26 21:42:19 +00001/*
Isabella Gottardic64f5062022-01-21 15:27:13 +00002 * Copyright (c) 2022 Arm Limited. All rights reserved.
alexander3c798932021-03-26 21:42:19 +00003 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17#include "Profiler.hpp"
alexander31ae9f02022-02-10 16:15:54 +000018#include "log_macros.h"
alexander3c798932021-03-26 21:42:19 +000019
20#include <cstring>
alexander3c798932021-03-26 21:42:19 +000021
22namespace arm {
23namespace app {
alexander3c798932021-03-26 21:42:19 +000024 Profiler::Profiler(hal_platform* platform, const char* name = "Unknown")
Isabella Gottardi56ee6202021-05-12 08:27:15 +010025 : m_name(name)
alexander3c798932021-03-26 21:42:19 +000026 {
27 if (platform && platform->inited) {
Isabella Gottardi56ee6202021-05-12 08:27:15 +010028 this->m_pPlatform = platform;
alexander3c798932021-03-26 21:42:19 +000029 this->Reset();
30 } else {
31 printf_err("Profiler %s initialised with invalid platform\n",
Isabella Gottardi56ee6202021-05-12 08:27:15 +010032 this->m_name.c_str());
alexander3c798932021-03-26 21:42:19 +000033 }
34 }
35
36 bool Profiler::StartProfiling(const char* name)
37 {
38 if (name) {
39 this->SetName(name);
40 }
Isabella Gottardi56ee6202021-05-12 08:27:15 +010041 if (this->m_pPlatform && !this->m_started) {
42 this->m_pPlatform->timer->reset();
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010043 this->m_tstampSt = this->m_pPlatform->timer->get_counters();
Isabella Gottardi56ee6202021-05-12 08:27:15 +010044 this->m_started = true;
alexander3c798932021-03-26 21:42:19 +000045 return true;
46 }
Isabella Gottardi56ee6202021-05-12 08:27:15 +010047 printf_err("Failed to start profiler %s\n", this->m_name.c_str());
alexander3c798932021-03-26 21:42:19 +000048 return false;
49 }
50
51 bool Profiler::StopProfiling()
52 {
Isabella Gottardi56ee6202021-05-12 08:27:15 +010053 if (this->m_pPlatform && this->m_started) {
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010054 this->m_tstampEnd = this->m_pPlatform->timer->get_counters();
Isabella Gottardi56ee6202021-05-12 08:27:15 +010055 this->m_started = false;
alexander3c798932021-03-26 21:42:19 +000056
Isabella Gottardi56ee6202021-05-12 08:27:15 +010057 this->AddProfilingUnit(this->m_tstampSt, this->m_tstampEnd, this->m_name);
alexander3c798932021-03-26 21:42:19 +000058
59 return true;
60 }
Isabella Gottardi56ee6202021-05-12 08:27:15 +010061 printf_err("Failed to stop profiler %s\n", this->m_name.c_str());
alexander3c798932021-03-26 21:42:19 +000062 return false;
63 }
64
65 bool Profiler::StopProfilingAndReset()
66 {
67 if (this->StopProfiling()) {
68 this->Reset();
69 return true;
70 }
Isabella Gottardi56ee6202021-05-12 08:27:15 +010071 printf_err("Failed to stop profiler %s\n", this->m_name.c_str());
alexander3c798932021-03-26 21:42:19 +000072 return false;
73 }
74
75 void Profiler::Reset()
76 {
Isabella Gottardi56ee6202021-05-12 08:27:15 +010077 this->m_started = false;
78 this->m_series.clear();
79 memset(&this->m_tstampSt, 0, sizeof(this->m_tstampSt));
80 memset(&this->m_tstampEnd, 0, sizeof(this->m_tstampEnd));
alexander3c798932021-03-26 21:42:19 +000081 }
82
Isabella Gottardi8df12f32021-04-07 17:15:31 +010083 void calcProfilingStat(uint64_t currentValue,
84 Statistics& data,
85 uint32_t samples)
alexander3c798932021-03-26 21:42:19 +000086 {
Isabella Gottardi8df12f32021-04-07 17:15:31 +010087 data.total += currentValue;
88 data.min = std::min(data.min, currentValue);
89 data.max = std::max(data.max, currentValue);
90 data.avrg = ((double)data.total / samples);
91 }
alexander3c798932021-03-26 21:42:19 +000092
Isabella Gottardi8df12f32021-04-07 17:15:31 +010093 void Profiler::GetAllResultsAndReset(std::vector<ProfileResult>& results)
94 {
Isabella Gottardi56ee6202021-05-12 08:27:15 +010095 for (const auto& item: this->m_series) {
alexander3c798932021-03-26 21:42:19 +000096 auto name = item.first;
97 ProfilingSeries series = item.second;
Isabella Gottardi8df12f32021-04-07 17:15:31 +010098 ProfileResult result{};
99 result.name = item.first;
100 result.samplesNum = series.size();
alexander3c798932021-03-26 21:42:19 +0000101
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100102 std::vector<Statistics> stats(series[0].counters.num_counters);
103 for (size_t i = 0; i < stats.size(); ++i) {
104 stats[i].name = series[0].counters.counters[i].name;
105 stats[i].unit = series[0].counters.counters[i].unit;
alexander3c798932021-03-26 21:42:19 +0000106 }
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100107
108 for(ProfilingUnit& unit: series) {
109 for (size_t i = 0; i < stats.size(); ++i) {
110 calcProfilingStat(
111 unit.counters.counters[i].value,
112 stats[i],
113 result.samplesNum);
114 }
115 }
116
117 for (Statistics& stat : stats) {
118 result.data.emplace_back(stat);
119 }
120
121 results.emplace_back(result);
alexander3c798932021-03-26 21:42:19 +0000122 }
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100123
alexander3c798932021-03-26 21:42:19 +0000124 this->Reset();
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100125 }
126
127 void printStatisticsHeader(uint32_t samplesNum) {
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100128 info("Number of samples: %" PRIu32 "\n", samplesNum);
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100129 info("%s\n", "Total / Avg./ Min / Max");
130 }
131
132 void Profiler::PrintProfilingResult(bool printFullStat) {
133 std::vector<ProfileResult> results{};
134 GetAllResultsAndReset(results);
135 for(ProfileResult& result: results) {
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100136 if (result.data.size()) {
137 info("Profile for %s:\n", result.name.c_str());
138 if (printFullStat) {
139 printStatisticsHeader(result.samplesNum);
140 }
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100141 }
142
143 for (Statistics &stat: result.data) {
144 if (printFullStat) {
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100145 info("%s %s: %" PRIu64 "/ %.0f / %" PRIu64 " / %" PRIu64 " \n",
146 stat.name.c_str(), stat.unit.c_str(),
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100147 stat.total, stat.avrg, stat.min, stat.max);
148 } else {
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100149 info("%s: %.0f %s\n", stat.name.c_str(), stat.avrg, stat.unit.c_str());
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100150 }
151 }
152 }
alexander3c798932021-03-26 21:42:19 +0000153 }
154
155 void Profiler::SetName(const char* str)
156 {
Isabella Gottardi56ee6202021-05-12 08:27:15 +0100157 this->m_name = std::string(str);
alexander3c798932021-03-26 21:42:19 +0000158 }
159
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100160 void Profiler::AddProfilingUnit(pmu_counters start, pmu_counters end,
alexanderc350cdc2021-04-29 20:36:09 +0100161 const std::string& name)
alexander3c798932021-03-26 21:42:19 +0000162 {
Kshitij Sisodia14ab8d42021-10-22 17:35:01 +0100163 if (!this->m_pPlatform) {
164 printf_err("Invalid platform\n");
165 return;
166 }
167
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100168 struct ProfilingUnit unit = {
169 .counters = end
170 };
alexander3c798932021-03-26 21:42:19 +0000171
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100172 if (end.num_counters != start.num_counters ||
173 true != end.initialised || true != start.initialised) {
174 printf_err("Invalid start or end counters\n");
175 return;
176 }
alexander3c798932021-03-26 21:42:19 +0000177
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100178 for (size_t i = 0; i < unit.counters.num_counters; ++i) {
179 if (unit.counters.counters[i].value < start.counters[i].value) {
180 warn("Overflow detected for %s\n", unit.counters.counters[i].name);
181 unit.counters.counters[i].value = 0;
182 } else {
183 unit.counters.counters[i].value -= start.counters[i].value;
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100184 }
alexander3c798932021-03-26 21:42:19 +0000185 }
186
Isabella Gottardi56ee6202021-05-12 08:27:15 +0100187 this->m_series[name].emplace_back(unit);
alexander3c798932021-03-26 21:42:19 +0000188 }
189
190} /* namespace app */
Kshitij Sisodia14ab8d42021-10-22 17:35:01 +0100191} /* namespace arm */