From 4ca85dfa6522596c3bf8c3d79f9c98629e06d4f4 Mon Sep 17 00:00:00 2001 From: Yann Duplouy Date: Thu, 11 Apr 2019 12:00:07 +0200 Subject: [PATCH] Splitting trace_mgr into a file per class --- src/kernel/resource/profile/DatedValue.cpp | 25 +++ src/kernel/resource/profile/DatedValue.hpp | 35 ++++ src/kernel/resource/profile/FutureEvtSet.cpp | 53 ++++++ src/kernel/resource/profile/FutureEvtSet.hpp | 35 ++++ src/kernel/resource/profile/Profile.cpp | 128 ++++++++++++++ src/kernel/resource/profile/Profile.hpp | 53 ++++++ src/kernel/resource/profile/trace_mgr.cpp | 169 +------------------ src/kernel/resource/profile/trace_mgr.hpp | 85 +--------- 8 files changed, 337 insertions(+), 246 deletions(-) create mode 100644 src/kernel/resource/profile/DatedValue.cpp create mode 100644 src/kernel/resource/profile/DatedValue.hpp create mode 100644 src/kernel/resource/profile/FutureEvtSet.cpp create mode 100644 src/kernel/resource/profile/FutureEvtSet.hpp create mode 100644 src/kernel/resource/profile/Profile.cpp create mode 100644 src/kernel/resource/profile/Profile.hpp diff --git a/src/kernel/resource/profile/DatedValue.cpp b/src/kernel/resource/profile/DatedValue.cpp new file mode 100644 index 0000000000..b104af7cdc --- /dev/null +++ b/src/kernel/resource/profile/DatedValue.cpp @@ -0,0 +1,25 @@ +/* Copyright (c) 2004-2019. The SimGrid Team. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +//#include "src/kernel/resource/profile/DatedValue.hpp" +#include + +namespace simgrid { +namespace kernel { +namespace profile { + +bool DatedValue::operator==(DatedValue const& e2) const +{ + return (fabs(date_ - e2.date_) < 0.0001) && (fabs(value_ - e2.value_) < 0.0001); +} +std::ostream& operator<<(std::ostream& out, const DatedValue& e) +{ + out << e.date_ << " " << e.value_; + return out; +} + +} // namespace profile +} // namespace kernel +} // namespace simgrid \ No newline at end of file diff --git a/src/kernel/resource/profile/DatedValue.hpp b/src/kernel/resource/profile/DatedValue.hpp new file mode 100644 index 0000000000..8530fb77c2 --- /dev/null +++ b/src/kernel/resource/profile/DatedValue.hpp @@ -0,0 +1,35 @@ +/* Copyright (c) 2004-2019. The SimGrid Team. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include + +namespace simgrid { +namespace kernel { +namespace profile { + +/** @brief Modeling of the availability profile (due to an external load) or the churn + * + * There is 4 main concepts in this module: + * - #simgrid::kernel::profile::DatedValue: a pair (both are of type double) + * - #simgrid::kernel::profile::Profile: a list of dated values + * - #simgrid::kernel::profile::Event: links a given trace to a given SimGrid resource. + * A Cpu for example has 2 kinds of events: state (ie, is it ON/OFF) and speed, + * while a link has 3 iterators: state, bandwidth and latency. + * - #simgrid::kernel::profile::FutureEvtSet: makes it easy to find the next occuring event of all profiles + */ +class XBT_PUBLIC DatedValue { +public: + double date_ = 0; + double value_ = 0; + explicit DatedValue() = default; + explicit DatedValue(double d, double v) : date_(d), value_(v) {} + bool operator==(DatedValue const& e2) const; + bool operator!=(DatedValue const& e2) const { return not(*this == e2); } +}; +std::ostream& operator<<(std::ostream& out, const DatedValue& e); + +} // namespace profile +} // namespace kernel +} // namespace simgrid \ No newline at end of file diff --git a/src/kernel/resource/profile/FutureEvtSet.cpp b/src/kernel/resource/profile/FutureEvtSet.cpp new file mode 100644 index 0000000000..59b0bdc94c --- /dev/null +++ b/src/kernel/resource/profile/FutureEvtSet.cpp @@ -0,0 +1,53 @@ +/* Copyright (c) 2004-2019. The SimGrid Team. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "src/kernel/resource/profile/FutureEvtSet.hpp" + +namespace simgrid { +namespace kernel { +namespace profile { + +FutureEvtSet::FutureEvtSet() = default; +FutureEvtSet::~FutureEvtSet() +{ + while (not heap_.empty()) { + delete heap_.top().second; + heap_.pop(); + } +} + +/** @brief Schedules an event to a future date */ +void FutureEvtSet::add_event(double date, Event* evt) +{ + heap_.emplace(date, evt); +} + +/** @brief returns the date of the next occurring event (or -1 if empty) */ +double FutureEvtSet::next_date() const +{ + return heap_.empty() ? -1.0 : heap_.top().first; +} + +/** @brief Retrieves the next occurring event, or nullptr if none happens before date */ +Event* FutureEvtSet::pop_leq(double date, double* value, resource::Resource** resource) +{ + double event_date = next_date(); + if (event_date > date || heap_.empty()) + return nullptr; + + Event* event = heap_.top().second; + Profile* profile = event->profile; + DatedValue dateVal = profile->next(event); + + *resource = event->resource; + *value = dateVal.value_; + + heap_.pop(); + + return event; +} +} // namespace profile +} // namespace kernel +} // namespace simgrid \ No newline at end of file diff --git a/src/kernel/resource/profile/FutureEvtSet.hpp b/src/kernel/resource/profile/FutureEvtSet.hpp new file mode 100644 index 0000000000..f565f0ab85 --- /dev/null +++ b/src/kernel/resource/profile/FutureEvtSet.hpp @@ -0,0 +1,35 @@ +/* Copyright (c) 2004-2019. The SimGrid Team. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include +#ifndef FUTUREEVTSET_HPP +#define FUTUREEVTSET_HPP + +namespace simgrid { +namespace kernel { +namespace profile { + +/** @brief Future Event Set (collection of iterators over the traces) + * That's useful to quickly know which is the next occurring event in a set of traces. */ +class XBT_PUBLIC FutureEvtSet { +public: + FutureEvtSet(); + FutureEvtSet(const FutureEvtSet&) = delete; + FutureEvtSet& operator=(const FutureEvtSet&) = delete; + virtual ~FutureEvtSet(); + double next_date() const; + Event* pop_leq(double date, double* value, resource::Resource** resource); + void add_event(double date, Event* evt); + +private: + typedef std::pair Qelt; + std::priority_queue, std::greater> heap_; +}; + +} // namespace profile +} // namespace kernel +} // namespace simgrid + +#endif \ No newline at end of file diff --git a/src/kernel/resource/profile/Profile.cpp b/src/kernel/resource/profile/Profile.cpp new file mode 100644 index 0000000000..73f2962e88 --- /dev/null +++ b/src/kernel/resource/profile/Profile.cpp @@ -0,0 +1,128 @@ +/* Copyright (c) 2004-2019. The SimGrid Team. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "xbt/log.h" +#include "xbt/sysdep.h" +#include +#include "src/kernel/resource/profile/Profile.hpp" +#include +#include "src/kernel/resource/profile/FutureEvtSet.cpp" +#include "src/kernel/resource/profile/DatedValue.cpp" +#include "simgrid/forward.h" +#include + +static std::unordered_map trace_list; + +namespace simgrid { +namespace kernel { +namespace profile { + +Profile::Profile() +{ + /* Add the first fake event storing the time at which the trace begins */ + DatedValue val(0, -1); + event_list.push_back(val); +} +Profile::~Profile() = default; + +/** @brief Register this profile for that resource onto that FES, + * and get an iterator over the integrated trace */ +Event* Profile::schedule(FutureEvtSet* fes, resource::Resource* resource) +{ + Event* event = new Event(); + event->profile = this; + event->idx = 0; + event->resource = resource; + event->free_me = false; + + xbt_assert((event->idx < event_list.size()), "Your profile should have at least one event!"); + + fes_ = fes; + fes_->add_event(0.0 /* start time */, event); + + return event; +} + +/** @brief Gets the next event from a profile */ +DatedValue Profile::next(Event* event) +{ + double event_date = fes_->next_date(); + DatedValue dateVal = event_list.at(event->idx); + + if (event->idx < event_list.size() - 1) { + fes_->add_event(event_date + dateVal.date_, event); + event->idx++; + } else if (dateVal.date_ > 0) { /* Last element. Shall we loop? */ + fes_->add_event(event_date + dateVal.date_, event); + event->idx = 1; /* idx=0 is a placeholder to store when events really start */ + } else { /* If we don't loop, we don't need this event anymore */ + event->free_me = true; + } + + return dateVal; +} + +Profile* Profile::from_string(const std::string& name, const std::string& input, double periodicity) +{ + int linecount = 0; + simgrid::kernel::profile::Profile* profile = new simgrid::kernel::profile::Profile(); + simgrid::kernel::profile::DatedValue* last_event = &(profile->event_list.back()); + + xbt_assert(trace_list.find(name) == trace_list.end(), "Refusing to define trace %s twice", name.c_str()); + + std::vector list; + boost::split(list, input, boost::is_any_of("\n\r")); + for (auto val : list) { + simgrid::kernel::profile::DatedValue event; + linecount++; + boost::trim(val); + if (val[0] == '#' || val[0] == '\0' || val[0] == '%') // pass comments + continue; + if (sscanf(val.c_str(), "PERIODICITY %lg\n", &periodicity) == 1) + continue; + if (sscanf(val.c_str(), "LOOPAFTER %lg\n", &periodicity) == 1) + continue; + + XBT_ATTRIB_UNUSED int res = sscanf(val.c_str(), "%lg %lg\n", &event.date_, &event.value_); + xbt_assert(res == 2, "%s:%d: Syntax error in trace\n%s", name.c_str(), linecount, input.c_str()); + + xbt_assert(last_event->date_ <= event.date_, + "%s:%d: Invalid trace: Events must be sorted, but time %g > time %g.\n%s", name.c_str(), linecount, + last_event->date_, event.date_, input.c_str()); + last_event->date_ = event.date_ - last_event->date_; + + profile->event_list.push_back(event); + last_event = &(profile->event_list.back()); + } + if (last_event) { + if (periodicity > 0) { + last_event->date_ = periodicity + profile->event_list.at(0).date_; + } else { + last_event->date_ = -1; + } + } + + trace_list.insert({name, profile}); + + return profile; +} +Profile* Profile::from_file(const std::string& path) +{ + xbt_assert(not path.empty(), "Cannot parse a trace from an empty filename"); + xbt_assert(trace_list.find(path) == trace_list.end(), "Refusing to define trace %s twice", path.c_str()); + + std::ifstream* f = surf_ifsopen(path); + xbt_assert(not f->fail(), "Cannot open file '%s' (path=%s)", path.c_str(), (boost::join(surf_path, ":")).c_str()); + + std::stringstream buffer; + buffer << f->rdbuf(); + delete f; + + return Profile::from_string(path, buffer.str(), -1); +} + +} // namespace profile +} // namespace kernel +} // namespace simgrid diff --git a/src/kernel/resource/profile/Profile.hpp b/src/kernel/resource/profile/Profile.hpp new file mode 100644 index 0000000000..305808a2b1 --- /dev/null +++ b/src/kernel/resource/profile/Profile.hpp @@ -0,0 +1,53 @@ +/* Copyright (c) 2004-2019. The SimGrid Team. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#ifndef PROFILE_HPP +#define PROFILE_HPP + +#include "src/kernel/resource/profile/DatedValue.hpp" +#include "src/kernel/resource/profile/FutureEvtSet.hpp" +#include +#include + +namespace simgrid { +namespace kernel { +namespace profile { + +class Event { +public: + Profile* profile; + unsigned int idx; + resource::Resource* resource; + bool free_me; +}; + +/** @brief A profile is a set of timed values, encoding the value that a variable takes at what time + * + * It is useful to model dynamic platforms, where an external load that makes the resource availability change over + * time. To model that, you have to set several profiles per resource: one for the on/off state and one for each + * numerical value (computational speed, bandwidth and/or latency). + */ +class XBT_PUBLIC Profile { +public: + /** Creates an empty trace */ + explicit Profile(); + virtual ~Profile(); + Event* schedule(FutureEvtSet* fes, resource::Resource* resource); + DatedValue next(Event* event); + + static Profile* from_file(const std::string& path); + static Profile* from_string(const std::string& name, const std::string& input, double periodicity); + // private: + std::vector event_list; + +private: + FutureEvtSet* fes_ = nullptr; +}; + +} // namespace profile +} // namespace kernel +} // namespace simgrid + +#endif \ No newline at end of file diff --git a/src/kernel/resource/profile/trace_mgr.cpp b/src/kernel/resource/profile/trace_mgr.cpp index a796657473..6c0d0db658 100644 --- a/src/kernel/resource/profile/trace_mgr.cpp +++ b/src/kernel/resource/profile/trace_mgr.cpp @@ -16,169 +16,14 @@ #include #include -XBT_LOG_NEW_DEFAULT_SUBCATEGORY(profile, resource, "Surf profile management"); - -static std::unordered_map trace_list; - -namespace simgrid { -namespace kernel { -namespace profile { - -bool DatedValue::operator==(DatedValue const& e2) const -{ - return (fabs(date_ - e2.date_) < 0.0001) && (fabs(value_ - e2.value_) < 0.0001); -} -std::ostream& operator<<(std::ostream& out, const DatedValue& e) -{ - out << e.date_ << " " << e.value_; - return out; -} - -Profile::Profile() -{ - /* Add the first fake event storing the time at which the trace begins */ - DatedValue val(0, -1); - event_list.push_back(val); -} -Profile::~Profile() = default; - -/** @brief Register this profile for that resource onto that FES, - * and get an iterator over the integrated trace */ -Event* Profile::schedule(FutureEvtSet* fes, resource::Resource* resource) -{ - Event* event = new Event(); - event->profile = this; - event->idx = 0; - event->resource = resource; - event->free_me = false; - - xbt_assert((event->idx < event_list.size()), "Your profile should have at least one event!"); - - fes_ = fes; - fes_->add_event(0.0 /* start time */, event); - - return event; -} - -/** @brief Gets the next event from a profile */ -DatedValue Profile::next(Event* event) -{ - double event_date = fes_->next_date(); - DatedValue dateVal = event_list.at(event->idx); - - if (event->idx < event_list.size() - 1) { - fes_->add_event(event_date + dateVal.date_, event); - event->idx++; - } else if (dateVal.date_ > 0) { /* Last element. Shall we loop? */ - fes_->add_event(event_date + dateVal.date_, event); - event->idx = 1; /* idx=0 is a placeholder to store when events really start */ - } else { /* If we don't loop, we don't need this event anymore */ - event->free_me = true; - } - - return dateVal; -} - -Profile* Profile::from_string(const std::string& name, const std::string& input, double periodicity) -{ - int linecount = 0; - simgrid::kernel::profile::Profile* profile = new simgrid::kernel::profile::Profile(); - simgrid::kernel::profile::DatedValue* last_event = &(profile->event_list.back()); - - xbt_assert(trace_list.find(name) == trace_list.end(), "Refusing to define trace %s twice", name.c_str()); - - std::vector list; - boost::split(list, input, boost::is_any_of("\n\r")); - for (auto val : list) { - simgrid::kernel::profile::DatedValue event; - linecount++; - boost::trim(val); - if (val[0] == '#' || val[0] == '\0' || val[0] == '%') // pass comments - continue; - if (sscanf(val.c_str(), "PERIODICITY %lg\n", &periodicity) == 1) - continue; - if (sscanf(val.c_str(), "LOOPAFTER %lg\n", &periodicity) == 1) - continue; - - XBT_ATTRIB_UNUSED int res = sscanf(val.c_str(), "%lg %lg\n", &event.date_, &event.value_); - xbt_assert(res == 2, "%s:%d: Syntax error in trace\n%s", name.c_str(), linecount, input.c_str()); +#include "src/kernel/resource/profile/Profile.cpp" - xbt_assert(last_event->date_ <= event.date_, - "%s:%d: Invalid trace: Events must be sorted, but time %g > time %g.\n%s", name.c_str(), linecount, - last_event->date_, event.date_, input.c_str()); - last_event->date_ = event.date_ - last_event->date_; +/** This file has been splitted into three different files: + - Profile, defining the class Profile and functions that allow to use provided profiles; + - DatedValue, the class of a DatedValue (a value and a timestamp); + - FutureEvtSet, a set of events happening in the future. **/ - profile->event_list.push_back(event); - last_event = &(profile->event_list.back()); - } - if (last_event) { - if (periodicity > 0) { - last_event->date_ = periodicity + profile->event_list.at(0).date_; - } else { - last_event->date_ = -1; - } - } - - trace_list.insert({name, profile}); - - return profile; -} -Profile* Profile::from_file(const std::string& path) -{ - xbt_assert(not path.empty(), "Cannot parse a trace from an empty filename"); - xbt_assert(trace_list.find(path) == trace_list.end(), "Refusing to define trace %s twice", path.c_str()); - - std::ifstream* f = surf_ifsopen(path); - xbt_assert(not f->fail(), "Cannot open file '%s' (path=%s)", path.c_str(), (boost::join(surf_path, ":")).c_str()); - - std::stringstream buffer; - buffer << f->rdbuf(); - delete f; - - return Profile::from_string(path, buffer.str(), -1); -} -FutureEvtSet::FutureEvtSet() = default; -FutureEvtSet::~FutureEvtSet() -{ - while (not heap_.empty()) { - delete heap_.top().second; - heap_.pop(); - } -} - -/** @brief Schedules an event to a future date */ -void FutureEvtSet::add_event(double date, Event* evt) -{ - heap_.emplace(date, evt); -} - -/** @brief returns the date of the next occurring event (or -1 if empty) */ -double FutureEvtSet::next_date() const -{ - return heap_.empty() ? -1.0 : heap_.top().first; -} - -/** @brief Retrieves the next occurring event, or nullptr if none happens before date */ -Event* FutureEvtSet::pop_leq(double date, double* value, resource::Resource** resource) -{ - double event_date = next_date(); - if (event_date > date || heap_.empty()) - return nullptr; - - Event* event = heap_.top().second; - Profile* profile = event->profile; - DatedValue dateVal = profile->next(event); - - *resource = event->resource; - *value = dateVal.value_; - - heap_.pop(); - - return event; -} -} // namespace profile -} // namespace kernel -} // namespace simgrid +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(profile, resource, "Surf profile management"); void tmgr_finalize() { for (auto const& kv : trace_list) @@ -192,4 +37,4 @@ void tmgr_trace_event_unref(simgrid::kernel::profile::Event** event) delete *event; *event = nullptr; } -} +} \ No newline at end of file diff --git a/src/kernel/resource/profile/trace_mgr.hpp b/src/kernel/resource/profile/trace_mgr.hpp index c0abe9e5ff..9930b140e2 100644 --- a/src/kernel/resource/profile/trace_mgr.hpp +++ b/src/kernel/resource/profile/trace_mgr.hpp @@ -7,27 +7,12 @@ #define SURF_PMGR_H #include "simgrid/forward.h" +#include "src/kernel/resource/profile/Profile.hpp" #include "xbt/sysdep.h" #include #include -/* Iterator within a trace */ -namespace simgrid { -namespace kernel { -namespace profile { -/** @brief Links a profile to a resource */ -class Event { -public: - Profile* profile; - unsigned int idx; - resource::Resource* resource; - bool free_me; -}; - -} // namespace profile -} // namespace kernel -} // namespace simgrid extern XBT_PRIVATE simgrid::kernel::profile::FutureEvtSet future_evt_set; /** @@ -38,76 +23,8 @@ extern XBT_PRIVATE simgrid::kernel::profile::FutureEvtSet future_evt_set; * When the structure is freed, the argument is set to nullptr */ XBT_PUBLIC void tmgr_trace_event_unref(simgrid::kernel::profile::Event** trace_event); - XBT_PUBLIC void tmgr_finalize(); -namespace simgrid { -namespace kernel { -namespace profile { - -/** @brief Modeling of the availability profile (due to an external load) or the churn - * - * There is 4 main concepts in this module: - * - #simgrid::kernel::profile::DatedValue: a pair (both are of type double) - * - #simgrid::kernel::profile::Profile: a list of dated values - * - #simgrid::kernel::profile::Event: links a given trace to a given SimGrid resource. - * A Cpu for example has 2 kinds of events: state (ie, is it ON/OFF) and speed, - * while a link has 3 iterators: state, bandwidth and latency. - * - #simgrid::kernel::profile::FutureEvtSet: makes it easy to find the next occuring event of all profiles - */ -class XBT_PUBLIC DatedValue { -public: - double date_ = 0; - double value_ = 0; - explicit DatedValue() = default; - explicit DatedValue(double d, double v) : date_(d), value_(v) {} - bool operator==(DatedValue const& e2) const; - bool operator!=(DatedValue const& e2) const { return not(*this == e2); } -}; -std::ostream& operator<<(std::ostream& out, const DatedValue& e); - -/** @brief A profile is a set of timed values, encoding the value that a variable takes at what time - * - * It is useful to model dynamic platforms, where an external load that makes the resource availability change over - * time. To model that, you have to set several profiles per resource: one for the on/off state and one for each - * numerical value (computational speed, bandwidth and/or latency). - */ -class XBT_PUBLIC Profile { -public: - /** Creates an empty trace */ - explicit Profile(); - virtual ~Profile(); - Event* schedule(FutureEvtSet* fes, resource::Resource* resource); - DatedValue next(Event* event); - - static Profile* from_file(const std::string& path); - static Profile* from_string(const std::string& name, const std::string& input, double periodicity); - // private: - std::vector event_list; - -private: - FutureEvtSet* fes_ = nullptr; -}; - -/** @brief Future Event Set (collection of iterators over the traces) - * That's useful to quickly know which is the next occurring event in a set of traces. */ -class XBT_PUBLIC FutureEvtSet { -public: - FutureEvtSet(); - FutureEvtSet(const FutureEvtSet&) = delete; - FutureEvtSet& operator=(const FutureEvtSet&) = delete; - virtual ~FutureEvtSet(); - double next_date() const; - Event* pop_leq(double date, double* value, resource::Resource** resource); - void add_event(double date, Event* evt); - -private: - typedef std::pair Qelt; - std::priority_queue, std::greater> heap_; -}; -} // namespace profile -} // namespace kernel -} // namespace simgrid #endif /* SURF_PMGR_H */ -- 2.20.1