Skip to content

Commit 98f4cbb

Browse files
authored
Merge pull request #7 from UniStuttgart-VISUS/collector
Collector fix
2 parents f9cf6fb + 559822b commit 98f4cbb

File tree

9 files changed

+359
-71
lines changed

9 files changed

+359
-71
lines changed

azure-pipelines.yml

Lines changed: 60 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,36 +18,63 @@ schedules:
1818
- master
1919
always: true
2020

21-
pool:
22-
vmImage: 'windows-2022'
23-
24-
variables:
25-
buildPlatform: 'x64'
26-
buildConfiguration: 'Release'
27-
generator: 'Visual Studio 17 2022'
28-
29-
steps:
30-
- task: NuGetToolInstaller@0
31-
32-
- task: CMake@1
33-
displayName: 'CMake'
34-
inputs:
35-
workingDirectory: '_build'
36-
cmakeArgs: .. -G"$(generator)" -A"$(buildPlatform)"
37-
38-
#- task: NuGetCommand@2
39-
# inputs:
40-
# restoreSolution: '$(solution)'
41-
42-
- task: VSBuild@1
43-
displayName: 'Build'
44-
inputs:
45-
solution: '_build/*.sln'
46-
platform: '$(buildPlatform)'
47-
configuration: '$(buildConfiguration)'
48-
49-
- task: VSTest@2
50-
displayName: 'Tests'
51-
inputs:
52-
platform: '$(buildPlatform)'
53-
configuration: '$(buildConfiguration)'
21+
22+
jobs:
23+
- job: Windows
24+
25+
variables:
26+
buildPlatform: 'x64'
27+
buildConfiguration: 'Release'
28+
generator: 'Visual Studio 17 2022'
29+
30+
pool:
31+
vmImage: 'windows-2022'
32+
33+
steps:
34+
- task: NuGetToolInstaller@0
35+
36+
- task: CMake@1
37+
displayName: 'Configure'
38+
inputs:
39+
workingDirectory: '_build'
40+
cmakeArgs: '.. -G"$(generator)" -A"$(buildPlatform)"'
41+
42+
#- task: NuGetCommand@2
43+
# inputs:
44+
# restoreSolution: '$(solution)'
45+
46+
- task: VSBuild@1
47+
displayName: 'Build'
48+
inputs:
49+
solution: '_build/*.sln'
50+
platform: '$(buildPlatform)'
51+
configuration: '$(buildConfiguration)'
52+
53+
- task: VSTest@2
54+
displayName: 'Tests'
55+
inputs:
56+
platform: '$(buildPlatform)'
57+
configuration: '$(buildConfiguration)'
58+
59+
60+
- job: Linux
61+
62+
variables:
63+
buildConfiguration: 'Release'
64+
generator: 'Unix Makefiles'
65+
66+
pool:
67+
vmImage: 'ubuntu-22.04'
68+
69+
steps:
70+
- task: CMake@1
71+
displayName: 'Configure'
72+
inputs:
73+
workingDirectory: '_build'
74+
cmakeArgs: '.. -G"$(generator)" -DCMAKE_BUILD_TYPE="$(buildConfiguration)"'
75+
76+
- task: CMake@1
77+
displayName: 'Build'
78+
inputs:
79+
workingDirectory: '_build'
80+
cmakeArgs: '--build .'

power_overwhelming/include/power_overwhelming/collector.h

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include <type_traits>
1414
#include <vector>
1515

16-
#include "power_overwhelming/sensor.h"
16+
#include "power_overwhelming/collector_settings.h"
1717

1818

