Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Remove useless declaration of default destructor.
[simgrid.git] / src / plugins / link_load.cpp
1 /* Copyright (c) 2017-2021. The SimGrid Team. All rights reserved.          */
2
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. */
5
6 #include "simgrid/host.h"
7 #include "simgrid/plugins/load.h"
8 #include "simgrid/s4u/Link.hpp"
9 #include "src/surf/network_interface.hpp"
10 #include "src/surf/surf_interface.hpp"
11 #include "surf/surf.hpp"
12
13 #include <limits>
14
15 SIMGRID_REGISTER_PLUGIN(link_load, "Link cumulated load.", &sg_link_load_plugin_init)
16
17 /** @defgroup plugin_link_load Plugin Link Cumulated Load
18
19  This is the link cumulated load plugin.
20  It enables to monitor how links are used over time by cumulating the amount of bytes that go through the link.
21
22  Usage:
23  - Call sg_link_load_plugin_init() between the SimGrid engine initialization and the platform loading.
24  - Track the links you want to monitor with sg_link_load_track() — you can untrack them later with
25  sg_link_load_untrack().
26  - Query the cumulated data about your link via these functions:
27    - sg_link_get_cum_load() to get the total load (in bytes) that went though the link since last reset.
28    - sg_link_get_avg_load() to get the average load (in bytes) that went though the link since last reset.
29    - sg_link_get_min_instantaneous_load() to get the peak minimum load (in bytes per second) observed on the link since
30  last reset.
31    - sg_link_get_max_instantaneous_load() to get the peak maximum load (in bytes per second) observer on the link since
32  last reset.
33  - Reset the counters on any tracked link via sg_link_load_reset().
34 */
35
36 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(link_load, surf, "Logging specific to the SURF LinkLoad plugin");
37
38 namespace simgrid {
39 namespace plugin {
40
41 class LinkLoad {
42 public:
43   static simgrid::xbt::Extension<simgrid::s4u::Link, LinkLoad> EXTENSION_ID;
44
45   explicit LinkLoad(simgrid::s4u::Link* ptr);
46
47   void track();
48   void untrack();
49   void reset();
50   void update();
51   double get_average_bytes();
52
53   /// Getter methods.
54   bool is_tracked() const;
55   double get_cumulated_bytes();
56   double get_min_bytes_per_second();
57   double get_max_bytes_per_second();
58
59 private:
60   s4u::Link* link_{};      /*< The link onto which this data is attached*/
61   bool is_tracked_{false}; /*<Whether the link is tracked or not*/
62
63   double cumulated_bytes_{};      /*< Cumulated load since last reset*/
64   double min_bytes_per_second_{}; /*< Minimum instantaneous load observed since last reset*/
65   double max_bytes_per_second_{}; /*< Maximum instantaneous load observed since last reset*/
66   double last_reset_{};           /*< Timestamp of the last reset (init timestamp by default)*/
67   double last_updated_{};         /*< Timestamp of the last energy update event*/
68 };
69
70 xbt::Extension<s4u::Link, LinkLoad> LinkLoad::EXTENSION_ID;
71
72 LinkLoad::LinkLoad(simgrid::s4u::Link* ptr) : link_(ptr), is_tracked_(false)
73 {
74   XBT_DEBUG("Instantiating a LinkLoad for link '%s'", link_->get_cname());
75 }
76
77 void LinkLoad::track()
78 {
79   xbt_assert(!is_tracked_, "Trying to track load of link '%s' while it is already tracked, aborting.",
80              link_->get_cname());
81   XBT_DEBUG("Tracking load of link '%s'", link_->get_cname());
82
83   is_tracked_ = true;
84   reset();
85 }
86
87 void LinkLoad::untrack()
88 {
89   xbt_assert(is_tracked_, "Trying to untrack load of link '%s' while it is not tracked, aborting.", link_->get_cname());
90   XBT_DEBUG("Untracking load of link '%s'", link_->get_cname());
91
92   is_tracked_ = false;
93 }
94
95 void LinkLoad::reset()
96 {
97   XBT_DEBUG("Resetting load of link '%s'", link_->get_cname());
98
99   cumulated_bytes_      = 0.0;
100   min_bytes_per_second_ = std::numeric_limits<double>::max();
101   max_bytes_per_second_ = std::numeric_limits<double>::lowest();
102   XBT_DEBUG("min_bytes_per_second_ = %g", min_bytes_per_second_);
103   XBT_DEBUG("max_bytes_per_second_ = %g", max_bytes_per_second_);
104   last_reset_   = surf_get_clock();
105   last_updated_ = last_reset_;
106 }
107
108 void LinkLoad::update()
109 {
110   XBT_DEBUG("Updating load of link '%s'", link_->get_cname());
111   xbt_assert(is_tracked_,
112              "Trying to update load of link '%s' while it is NOT tracked, aborting."
113              " Please track your link with sg_link_load_track before trying to access any of its load metrics.",
114              link_->get_cname());
115
116   double current_instantaneous_bytes_per_second = link_->get_usage();
117   double now                                    = surf_get_clock();
118
119   // Update minimum/maximum observed values if needed
120   min_bytes_per_second_ = std::min(min_bytes_per_second_, current_instantaneous_bytes_per_second);
121   max_bytes_per_second_ = std::max(max_bytes_per_second_, current_instantaneous_bytes_per_second);
122
123   // Update cumulated load
124   double duration_since_last_update = now - last_updated_;
125   double bytes_since_last_update    = duration_since_last_update * current_instantaneous_bytes_per_second;
126   XBT_DEBUG("Cumulated %g bytes since last update (duration of %g seconds)", bytes_since_last_update,
127             duration_since_last_update);
128   xbt_assert(bytes_since_last_update >= 0, "LinkLoad plugin inconsistency: negative amount of bytes is accumulated.");
129
130   cumulated_bytes_ += bytes_since_last_update;
131   last_updated_ = now;
132 }
133
134 bool LinkLoad::is_tracked() const
135 {
136   return is_tracked_;
137 }
138 double LinkLoad::get_cumulated_bytes()
139 {
140   update();
141   return cumulated_bytes_;
142 }
143 double LinkLoad::get_min_bytes_per_second()
144 {
145   update();
146   return min_bytes_per_second_;
147 }
148 double LinkLoad::get_max_bytes_per_second()
149 {
150   update();
151   return max_bytes_per_second_;
152 }
153
154 double LinkLoad::get_average_bytes()
155 {
156   update();
157
158   double now = surf_get_clock();
159   if (now > last_reset_)
160     return cumulated_bytes_ / (now - last_reset_);
161   else
162     return 0;
163 }
164
165 } // namespace plugin
166 } // namespace simgrid
167
168 using simgrid::plugin::LinkLoad;
169
170 /* **************************** events  callback *************************** */
171 static void on_communicate(const simgrid::kernel::resource::NetworkAction& action)
172 {
173   XBT_DEBUG("on_communicate is called");
174   for (auto* link : action.get_links()) {
175     if (link == nullptr || link->get_sharing_policy() == simgrid::s4u::Link::SharingPolicy::WIFI)
176       continue;
177
178     auto link_load = link->get_iface()->extension<LinkLoad>();
179     if (link_load->is_tracked()) {
180       link_load->update();
181     }
182   }
183 }
184
185 /* **************************** Public interface *************************** */
186
187 /**
188  * @ingroup plugin_link_load
189  * @brief Initialize the link cumulated load plugin.
190  * @pre The energy plugin should NOT be initialized.
191  */
192 void sg_link_load_plugin_init()
193 {
194   xbt_assert(sg_host_count() == 0, "Please call sg_link_load_plugin_init() BEFORE initializing the platform.");
195   xbt_assert(!LinkLoad::EXTENSION_ID.valid(), "Double call to sg_link_load_plugin_init. Aborting.");
196   LinkLoad::EXTENSION_ID = simgrid::s4u::Link::extension_create<LinkLoad>();
197
198   // Attach new LinkLoad links created in the future.
199   simgrid::s4u::Link::on_creation.connect([](simgrid::s4u::Link& link) {
200     if (link.get_sharing_policy() != simgrid::s4u::Link::SharingPolicy::WIFI) {
201       XBT_DEBUG("Wired link '%s' created. Attaching a LinkLoad to it.", link.get_cname());
202       link.extension_set(new LinkLoad(&link));
203     } else {
204       XBT_DEBUG("Wireless link '%s' created. NOT attaching any LinkLoad to it.", link.get_cname());
205     }
206   });
207
208   // Call this plugin on some of the links' events.
209   simgrid::s4u::Link::on_communicate.connect(&on_communicate);
210   simgrid::s4u::Link::on_state_change.connect([](simgrid::s4u::Link const& link) {
211     if (link.get_sharing_policy() != simgrid::s4u::Link::SharingPolicy::WIFI) {
212       auto link_load = link.extension<LinkLoad>();
213       if (link_load->is_tracked())
214         link_load->update();
215     }
216   });
217   simgrid::s4u::Link::on_communication_state_change.connect(
218       [](simgrid::kernel::resource::NetworkAction const& action,
219          simgrid::kernel::resource::Action::State /* previous */) {
220         for (auto const* link : action.get_links()) {
221           if (link != nullptr && link->get_sharing_policy() != simgrid::s4u::Link::SharingPolicy::WIFI) {
222             auto link_load = link->get_iface()->extension<LinkLoad>();
223             if (link_load->is_tracked())
224               link_load->update();
225           }
226         }
227       });
228 }
229
230 /**
231  * @ingroup plugin_link_load
232  * @brief Start the tracking of a link.
233  * @details This is required so the link cumulated load can be obtained later on.
234  * @pre The energy plugin should be initialized (cf. sg_link_load_plugin_init()).
235  * @pre The link should be in "untracked" state. In other words, do not call this function twice on the same link
236  * without a sg_link_load_untrack() call between them.
237  *
238  * @param link The link to track.
239  */
240 void sg_link_load_track(const_sg_link_t link)
241 {
242   xbt_assert(LinkLoad::EXTENSION_ID.valid(),
243              "Please call sg_link_load_plugin_init before sg_link_load_track. Aborting.");
244   link->extension<LinkLoad>()->track();
245 }
246
247 /**
248  * @ingroup plugin_link_load
249  * @brief Stop the tracking of a link.
250  * @details Once the tracking is stopped, the cumulated load of the link can no longer be obtained until
251  * sg_link_load_track() is called again on this link.
252  * @pre The energy plugin should be initialized (cf. sg_link_load_plugin_init()).
253  * @pre The link should be in "tracked" state. In other words, do not call this function twice on the same link without
254  * a sg_link_load_track() call between them.
255  *
256  * @param link The link to untrack.
257  */
258 void sg_link_load_untrack(const_sg_link_t link)
259 {
260   xbt_assert(LinkLoad::EXTENSION_ID.valid(),
261              "Please call sg_link_load_plugin_init before sg_link_load_untrack. Aborting.");
262   link->extension<LinkLoad>()->untrack();
263 }
264
265 /**
266  * @ingroup plugin_link_load
267  * @brief Resets the cumulated load counters of a link.
268  * @pre The energy plugin should be initialized (cf. sg_link_load_plugin_init()).
269  * @pre The link should be in "tracked" state (cf. sg_link_load_track()).
270  *
271  * @param link The link whose counters should be reset.
272  */
273 void sg_link_load_reset(const_sg_link_t link)
274 {
275   xbt_assert(LinkLoad::EXTENSION_ID.valid(),
276              "Please call sg_link_load_plugin_init before sg_link_load_reset. Aborting.");
277   link->extension<LinkLoad>()->reset();
278 }
279
280 /**
281  * @ingroup plugin_link_load
282  * @brief Get the cumulated load of a link (since the last call to sg_link_load_reset()).
283  * @pre The energy plugin should be initialized (cf. sg_link_load_plugin_init()).
284  * @pre The link should be in "tracked" state (cf. sg_link_load_track()).
285
286  * @param link The link whose cumulated load is requested.
287  * @return The load (in bytes) that passed through the given link since the last call to sg_link_load_reset.
288  */
289 double sg_link_get_cum_load(const_sg_link_t link)
290 {
291   xbt_assert(LinkLoad::EXTENSION_ID.valid(),
292              "Please call sg_link_load_plugin_init before sg_link_get_cum_load. Aborting.");
293   return link->extension<LinkLoad>()->get_cumulated_bytes();
294 }
295
296 /**
297  * @ingroup plugin_link_load
298  * @brief Get the average load of a link (since the last call to sg_link_load_reset()).
299  * @pre The energy plugin should be initialized (cf. sg_link_load_plugin_init()).
300  * @pre The link should be in "tracked" state (cf. sg_link_load_track()).
301
302  * @param link The link whose average load is requested.
303  * @return The average load (in bytes) that passed through the given link since the last call to sg_link_load_reset.
304  */
305 double sg_link_get_avg_load(const_sg_link_t link)
306 {
307   xbt_assert(LinkLoad::EXTENSION_ID.valid(),
308              "Please call sg_link_load_plugin_init before sg_link_get_avg_load. Aborting.");
309   return link->extension<LinkLoad>()->get_average_bytes();
310 }
311
312 /**
313  * @ingroup plugin_link_load
314  * @brief Get the minimum instantaneous load of a link (since the last call to sg_link_load_reset()).
315  * @pre The energy plugin should be initialized (cf. sg_link_load_plugin_init()).
316  * @pre The link should be in "tracked" state (cf. sg_link_load_track()).
317
318  * @param link The link whose average load is requested.
319  * @return The minimum load instantaneous load (in bytes per second) that passed through the given link since the last
320  call to sg_link_load_reset.
321  */
322 double sg_link_get_min_instantaneous_load(const_sg_link_t link)
323 {
324   xbt_assert(LinkLoad::EXTENSION_ID.valid(),
325              "Please call sg_link_load_plugin_init before sg_link_get_min_load. Aborting.");
326   return link->extension<LinkLoad>()->get_min_bytes_per_second();
327 }
328
329 /**
330  * @ingroup plugin_link_load
331  * @brief Get the maximum instantaneous load of a link (since the last call to sg_link_load_reset()).
332  * @pre The energy plugin should be initialized (cf. sg_link_load_plugin_init()).
333  * @pre The link should be in "tracked" state (cf. sg_link_load_track()).
334
335  * @param link The link whose average load is requested.
336  * @return The maximum load instantaneous load (in bytes per second) that passed through the given link since the last
337  call to sg_link_load_reset.
338  */
339 double sg_link_get_max_instantaneous_load(const_sg_link_t link)
340 {
341   xbt_assert(LinkLoad::EXTENSION_ID.valid(),
342              "Please call sg_link_load_plugin_init before sg_link_get_max_load. Aborting.");
343   return link->extension<LinkLoad>()->get_max_bytes_per_second();
344 }