-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy paththroughput_subscriber.cc
130 lines (102 loc) · 3.24 KB
/
throughput_subscriber.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <getopt.h>
#include <spdlog/spdlog.h>
#include <rclcpp/rclcpp.hpp>
#include <std_msgs/msg/byte_multi_array.hpp>
namespace {
struct Options
{
size_t window{1000000};
};
void showHelp(const std::string &name)
{
std::cout << "usage: " << name << " OPTIONS\n"
"OPTIONS:\n"
" -w | --window window for measuring bandwidth.\n"
" -h | --help show this help.\n";
}
Options parseOpts(int argc, char **argv)
{
static constexpr auto shortOpts = "w:h";
static constexpr struct option longOpts[] = {
{ "window", required_argument, nullptr, 'w' },
{ "help", no_argument, nullptr, 'h' },
{ nullptr, 0, nullptr, 0 }
};
Options opts{ };
for (int c = 0; (c = getopt_long(argc, argv, shortOpts, longOpts, nullptr)) >= 0; )
{
switch (c)
{
case 'w':
opts.window = std::clamp<size_t>(std::stod(optarg), 1, 1e9);
break;
case 'h':
showHelp(argv[0]);
std::exit(0);
case '?':
std::exit(1);
default:
break;
}
}
if (optind < argc)
{
std::cerr << argv[0] << ": trailing args..\n";
std::exit(1);
}
return opts;
}
struct Stats
{
size_t count{ };
size_t finishedRounds{ };
std::chrono::time_point<std::chrono::steady_clock> start{ };
std::chrono::time_point<std::chrono::steady_clock> firstStart{ };
bool started{ };
};
}
int main(int argc, char **argv)
{
using Clock = std::chrono::steady_clock;
using microseconds = std::chrono::microseconds;
rclcpp::init(argc, argv, rclcpp::InitOptions());
auto opts = parseOpts(argc, argv);
auto node = std::make_shared<rclcpp::Node>("throughput_subscriber");
auto stats = Stats{ };
auto payloadSub = node->create_subscription<std_msgs::msg::ByteMultiArray>(
"payload",
1,
[&stats, &opts](const std_msgs::msg::ByteMultiArray &payload)
{
// styled after z_thr_sub.c example
if (stats.count == 0) {
stats.start = Clock::now();
if (!stats.started)
{
stats.firstStart = stats.start;
stats.started = true;
}
stats.count++;
}
else if (stats.count < opts.window)
{
stats.count++;
}
else
{
stats.finishedRounds++;
auto now = Clock::now();
auto elapsedMicroseconds = std::chrono::duration_cast<microseconds>(now - stats.start).count();
auto elapsedSeconds = elapsedMicroseconds / 1e6;
auto msgsPerSecond = static_cast<double>(opts.window) / elapsedSeconds;
auto bytesPerSecond = static_cast<double>(payload.data.size() * opts.window) / elapsedSeconds;
spdlog::info("{} msg/s, {} MB/s"
, msgsPerSecond
, bytesPerSecond * 1e-6);
stats.start = Clock::now();
stats.count = 0;
}
});
rclcpp::spin(node);
return 0;
}