1 /* Copyright (c) 2017-2022. The SimGrid Team. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
6 #include <simgrid/plugins/load.h>
7 #include <simgrid/s4u/Engine.hpp>
9 #include "src/kernel/activity/CommImpl.hpp"
10 #include "src/kernel/resource/StandardLinkImpl.hpp"
14 SIMGRID_REGISTER_PLUGIN(link_load, "Link cumulated load.", &sg_link_load_plugin_init)
16 /** @defgroup plugin_link_load Plugin Link Cumulated Load
18 This is the link cumulated load plugin.
19 It enables to monitor how links are used over time by cumulating the amount of bytes that go through the link.
22 - Call sg_link_load_plugin_init() between the SimGrid engine initialization and the platform loading.
23 - Track the links you want to monitor with sg_link_load_track() — you can untrack them later with
24 sg_link_load_untrack().
25 - Query the cumulated data about your link via these functions:
26 - sg_link_get_cum_load() to get the total load (in bytes) that went though the link since last reset.
27 - sg_link_get_avg_load() to get the average load (in bytes) that went though the link since last reset.
28 - sg_link_get_min_instantaneous_load() to get the peak minimum load (in bytes per second) observed on the link since
30 - sg_link_get_max_instantaneous_load() to get the peak maximum load (in bytes per second) observer on the link since
32 - Reset the counters on any tracked link via sg_link_load_reset().
35 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(link_load, kernel, "Logging specific to the LinkLoad plugin");
41 s4u::Link* link_{}; /*< The link onto which this data is attached*/
42 bool is_tracked_{false}; /*<Whether the link is tracked or not*/
44 double cumulated_bytes_{}; /*< Cumulated load since last reset*/
45 double min_bytes_per_second_{}; /*< Minimum instantaneous load observed since last reset*/
46 double max_bytes_per_second_{}; /*< Maximum instantaneous load observed since last reset*/
47 double last_reset_{}; /*< Timestamp of the last reset (init timestamp by default)*/
48 double last_updated_{}; /*< Timestamp of the last energy update event*/
51 static xbt::Extension<s4u::Link, LinkLoad> EXTENSION_ID;
53 explicit LinkLoad(s4u::Link* ptr);
59 double get_average_bytes();
62 bool is_tracked() const { return is_tracked_; }
63 double get_cumulated_bytes();
64 double get_min_bytes_per_second();
65 double get_max_bytes_per_second();
68 xbt::Extension<s4u::Link, LinkLoad> LinkLoad::EXTENSION_ID;
70 LinkLoad::LinkLoad(s4u::Link* ptr) : link_(ptr), is_tracked_(false)
72 XBT_DEBUG("Instantiating a LinkLoad for link '%s'", link_->get_cname());
75 void LinkLoad::track()
77 xbt_assert(not is_tracked_, "Trying to track load of link '%s' while it is already tracked, aborting.",
79 XBT_DEBUG("Tracking load of link '%s'", link_->get_cname());
85 void LinkLoad::untrack()
87 xbt_assert(is_tracked_, "Trying to untrack load of link '%s' while it is not tracked, aborting.", link_->get_cname());
88 XBT_DEBUG("Untracking load of link '%s'", link_->get_cname());
93 void LinkLoad::reset()
95 XBT_DEBUG("Resetting load of link '%s'", link_->get_cname());
97 cumulated_bytes_ = 0.0;
98 min_bytes_per_second_ = std::numeric_limits<double>::max();
99 max_bytes_per_second_ = std::numeric_limits<double>::lowest();
100 XBT_DEBUG("min_bytes_per_second_ = %g", min_bytes_per_second_);
101 XBT_DEBUG("max_bytes_per_second_ = %g", max_bytes_per_second_);
102 last_reset_ = simgrid::s4u::Engine::get_clock();
103 last_updated_ = last_reset_;
106 void LinkLoad::update()
108 XBT_DEBUG("Updating load of link '%s'", link_->get_cname());
109 xbt_assert(is_tracked_,
110 "Trying to update load of link '%s' while it is NOT tracked, aborting."
111 " Please track your link with sg_link_load_track before trying to access any of its load metrics.",
114 double current_instantaneous_bytes_per_second = link_->get_usage();
115 double now = simgrid::s4u::Engine::get_clock();
117 // Update minimum/maximum observed values if needed
118 min_bytes_per_second_ = std::min(min_bytes_per_second_, current_instantaneous_bytes_per_second);
119 max_bytes_per_second_ = std::max(max_bytes_per_second_, current_instantaneous_bytes_per_second);
121 // Update cumulated load
122 double duration_since_last_update = now - last_updated_;
123 double bytes_since_last_update = duration_since_last_update * current_instantaneous_bytes_per_second;
124 XBT_DEBUG("Cumulated %g bytes since last update (duration of %g seconds)", bytes_since_last_update,
125 duration_since_last_update);
126 xbt_assert(bytes_since_last_update >= 0, "LinkLoad plugin inconsistency: negative amount of bytes is accumulated.");
128 cumulated_bytes_ += bytes_since_last_update;
132 double LinkLoad::get_cumulated_bytes()
135 return cumulated_bytes_;
137 double LinkLoad::get_min_bytes_per_second()
140 return min_bytes_per_second_;
142 double LinkLoad::get_max_bytes_per_second()
145 return max_bytes_per_second_;
148 double LinkLoad::get_average_bytes()
152 double now = simgrid::s4u::Engine::get_clock();
153 if (now > last_reset_)
154 return cumulated_bytes_ / (now - last_reset_);
159 } // namespace plugin
160 } // namespace simgrid
162 using simgrid::plugin::LinkLoad;
164 /* **************************** events callback *************************** */
165 static void on_communication(const simgrid::kernel::activity::CommImpl& comm)
167 for (const auto* link : comm.get_traversed_links()) {
168 if (link != nullptr && link->get_sharing_policy() != simgrid::s4u::Link::SharingPolicy::WIFI) {
169 auto* link_load = link->extension<LinkLoad>();
170 XBT_DEBUG("Update %s on Comm Start/End", link->get_cname());
171 if (link_load->is_tracked())
177 /* **************************** Public interface *************************** */
180 * @ingroup plugin_link_load
181 * @brief Initialize the link cumulated load plugin.
182 * @pre The energy plugin should NOT be initialized.
184 void sg_link_load_plugin_init()
186 xbt_assert(simgrid::s4u::Engine::get_instance()->get_host_count() == 0,
187 "Please call sg_link_load_plugin_init() BEFORE initializing the platform.");
188 xbt_assert(not LinkLoad::EXTENSION_ID.valid(), "Double call to sg_link_load_plugin_init. Aborting.");
189 LinkLoad::EXTENSION_ID = simgrid::s4u::Link::extension_create<LinkLoad>();
191 // Attach new LinkLoad links created in the future.
192 simgrid::s4u::Link::on_creation_cb([](simgrid::s4u::Link& link) {
193 if (link.get_sharing_policy() != simgrid::s4u::Link::SharingPolicy::WIFI) {
194 XBT_DEBUG("Wired link '%s' created. Attaching a LinkLoad to it.", link.get_cname());
195 link.extension_set(new LinkLoad(&link));
197 XBT_DEBUG("Wireless link '%s' created. NOT attaching any LinkLoad to it.", link.get_cname());
201 // Call this plugin on some of the links' events.
202 simgrid::kernel::activity::CommImpl::on_start.connect(&on_communication);
203 simgrid::kernel::activity::CommImpl::on_completion.connect(&on_communication);
205 simgrid::s4u::Link::on_state_change_cb([](simgrid::s4u::Link const& link) {
206 if (link.get_sharing_policy() != simgrid::s4u::Link::SharingPolicy::WIFI) {
207 auto link_load = link.extension<LinkLoad>();
208 if (link_load->is_tracked())
212 simgrid::s4u::Link::on_communication_state_change_cb([](simgrid::kernel::resource::NetworkAction const& action,
213 simgrid::kernel::resource::Action::State /* previous */) {
214 for (auto const* link : action.get_links()) {
215 if (link != nullptr && link->get_sharing_policy() != simgrid::s4u::Link::SharingPolicy::WIFI) {
216 auto link_load = link->get_iface()->extension<LinkLoad>();
217 if (link_load->is_tracked())
225 * @ingroup plugin_link_load
226 * @brief Start the tracking of a link.
227 * @details This is required so the link cumulated load can be obtained later on.
228 * @pre The energy plugin should be initialized (cf. sg_link_load_plugin_init()).
229 * @pre The link should be in "untracked" state. In other words, do not call this function twice on the same link
230 * without a sg_link_load_untrack() call between them.
232 * @param link The link to track.
234 void sg_link_load_track(const_sg_link_t link)
236 xbt_assert(LinkLoad::EXTENSION_ID.valid(),
237 "Please call sg_link_load_plugin_init before sg_link_load_track. Aborting.");
238 link->extension<LinkLoad>()->track();
242 * @ingroup plugin_link_load
243 * @brief Stop the tracking of a link.
244 * @details Once the tracking is stopped, the cumulated load of the link can no longer be obtained until
245 * sg_link_load_track() is called again on this link.
246 * @pre The energy plugin should be initialized (cf. sg_link_load_plugin_init()).
247 * @pre The link should be in "tracked" state. In other words, do not call this function twice on the same link without
248 * a sg_link_load_track() call between them.
250 * @param link The link to untrack.
252 void sg_link_load_untrack(const_sg_link_t link)
254 xbt_assert(LinkLoad::EXTENSION_ID.valid(),
255 "Please call sg_link_load_plugin_init before sg_link_load_untrack. Aborting.");
256 link->extension<LinkLoad>()->untrack();
260 * @ingroup plugin_link_load
261 * @brief Resets the cumulated load counters of a link.
262 * @pre The energy plugin should be initialized (cf. sg_link_load_plugin_init()).
263 * @pre The link should be in "tracked" state (cf. sg_link_load_track()).
265 * @param link The link whose counters should be reset.
267 void sg_link_load_reset(const_sg_link_t link)
269 xbt_assert(LinkLoad::EXTENSION_ID.valid(),
270 "Please call sg_link_load_plugin_init before sg_link_load_reset. Aborting.");
271 link->extension<LinkLoad>()->reset();
275 * @ingroup plugin_link_load
276 * @brief Get the cumulated load of a link (since the last call to sg_link_load_reset()).
277 * @pre The energy plugin should be initialized (cf. sg_link_load_plugin_init()).
278 * @pre The link should be in "tracked" state (cf. sg_link_load_track()).
280 * @param link The link whose cumulated load is requested.
281 * @return The load (in bytes) that passed through the given link since the last call to sg_link_load_reset.
283 double sg_link_get_cum_load(const_sg_link_t link)
285 xbt_assert(LinkLoad::EXTENSION_ID.valid(),
286 "Please call sg_link_load_plugin_init before sg_link_get_cum_load. Aborting.");
287 return link->extension<LinkLoad>()->get_cumulated_bytes();
291 * @ingroup plugin_link_load
292 * @brief Get the average load of a link (since the last call to sg_link_load_reset()).
293 * @pre The energy plugin should be initialized (cf. sg_link_load_plugin_init()).
294 * @pre The link should be in "tracked" state (cf. sg_link_load_track()).
296 * @param link The link whose average load is requested.
297 * @return The average load (in bytes) that passed through the given link since the last call to sg_link_load_reset.
299 double sg_link_get_avg_load(const_sg_link_t link)
301 xbt_assert(LinkLoad::EXTENSION_ID.valid(),
302 "Please call sg_link_load_plugin_init before sg_link_get_avg_load. Aborting.");
303 return link->extension<LinkLoad>()->get_average_bytes();
307 * @ingroup plugin_link_load
308 * @brief Get the minimum instantaneous load of a link (since the last call to sg_link_load_reset()).
309 * @pre The energy plugin should be initialized (cf. sg_link_load_plugin_init()).
310 * @pre The link should be in "tracked" state (cf. sg_link_load_track()).
312 * @param link The link whose average load is requested.
313 * @return The minimum load instantaneous load (in bytes per second) that passed through the given link since the last
314 call to sg_link_load_reset.
316 double sg_link_get_min_instantaneous_load(const_sg_link_t link)
318 xbt_assert(LinkLoad::EXTENSION_ID.valid(),
319 "Please call sg_link_load_plugin_init before sg_link_get_min_load. Aborting.");
320 return link->extension<LinkLoad>()->get_min_bytes_per_second();
324 * @ingroup plugin_link_load
325 * @brief Get the maximum instantaneous load of a link (since the last call to sg_link_load_reset()).
326 * @pre The energy plugin should be initialized (cf. sg_link_load_plugin_init()).
327 * @pre The link should be in "tracked" state (cf. sg_link_load_track()).
329 * @param link The link whose average load is requested.
330 * @return The maximum load instantaneous load (in bytes per second) that passed through the given link since the last
331 call to sg_link_load_reset.
333 double sg_link_get_max_instantaneous_load(const_sg_link_t link)
335 xbt_assert(LinkLoad::EXTENSION_ID.valid(),
336 "Please call sg_link_load_plugin_init before sg_link_get_max_load. Aborting.");
337 return link->extension<LinkLoad>()->get_max_bytes_per_second();