Skip to content

Commit 781e787

Browse files
authored
FEAT: run flags (#334)
closes #321
1 parent c916d4f commit 781e787

9 files changed

Lines changed: 210 additions & 102 deletions

README.md

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,34 @@ cmake --build build
1515

1616
```
1717
./build/nons
18-
--config path
19-
[--output-dir output-dir-name]
18+
--config path
19+
[--output-dir output-dir-name]
2020
[--no-logs]
21-
[--no-plots]
22-
[--export-metrics]
21+
[--no-plots]
22+
[--export-metrics]
2323
```
2424

2525
Options:
2626

2727
```
28-
-c, --config arg Path to the simulation configuration file
29-
--output-dir arg Output directory for metrics and plots (default: metrics)
30-
--no-logs Disables logging
31-
--no-plots Disables plots generation
32-
--export-metrics Export metric values into output-dir
33-
-h, --help Print usage
28+
-c, --config arg Path to the simulation configuration file
29+
--output-dir arg Output directory for metrics and plots
30+
(default: metrics)
31+
--no-logs Output without logs
32+
--no-plots Disables plots generation
33+
--metrics-filter arg Fiter for collecting metrics pathes
34+
(default: .*)
35+
-h, --help Print usage
3436
```
3537

3638
Examples of simulation configs placed in `configuration_examples/simulation_examples`
3739

40+
### `export-metrics` flag format
41+
42+
This flags represents regular expression that match generated **data file names** under metrics output directory. Plots generates accordingly to collected data.
43+
44+
E.g. if `--metrics-filter = "cwnd/.*"`, NoNS measures only CWND values, if `--metrics-filter = ".*_link1.*"`, only metircs about link1.
45+
3846
## Resuls of simulations
3947

4048
Metrics of all simulation runs deploys to [gihub pages](https://cloud-storage-team.github.io/algnet/main). If you want to see results on all branches, visit [root site](https://cloud-storage-team.github.io/algnet).

source/main.cpp

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,38 +15,34 @@ int main(const int argc, char **argv) {
1515
cxxopts::value<bool>()->default_value("false"))(
1616
"no-plots", "Disables plots generation",
1717
cxxopts::value<bool>()->default_value("false"))(
18-
"export-metrics", "Export metric values into output-dir",
19-
cxxopts::value<bool>()->default_value("false"))("h,help",
20-
"Print usage");
21-
22-
try {
23-
auto flags = options.parse(argc, argv);
24-
auto output_dir = flags["output-dir"].as<std::string>();
25-
26-
if (flags.contains("help")) {
27-
std::cout << options.help() << std::endl;
28-
return 0;
29-
}
30-
31-
if (flags["no-logs"].as<bool>()) {
32-
Logger::get_instance().disable_logs();
33-
}
34-
35-
sim::YamlParser parser;
36-
auto [simulator, simulation_time] = parser.build_simulator_from_config(
37-
flags["config"].as<std::string>());
38-
std::visit([&](auto &sim) { sim.start(simulation_time); }, simulator);
39-
40-
if (!flags["no-plots"].as<bool>()) {
41-
sim::MetricsCollector::get_instance().draw_metric_plots(output_dir);
42-
}
43-
if (flags["export-metrics"].as<bool>()) {
44-
sim::MetricsCollector::get_instance().export_metrics_to_files(
45-
output_dir);
46-
}
47-
} catch (const std::exception &e) {
48-
std::cerr << fmt::format("Error: {}", e.what()) << std::endl;
49-
return 1;
18+
"metrics-filter", "Fiter for collecting metrics pathes",
19+
cxxopts::value<std::string>()->default_value(".*"))("h,help",
20+
"Print usage");
21+
22+
auto flags = options.parse(argc, argv);
23+
auto output_dir = flags["output-dir"].as<std::string>();
24+
25+
if (flags.contains("help")) {
26+
std::cout << options.help() << std::endl;
27+
return 0;
5028
}
29+
30+
if (flags["no-logs"].as<bool>()) {
31+
Logger::get_instance().disable_logs();
32+
}
33+
34+
sim::MetricsCollector::get_instance().set_metrics_filter(
35+
flags["metrics-filter"].as<std::string>());
36+
37+
sim::YamlParser parser;
38+
auto [simulator, simulation_time] =
39+
parser.build_simulator_from_config(flags["config"].as<std::string>());
40+
std::visit([&](auto &sim) { sim.start(simulation_time); }, simulator);
41+
42+
if (!flags["no-plots"].as<bool>()) {
43+
sim::MetricsCollector::get_instance().draw_metric_plots(output_dir);
44+
}
45+
sim::MetricsCollector::get_instance().export_metrics_to_files(output_dir);
46+
5147
return 0;
5248
}

source/metrics/metrics_collector.cpp

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
#include "metrics/metrics_collector.hpp"
1+
#include "metrics_collector.hpp"
22

3-
#include <matplot/matplot.h>
43
#include <spdlog/fmt/fmt.h>
54

6-
#include <filesystem>
7-
85
#include "flow/i_flow.hpp"
96
#include "link/i_link.hpp"
107
#include "utils/identifier_factory.hpp"
8+
#include "utils/safe_matplot.hpp"
119

1210
namespace sim {
1311

@@ -17,42 +15,28 @@ MetricsCollector& MetricsCollector::get_instance() {
1715
}
1816

1917
void MetricsCollector::add_cwnd(Id flow_id, Time time, double cwnd) {
20-
m_cwnd_storage[flow_id].add_record(time, cwnd);
18+
m_cwnd_storage.add_record(std::move(flow_id), time, cwnd);
2119
}
2220

2321
void MetricsCollector::add_delivery_rate(Id flow_id, Time time, double value) {
24-
m_rate_storage[flow_id].add_record(time, value);
22+
m_rate_storage.add_record(std::move(flow_id), time, value);
2523
}
2624

2725
void MetricsCollector::add_RTT(Id flow_id, Time time, Time value) {
28-
m_RTT_storage[flow_id].add_record(time, value);
29-
}
30-
31-
void MetricsCollector::export_metrics_to_files(
32-
std::filesystem::path metrics_dir) const {
33-
for (auto& [flow_id, values] : m_RTT_storage) {
34-
values.export_to_file(metrics_dir / fmt::format("rtt_{}.txt", flow_id));
35-
}
36-
37-
for (auto& [link_id, values] : m_queue_size_storage) {
38-
values.export_to_file(metrics_dir /
39-
fmt::format("queue_size_{}.txt", link_id));
40-
}
41-
42-
for (auto& [flow_id, values] : m_cwnd_storage) {
43-
values.export_to_file(metrics_dir /
44-
fmt::format("cwnd_{}.txt", flow_id));
45-
}
46-
47-
for (auto& [flow_id, values] : m_rate_storage) {
48-
values.export_to_file(metrics_dir /
49-
fmt::format("rate_{}.txt", flow_id));
50-
}
26+
m_RTT_storage.add_record(std::move(flow_id), time, value);
5127
}
5228

5329
void MetricsCollector::add_queue_size(Id link_id, Time time,
5430
std::uint32_t value) {
55-
m_queue_size_storage[link_id].add_record(time, value);
31+
m_queue_size_storage.add_record(std::move(link_id), time, value);
32+
}
33+
34+
void MetricsCollector::export_metrics_to_files(
35+
std::filesystem::path metrics_dir) const {
36+
m_RTT_storage.export_to_files(metrics_dir);
37+
m_queue_size_storage.export_to_files(metrics_dir);
38+
m_cwnd_storage.export_to_files(metrics_dir);
39+
m_rate_storage.export_to_files(metrics_dir);
5640
}
5741

5842
// verctor of pairs<Storage, curve name>
@@ -76,14 +60,14 @@ static void draw_on_same_plot(std::filesystem::path path, PlotMetricsData data,
7660
ax->title(metadata.title);
7761
ax->legend(std::vector<std::string>());
7862

79-
matplot::save(fig, path.string());
63+
matplot::safe_save(fig, path.string());
8064
}
8165

8266
void MetricsCollector::draw_cwnd_plot(std::filesystem::path path) const {
8367
PlotMetricsData data;
8468
std::transform(
85-
begin(m_cwnd_storage), end(m_cwnd_storage), std::back_inserter(data),
86-
[](auto const& pair) {
69+
begin(m_cwnd_storage.data()), end(m_cwnd_storage.data()),
70+
std::back_inserter(data), [](auto const& pair) {
8771
auto flow =
8872
IdentifierFactory::get_instance().get_object<IFlow>(pair.first);
8973
std::string name =
@@ -98,8 +82,8 @@ void MetricsCollector::draw_cwnd_plot(std::filesystem::path path) const {
9882
void MetricsCollector::draw_RTT_plot(std::filesystem::path path) const {
9983
PlotMetricsData data;
10084
std::transform(
101-
begin(m_RTT_storage), end(m_RTT_storage), std::back_inserter(data),
102-
[](auto const& pair) {
85+
begin(m_RTT_storage.data()), end(m_RTT_storage.data()),
86+
std::back_inserter(data), [](auto const& pair) {
10387
auto flow =
10488
IdentifierFactory::get_instance().get_object<IFlow>(pair.first);
10589
std::string name =
@@ -115,8 +99,8 @@ void MetricsCollector::draw_delivery_rate_plot(
11599
std::filesystem::path path) const {
116100
PlotMetricsData data;
117101
std::transform(
118-
begin(m_rate_storage), end(m_rate_storage), std::back_inserter(data),
119-
[](auto const& pair) {
102+
begin(m_rate_storage.data()), end(m_rate_storage.data()),
103+
std::back_inserter(data), [](auto const& pair) {
120104
auto flow =
121105
IdentifierFactory::get_instance().get_object<IFlow>(pair.first);
122106
std::string name =
@@ -130,7 +114,7 @@ void MetricsCollector::draw_delivery_rate_plot(
130114

131115
void MetricsCollector::draw_queue_size_plots(
132116
std::filesystem::path dir_path) const {
133-
for (auto& [link_id, values] : m_queue_size_storage) {
117+
for (auto& [link_id, values] : m_queue_size_storage.data()) {
134118
auto link =
135119
IdentifierFactory::get_instance().get_object<ILink>(link_id);
136120
auto fig = values.get_picture(
@@ -149,7 +133,10 @@ void MetricsCollector::draw_queue_size_plots(
149133

150134
ax->color("white");
151135

152-
matplot::save(fig, dir_path / fmt::format("{}.svg", link_id));
136+
std::filesystem::path plot_path =
137+
dir_path / fmt::format("{}.svg", link_id);
138+
139+
matplot::safe_save(fig, plot_path.string());
153140
}
154141
}
155142

@@ -161,4 +148,11 @@ void MetricsCollector::draw_metric_plots(
161148
draw_queue_size_plots(metrics_dir / "queue_size");
162149
}
163150

151+
void MetricsCollector::set_metrics_filter(const std::string& filter) {
152+
m_RTT_storage.set_filter(filter);
153+
m_cwnd_storage.set_filter(filter);
154+
m_rate_storage.set_filter(filter);
155+
m_queue_size_storage.set_filter(filter);
156+
}
157+
164158
} // namespace sim

source/metrics/metrics_collector.hpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#pragma once
22

3+
#include <regex>
34
#include <unordered_map>
45

5-
#include "metrics/metrics_storage.hpp"
6+
#include "multi_id_metrics_storage.hpp"
67

78
namespace sim {
89

@@ -18,6 +19,8 @@ class MetricsCollector {
1819
void export_metrics_to_files(std::filesystem::path metrics_dir) const;
1920
void draw_metric_plots(std::filesystem::path metrics_dir) const;
2021

22+
void set_metrics_filter(const std::string& filter);
23+
2124
private:
2225
MetricsCollector() {}
2326
MetricsCollector(const MetricsCollector&) = delete;
@@ -29,12 +32,13 @@ class MetricsCollector {
2932
void draw_queue_size_plots(std::filesystem::path dir_path) const;
3033

3134
// flow_ID --> vector of <time, ...> values
32-
std::unordered_map<Id, MetricsStorage> m_RTT_storage;
33-
std::unordered_map<Id, MetricsStorage> m_cwnd_storage;
34-
std::unordered_map<Id, MetricsStorage> m_rate_storage;
35+
MultiIdMetricsStorage m_RTT_storage = MultiIdMetricsStorage("rtt");
36+
MultiIdMetricsStorage m_cwnd_storage = MultiIdMetricsStorage("cwnd");
37+
MultiIdMetricsStorage m_rate_storage = MultiIdMetricsStorage("rate");
3538

3639
// link_ID --> vector of <time, queue size> values
37-
std::unordered_map<Id, MetricsStorage> m_queue_size_storage;
40+
MultiIdMetricsStorage m_queue_size_storage =
41+
MultiIdMetricsStorage("queue_size");
3842
};
3943

4044
} // namespace sim

source/metrics/metrics_storage.cpp

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,15 @@
22

33
#include <spdlog/fmt/fmt.h>
44

5+
#include "utils/safe_matplot.hpp"
6+
57
namespace sim {
68

79
void MetricsStorage::add_record(Time time, double value) {
810
m_records.emplace_back(time, value);
911
}
10-
11-
void static create_all_directories(std::filesystem::path path) {
12-
std::filesystem::path dir_path = path.parent_path();
13-
if (std::filesystem::exists(dir_path)) {
14-
return;
15-
}
16-
if (!std::filesystem::create_directories(dir_path) ||
17-
!std::filesystem::exists(dir_path)) {
18-
throw std::runtime_error(
19-
fmt::format("Can not create {} directory", dir_path.string()));
20-
}
21-
}
22-
2312
void MetricsStorage::export_to_file(std::filesystem::path path) const {
24-
create_all_directories(path);
13+
utils::create_all_directories(path);
2514
std::ofstream output_file(path);
2615
if (!output_file) {
2716
throw std::runtime_error("Failed to create file for metric values");
@@ -48,8 +37,7 @@ matplot::figure_handle MetricsStorage::get_picture(
4837
void MetricsStorage::draw_plot(std::filesystem::path path,
4938
PlotMetadata metadata) const {
5039
auto fig = get_picture(metadata);
51-
create_all_directories(path);
52-
matplot::save(fig, path.string());
40+
matplot::safe_save(fig, path.string());
5341
}
5442

5543
void MetricsStorage::draw_on_plot(matplot::figure_handle& fig,
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include <ranges>
2+
3+
#include "multi_id_metrics_storage.hpp"
4+
5+
namespace sim {
6+
MultiIdMetricsStorage::MultiIdMetricsStorage(std::string a_metric_name)
7+
: metric_name(std::move(a_metric_name)) {}
8+
9+
void MultiIdMetricsStorage::add_record(Id id, Time time, double value) {
10+
auto it = m_storage.find(id);
11+
if (it == m_storage.end()) {
12+
if (!std::regex_match(get_metrics_filename(id), m_filter)) {
13+
m_storage[id] = std::nullopt;
14+
} else {
15+
MetricsStorage new_storage;
16+
new_storage.add_record(time, value);
17+
m_storage.emplace(std::move(id), std::move(new_storage));
18+
}
19+
} else if (it->second.has_value()) {
20+
it->second->add_record(time, value);
21+
}
22+
}
23+
24+
void MultiIdMetricsStorage::export_to_files(
25+
std::filesystem::path output_dir_path) const {
26+
for (auto& [id, values] : m_storage) {
27+
if (values) {
28+
values->export_to_file(output_dir_path / get_metrics_filename(id));
29+
}
30+
}
31+
}
32+
33+
std::unordered_map<Id, MetricsStorage> MultiIdMetricsStorage::data() const {
34+
std::unordered_map<Id, MetricsStorage> result;
35+
for (auto [id, maybe_storage] : m_storage) {
36+
if (maybe_storage) {
37+
result[id] = maybe_storage.value();
38+
}
39+
}
40+
return result;
41+
}
42+
43+
void MultiIdMetricsStorage::set_filter(std::string filter) {
44+
m_filter = std::regex(filter);
45+
}
46+
47+
std::string MultiIdMetricsStorage::get_metrics_filename(Id id) const {
48+
return fmt::format("{}/{}.txt", metric_name, id);
49+
}
50+
51+
} // namespace sim

0 commit comments

Comments
 (0)