Skip to content

Commit aadd336

Browse files
authored
DPL: refactor metrics helpers (#5817)
* Move helpers in separate file. * Move some template invariant code to separate out-of-line function. * Separate booking of the metric from cursor creation.
1 parent 6bfad0d commit aadd336

File tree

10 files changed

+449
-366
lines changed

10 files changed

+449
-366
lines changed

Framework/Core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ o2_add_library(Framework
5252
src/DataSpecUtils.cxx
5353
src/DeviceConfigInfo.cxx
5454
src/DeviceMetricsInfo.cxx
55+
src/DeviceMetricsHelper.cxx
5556
src/DeviceSpec.cxx
5657
src/DeviceController.cxx
5758
src/DeviceSpecHelpers.cxx
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// Copyright CERN and copyright holders of ALICE O2. This software is
2+
// distributed under the terms of the GNU General Public License v3 (GPL
3+
// Version 3), copied verbatim in the file "COPYING".
4+
//
5+
// See http://alice-o2.web.cern.ch/license for full licensing information.
6+
//
7+
// In applying this license CERN does not waive the privileges and immunities
8+
// granted to it by virtue of its status as an Intergovernmental Organization
9+
// or submit itself to any jurisdiction.
10+
//
11+
#ifndef O2_FRAMEWORK_DEVICEMETRICSHELPERS_H_
12+
#define O2_FRAMEWORK_DEVICEMETRICSHELPERS_H_
13+
14+
#include "Framework/DeviceMetricsInfo.h"
15+
#include "Framework/RuntimeError.h"
16+
#include <array>
17+
#include <cstddef>
18+
#include <cstring>
19+
#include <functional>
20+
#include <string>
21+
#include <string_view>
22+
#include <vector>
23+
24+
namespace o2::framework
25+
{
26+
27+
struct DeviceMetricsHelper {
28+
/// Type of the callback which can be provided to be invoked every time a new
29+
/// metric is found by the system.
30+
using NewMetricCallback = std::function<void(std::string const&, MetricInfo const&, int value, size_t metricIndex)>;
31+
32+
/// Helper function to parse a metric string.
33+
static bool parseMetric(std::string_view const s, ParsedMetricMatch& results);
34+
35+
/// Processes a parsed metric and stores in the backend store.
36+
///
37+
/// @matches is the regexp_matches from the metric identifying regex
38+
/// @info is the DeviceInfo associated to the device posting the metric
39+
/// @newMetricsCallback is a callback that will be invoked every time a new metric is added to the list.
40+
static bool processMetric(ParsedMetricMatch& results,
41+
DeviceMetricsInfo& info,
42+
NewMetricCallback newMetricCallback = nullptr);
43+
/// @return the index in metrics for the information of given metric
44+
static size_t metricIdxByName(const std::string& name,
45+
const DeviceMetricsInfo& info);
46+
47+
/// Typesafe way to get the actual store
48+
template <typename T>
49+
static auto& getMetricsStore(DeviceMetricsInfo& metrics)
50+
{
51+
if constexpr (std::is_same_v<T, int>) {
52+
return metrics.intMetrics;
53+
} else if constexpr (std::is_same_v<T, float>) {
54+
return metrics.floatMetrics;
55+
} else if constexpr (std::is_same_v<T, uint64_t>) {
56+
return metrics.uint64Metrics;
57+
} else {
58+
throw runtime_error("Unhandled metric type");
59+
};
60+
}
61+
62+
template <typename T>
63+
static auto getMetricType()
64+
{
65+
if constexpr (std::is_same_v<T, int>) {
66+
return MetricType::Int;
67+
} else if constexpr (std::is_same_v<T, float>) {
68+
return MetricType::Float;
69+
} else if constexpr (std::is_same_v<T, uint64_t>) {
70+
return MetricType::Uint64;
71+
} else {
72+
throw runtime_error("Unhandled metric type");
73+
};
74+
}
75+
76+
template <typename T>
77+
static auto getNumericMetricCursor(size_t metricIndex)
78+
{
79+
return [metricIndex](DeviceMetricsInfo& metrics, T value, size_t timestamp) {
80+
MetricInfo& metric = metrics.metrics[metricIndex];
81+
82+
metrics.minDomain[metricIndex] = std::min(metrics.minDomain[metricIndex], timestamp);
83+
metrics.maxDomain[metricIndex] = std::max(metrics.maxDomain[metricIndex], timestamp);
84+
metrics.max[metricIndex] = std::max(metrics.max[metricIndex], (float)value);
85+
metrics.min[metricIndex] = std::min(metrics.min[metricIndex], (float)value);
86+
metrics.changed.at(metricIndex) = true;
87+
auto& store = getMetricsStore<T>(metrics);
88+
size_t pos = metric.pos++ % store[metric.storeIdx].size();
89+
metrics.timestamps[metricIndex][pos] = timestamp;
90+
store[metric.storeIdx][pos] = value;
91+
metric.filledMetrics++;
92+
};
93+
}
94+
95+
static size_t bookMetricInfo(DeviceMetricsInfo& metrics, char const* name);
96+
97+
/// @return helper to insert a given value in the metrics
98+
template <typename T>
99+
static size_t
100+
bookNumericMetric(DeviceMetricsInfo& metrics,
101+
char const* name,
102+
NewMetricCallback newMetricsCallback = nullptr)
103+
{
104+
static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint64_t> || std::is_same_v<T, float>, "Unsupported metric type");
105+
size_t metricIndex = bookMetricInfo(metrics, name);
106+
auto& metricInfo = metrics.metrics[metricIndex];
107+
metricInfo.type = getMetricType<T>();
108+
metricInfo.storeIdx = getMetricsStore<T>(metrics).size();
109+
getMetricsStore<T>(metrics).emplace_back(std::array<T, 1024>{});
110+
if (newMetricsCallback != nullptr) {
111+
newMetricsCallback(name, metricInfo, 0, metricIndex);
112+
}
113+
return metricIndex;
114+
}
115+
116+
/// @return helper to insert a given value in the metrics
117+
template <typename T>
118+
static std::function<void(DeviceMetricsInfo&, T value, size_t timestamp)>
119+
createNumericMetric(DeviceMetricsInfo& metrics,
120+
char const* name,
121+
NewMetricCallback newMetricsCallback = nullptr)
122+
{
123+
static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint64_t> || std::is_same_v<T, float>, "Unsupported metric type");
124+
size_t metricIndex = bookNumericMetric<T>(metrics, name, newMetricsCallback);
125+
return getNumericMetricCursor<T>(metricIndex);
126+
}
127+
};
128+
129+
} // namespace o2::framework
130+
131+
#endif // O2_FRAMEWORK_DEVICEMETRICSINFO_H_