1919
namespace visus {
@@ -30,18 +30,32 @@ namespace power_overwhelming {
3030

3131
public:
3232

33+
/// <summary>
34+
/// Creates a collector for all sensors that could be found and
35+
/// instantiated on the machine.
36+
/// </summary>
37+
/// <param name="settings">The general settings for the collector,
38+
/// including the sampling interval.</param>
39+
/// <returns>A collector for all available sensors.</returns>
40+
static collector for_all(const collector_settings& settings);
41+
3342
/// <summary>
3443
/// Creates a collector for all sensors that could be found and
3544
/// instantiated on the machne.
3645
/// </summary>
3746
/// <param name="output_path">The path where the collector should write
3847
/// the output to.</param>
3948
/// <param name="sampling_interval">The sampling interval for the sensors
40-
/// in microseconds. This parameter defaults to 5000 microseconds.
41-
/// </param>
49+
/// in microseconds.</param>
4250
/// <returns>A collector for all available sensors.</returns>
43-
static collector for_all(const wchar_t *output_path,
44-
const sensor::microseconds_type sampling_interval = 5000);
51+
/// <exception std::invalid_argument">If <paramref name="output_path" />
52+
/// is <c>nullptr</c>.</exception>
53+
inline static collector for_all(const wchar_t *output_path,
54+
const sensor::microseconds_type sampling_interval
55+
= collector_settings::default_sampling_interval) {
56+
return for_all(collector_settings().output_path(output_path)
57+
.sampling_interval(sampling_interval));
58+
}
4559

4660
/// <summary>
4761
/// Create a collector for the configuration template generated by
@@ -65,23 +79,29 @@ namespace power_overwhelming {
6579
/// <typeparam name="TSensorLists">The types of the lists of sensors,
6680
/// which must be STL collection types (with <c>begin</c> and
6781
/// <c>end</c>) or sensors.</typeparam>
82+
/// <param name="settings">The general settings for the collector,
83+
/// including the sampling interval.</param>
6884
/// <param name="sensors">The lists of sensors.</param>
6985
/// <returns></returns>
7086
template<class... TSensorLists>
71-
static collector from_sensor_lists(TSensorLists&&... sensors);
87+
static collector from_sensor_lists(const collector_settings& settings,
88+
TSensorLists&&... sensors);
7289

7390
/// <summary>
7491
/// Initialise a new instance from the given compile-time list of
7592
/// (possibly different kinds of) sensors.
7693
/// </summary>
7794
/// <typeparam name="TSensors>The types of the sensors to be used by
7895
/// the collector.</typeparam>
96+
/// <param name="settings">The general settings for the collector,
97+
/// including the sampling interval.</param>
7998
/// <param name="sensors">A compile-time list of sensors. The new
8099
/// instance will take ownership of these sensors, ie they will be
81100
/// disposed by moving them once the method returns.</param>
82101
/// <returns>A new collector using the given sensors.</returns>
83102
template<class... TSensors>
84-
static collector from_sensors(TSensors&&... sensors);
103+
static collector from_sensors(const collector_settings& settings,
104+
TSensors&&... sensors);
85105

86106
/// <summary>
87107
/// Creates a configuration file for all sensors currently attached to
@@ -183,12 +203,14 @@ namespace power_overwhelming {
183203
TSensorList&& sensors);
184204

185205
/// <summary>
186-
/// Creates a new collector that has no sensors, reserved space for the
187-
/// given number of sensors.
206+
/// Creates a new collector that has no sensors, but reserved space for
207+
/// the given number of sensors.
188208
/// </summary>
209+
/// <param name="settings"></param>
189210
/// <param name="capacity"></param>
190211
/// <returns>A new collector without sensors.</returns>
191-
static collector prepare(const std::size_t capacity);
212+
static collector prepare(const collector_settings& settings,
213+
const std::size_t capacity);
192214

193215
/// <summary>
194216
/// Initialise a new instance.

power_overwhelming/include/power_overwhelming/collector.inl

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,18 @@
1010
template<class... TSensorLists>
1111
visus::power_overwhelming::collector
1212
visus::power_overwhelming::collector::from_sensor_lists(
13-
TSensorLists&&... sensors) {
13+
const collector_settings& settings, TSensorLists&&... sensors) {
1414
std::array<std::vector<std::unique_ptr<sensor>>,
1515
sizeof...(sensors)> instances = { move_to_heap(sensors)... };
16+
typedef typename decltype(instances)::value_type sensor_type;
1617

1718
const auto cnt = std::accumulate(instances.begin(),
1819
instances.end(), static_cast<std::size_t>(0),
19-
[](const std::size_t s, const decltype(instances)::value_type& v) {
20+
[](const std::size_t s, const sensor_type& v) {
2021
return std::size(v) + s;
2122
});
2223

23-
auto retval = collector::prepare(cnt);
24+
auto retval = collector::prepare(settings, cnt);
2425

2526
for (auto& l : instances) {
2627
for (auto& i : l) {
@@ -37,13 +38,14 @@ visus::power_overwhelming::collector::from_sensor_lists(
3738
*/
3839
template<class... TSensors>
3940
visus::power_overwhelming::collector
40-
visus::power_overwhelming::collector::from_sensors(TSensors&&... sensors) {
41+
visus::power_overwhelming::collector::from_sensors(
42+
const collector_settings& settings, TSensors&&... sensors) {
4143
std::array<std::unique_ptr<sensor>, sizeof...(sensors)> instances = {
4244
std::unique_ptr<sensor>(new typename std::decay<TSensors>::type(
4345
std::move(sensors)))...
4446
};
4547

46-
auto retval = collector::prepare(instances.size());
48+
auto retval = collector::prepare(settings, instances.size());
4749

4850
for (auto& i : instances) {
4951
// Note: We release this on purpose as the library and the calling code
@@ -69,8 +71,8 @@ visus::power_overwhelming::collector::move_to_heap(TSensorList&& sensors) {
6971
retval.reserve(std::size(sensors));
7072

7173
std::transform(sensors.begin(), sensors.end(), std::back_inserter(retval),
72-
[](typename sensor_type& s) {
73-
return std::unique_ptr<sensor>(new typename sensor_type(std::move(s)));
74+
[](sensor_type& s) {
75+
return std::unique_ptr<sensor>(new sensor_type(std::move(s)));
7476
});
7577

7678
return retval;
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// <copyright file="collector_settings.h" company="Visualisierungsinstitut der Universität Stuttgart">
2+
// Copyright © 2023 Visualisierungsinstitut der Universität Stuttgart. Alle Rechte vorbehalten.
3+
// </copyright>
4+
// <author>Christoph Müller</author>
5+
6+
#pragma once
7+
8+
#include <cinttypes>
9+
10+
#include "power_overwhelming/sensor.h"
11+
12+
13+
namespace visus {
14+
namespace power_overwhelming {
15+
16+
/// <summary>
17+
/// Enapsulates the settings of a
18+
/// <see cref="visus::power_overwhelming::collector" />.
19+
/// </summary>
20+
class POWER_OVERWHELMING_API collector_settings final {
21+
22+
public:
23+
24+
/// <summary>
25+
/// The type used to specify sampling intervals in (microseconds).
26+
/// </summary>
27+
typedef sensor::microseconds_type sampling_interval_type;
28+
29+
/// <summary>
30+
/// The default output path.
31+
/// </summary>
32+
static constexpr const wchar_t *default_output_path = L"output.csv";
33+
34+
/// <summary>
35+
/// The default sampling interval of 5 milliseconds (or 5000
36+
/// microseconds).
37+
/// </summary>
38+
static constexpr sampling_interval_type default_sampling_interval
39+
= 5000;
40+
41+
/// <summary>
42+
/// Initialises a new instance.
43+
/// </summary>
44+
/// <param name=""></param>
45+
collector_settings(void);
46+
47+
/// <summary>
48+
/// Clone <paramref name="rhs" />.
49+
/// </summary>
50+
/// <param name="rhs">The object to be cloned.</param>
51+
collector_settings(const collector_settings& rhs);
52+
53+
/// <summary>
54+
/// Finalises the instance.
55+
/// </summary>
56+
~collector_settings(void);
57+
58+
/// <summary>
59+
/// Gets the path to the file where the collector should write its
60+
/// output to.
61+
/// </summary>
62+
/// <returns>The path to the output file.</returns>
63+
inline const wchar_t *output_path(void) const noexcept {
64+
return this->_output_path;
65+
}
66+
67+
/// <summary>
68+
/// Sets the path to the file where the collector should write its
69+
/// output to.
70+
/// </summary>
71+
/// <param name="path">The path to the output file.</param>
72+
/// <returns><c>*this</c>.</returns>
73+
/// <exception cref="std::invalid_argument">If
74+
/// <paramref name="output_path" /> is <c>nullptr</c>.</exception>
75+
collector_settings& output_path(const wchar_t *path);
76+
77+
/// <summary>
78+
/// Gets the time interval in which the collector should sample the
79+
/// sensors.
80+
/// </summary>
81+
/// <returns>The sampling interval.</returns>
82+
inline sampling_interval_type sampling_interval(void) const noexcept {
83+
return this->_sampling_interval;
84+
}
85+
86+
/// <summary>
87+
/// Sets the interval in which the collector should sample the sensors.
88+
/// </summary>
89+
/// <param name="interval">The sampling interval.</param>
90+
/// <returns><c>*this</c>.</returns>
91+
collector_settings& sampling_interval(
92+
const sampling_interval_type interval);
93+
94+
/// <summary>
95+
/// Assignment.
96+
/// </summary>
97+
/// <param name="rhs">The right hand side operand.</param>
98+
/// <returns><c>*this</c>.</returns>
99+
collector_settings& operator =(const collector_settings& rhs);
100+
101+
private:
102+
103+
wchar_t *_output_path;
104+
sampling_interval_type _sampling_interval;
105+
106+
};
107+
108+
} /* namespace power_overwhelming */
109+
} /* namespace visus */

power_overwhelming/src/collector.cpp

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -78,24 +78,11 @@ namespace detail {
7878
* visus::power_overwhelming::collector::for_all
7979
*/
8080
visus::power_overwhelming::collector
81-
visus::power_overwhelming::collector::for_all(const wchar_t *output_path,
82-
const sensor::microseconds_type sampling_interval) {
83-
if (output_path == nullptr) {
84-
throw std::invalid_argument("The output path of a collector cannot be "
85-
"null.");
86-
}
87-
81+
visus::power_overwhelming::collector::for_all(
82+
const collector_settings& settings) {
8883
auto retval = collector(new detail::collector_impl());
84+
retval._impl->apply(settings);
8985
retval._impl->sensors = detail::get_all_sensors();
90-
#if defined(_WIN32)
91-
retval._impl->stream = std::wofstream(output_path, std::ofstream::trunc);
92-
#else /* defined(_WIN32) */
93-
auto p = convert_string<char>(output_path);
94-
retval._impl->stream = std::wofstream(p, std::ofstream::trunc);
95-
#endif /* defined(_WIN32) */
96-
retval._impl->sampling_interval = std::chrono::microseconds(
97-
sampling_interval);
98-
9986
return retval;
10087
}
10188

@@ -217,9 +204,11 @@ visus::power_overwhelming::collector::operator bool(void) const noexcept {
217204
* visus::power_overwhelming::collector::prepare
218205
*/
219206
visus::power_overwhelming::collector
220-
visus::power_overwhelming::collector::prepare(const std::size_t capacity) {
207+
visus::power_overwhelming::collector::prepare(
208+
const collector_settings& settings, const std::size_t capacity) {
221209
auto retval = collector(new detail::collector_impl());
222210
retval._impl->sensors.reserve(capacity);
211+
retval._impl->apply(settings);
223212
return retval;
224213
}
225214

0 commit comments

Comments
 (0)