Framework/Core/include/Framework/DeviceMetricsInfo.h

Lines changed: 0 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@
1414
#include "Framework/RuntimeError.h"
1515
#include <array>
1616
#include <cstddef>
17-
#include <cstring>
18-
#include <functional>
1917
#include <string>
20-
#include <string_view>
2118
#include <vector>
2219

2320
namespace o2::framework
@@ -88,115 +85,6 @@ struct DeviceMetricsInfo {
8885
std::vector<bool> changed;
8986
};
9087

91-
struct DeviceMetricsHelper {
92-
/// Type of the callback which can be provided to be invoked every time a new
93-
/// metric is found by the system.
94-
using NewMetricCallback = std::function<void(std::string const&, MetricInfo const&, int value, size_t metricIndex)>;
95-
96-
/// Helper function to parse a metric string.
97-
static bool parseMetric(std::string_view const s, ParsedMetricMatch& results);
98-
99-
/// Processes a parsed metric and stores in the backend store.
100-
///
101-
/// @matches is the regexp_matches from the metric identifying regex
102-
/// @info is the DeviceInfo associated to the device posting the metric
103-
/// @newMetricsCallback is a callback that will be invoked every time a new metric is added to the list.
104-
static bool processMetric(ParsedMetricMatch& results,
105-
DeviceMetricsInfo& info,
106-
NewMetricCallback newMetricCallback = nullptr);
107-
/// @return the index in metrics for the information of given metric
108-
static size_t metricIdxByName(const std::string& name,
109-
const DeviceMetricsInfo& info);
110-
111-
/// Typesafe way to get the actual store
112-
template <typename T>
113-
static auto& getMetricsStore(DeviceMetricsInfo& metrics)
114-
{
115-
if constexpr (std::is_same_v<T, int>) {
116-
return metrics.intMetrics;
117-
} else if constexpr (std::is_same_v<T, float>) {
118-
return metrics.floatMetrics;
119-
} else if constexpr (std::is_same_v<T, uint64_t>) {
120-
return metrics.uint64Metrics;
121-
} else {
122-
throw runtime_error("Unhandled metric type");
123-
};
124-
}
125-
126-
template <typename T>
127-
static auto getMetricType()
128-
{
129-
if constexpr (std::is_same_v<T, int>) {
130-
return MetricType::Int;
131-
} else if constexpr (std::is_same_v<T, float>) {
132-
return MetricType::Float;
133-
} else if constexpr (std::is_same_v<T, uint64_t>) {
134-
return MetricType::Uint64;
135-
} else {
136-
throw runtime_error("Unhandled metric type");
137-
};
138-
}
139-
140-
/// @return helper to insert a given value in the metrics
141-
template <typename T>
142-
static std::function<void(DeviceMetricsInfo&, T value, size_t timestamp)>
143-
createNumericMetric(DeviceMetricsInfo& metrics,
144-
char const* name,
145-
NewMetricCallback newMetricsCallback = nullptr)
146-
{
147-
static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint64_t> || std::is_same_v<T, float>, "Unsupported metric type");
148-
// Create a new metric
149-
MetricInfo metricInfo;
150-
metricInfo.pos = 0;
151-
metricInfo.type = getMetricType<T>();
152-
metricInfo.filledMetrics = 0;
153-
metricInfo.storeIdx = getMetricsStore<T>(metrics).size();
154-
getMetricsStore<T>(metrics).emplace_back(std::array<T, 1024>{});
155-
156-
// Add the timestamp buffer for it
157-
metrics.timestamps.emplace_back(std::array<size_t, 1024>{});
158-
metrics.max.push_back(std::numeric_limits<float>::lowest());
159-
metrics.min.push_back(std::numeric_limits<float>::max());
160-
metrics.maxDomain.push_back(std::numeric_limits<size_t>::lowest());
161-
metrics.minDomain.push_back(std::numeric_limits<size_t>::max());
162-
metrics.changed.push_back(true);
163-
164-
// Add the index by name in the correct position
165-
// this will require moving the tail of the index,
166-
// but inserting should happen only once for each metric,
167-
// so who cares.
168-
// Add the the actual Metric info to the store
169-
MetricLabelIndex metricLabelIdx;
170-
strncpy(metricLabelIdx.label, name, MetricLabelIndex::MAX_METRIC_LABEL_SIZE - 1);
171-
metricLabelIdx.label[MetricLabelIndex::MAX_METRIC_LABEL_SIZE - 1] = '\0';
172-
metricLabelIdx.index = metrics.metrics.size();
173-
metricLabelIdx.size = strlen(metricLabelIdx.label);
174-
metrics.metricLabelsIdx.push_back(metricLabelIdx);
175-
176-
// Add the the actual Metric info to the store
177-
auto metricIndex = metrics.metrics.size();
178-
metrics.metrics.push_back(metricInfo);
179-
180-
if (newMetricsCallback != nullptr) {
181-
newMetricsCallback(metricLabelIdx.label, metricInfo, 0, metricIndex);
182-
}
183-
return [metricIndex](DeviceMetricsInfo& metrics, T value, size_t timestamp) {
184-
MetricInfo& metric = metrics.metrics[metricIndex];
185-
186-
metrics.minDomain[metricIndex] = std::min(metrics.minDomain[metricIndex], timestamp);
187-
metrics.maxDomain[metricIndex] = std::max(metrics.maxDomain[metricIndex], timestamp);
188-
metrics.max[metricIndex] = std::max(metrics.max[metricIndex], (float)value);
189-
metrics.min[metricIndex] = std::min(metrics.min[metricIndex], (float)value);
190-
metrics.changed.at(metricIndex) = true;
191-
auto& store = getMetricsStore<T>(metrics);
192-
size_t pos = metric.pos++ % store[metric.storeIdx].size();
193-
metrics.timestamps[metricIndex][pos] = timestamp;
194-
store[metric.storeIdx][pos] = value;
195-
metric.filledMetrics++;
196-
};
197-
}
198-
};
199-
20088
} // namespace o2::framework
20189

20290
#endif // O2_FRAMEWORK_DEVICEMETRICSINFO_H_

Framework/Core/src/ArrowSupport.cxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "Framework/EndOfStreamContext.h"
1616
#include "Framework/Tracing.h"
1717
#include "Framework/DeviceMetricsInfo.h"
18+
#include "Framework/DeviceMetricsHelper.h"
1819
#include "Framework/DeviceInfo.h"
1920

2021
#include "CommonMessageBackendsHelpers.h"

0 commit comments

Comments
 (0)