16#include "sparta/utils/Enum.hpp"
35 namespace has_ostream_operator_impl {
69 static std::ostream & s;
71 static constexpr bool value {
77 sizeof(
test(s << t)) ==
sizeof(
yes)};
87 template<
typename T>
struct StateSet;
104 weak_pool_ptr_(weak_pool) {}
108 inline void operator()(StateTrackerUnit<T> * ptr)
const {
109 if(!valid_ || !ptr) {
112 if(!weak_pool_ptr_.expired()) {
113 weak_pool_ptr_.lock()->releaseToPool(ptr);
121 std::weak_ptr<StatePool<T>> weak_pool_ptr_;
133 using state_tracker_ptr =
134 std::unique_ptr<StateTrackerUnit<T>, StateTrackerDeleter<T>>;
147 using tracker_queue_ptr =
148 std::unique_ptr<std::deque<state_tracker_ptr<T>>,
149 std::function<void(std::deque<state_tracker_ptr<T>> *)>>;
163 static size_t next()
noexcept {
164 static size_t counter {0};
184 explicit StatePool(
const std::string & tracking_filename) :
191 pool_existence_reference_(this, [](void *){}),
194 tracking_filename_(tracking_filename),
198 available_tracker_queue_(
new std::deque<state_tracker_ptr<T>>(),
199 [
this](std::deque<state_tracker_ptr<T>> * raw_queue){
204 static size_t id() noexcept {
205 static const size_t identifier {StatePoolBase::next()};
219 if(available_tracker_queue_->empty()) {
220 state_tracker_ptr<T> state_tracker_unit(
223 return state_tracker_unit;
229 state_tracker_ptr<T> state_tracker_unit {
230 std::move(available_tracker_queue_->front())};
231 available_tracker_queue_->pop_front();
232 return state_tracker_unit;
241 state_tracker_ptr<T> tracker_unique_ptr(raw_ptr,
250 tracker_unique_ptr->updateLastDeltas();
253 available_tracker_queue_->push_back(std::move(tracker_unique_ptr));
262 std::unique_ptr<std::deque<state_tracker_ptr<T>>> queue_ptr(raw_queue);
268 std::fstream data_file(tracking_filename_, std::ios_base::app);
273 pool_existence_reference_.reset();
276 std::vector<sparta::Scheduler::Tick> stats_vector(
277 static_cast<uint64_t
>(T::__LAST) + 1, 0);
280 std::for_each(queue_ptr->begin(), queue_ptr->end(),
281 [&stats_vector](
const state_tracker_ptr<T> & item) {
284 const StateSet<T> & state_set {item->getStateSet()};
285 sparta_assert(state_set.state_delta_set.size() == stats_vector.size());
288 std::transform(stats_vector.begin(), stats_vector.end(),
289 state_set.state_delta_set.begin(), stats_vector.begin(),
290 std::plus<sparta::Scheduler::Tick>()); });
296 std::vector<double> avg_stats_vector(
297 static_cast<uint64_t
>(T::__LAST) + 1, 0);
299 std::transform(stats_vector.begin(), stats_vector.end(),
300 avg_stats_vector.begin(),
302 return static_cast<double>(item) /
303 static_cast<double>(instance_count_); });
306 std::string name_string;
309 extractEnumTypeAsString_(__PRETTY_FUNCTION__,
"[",
"]", name_string);
312 data_file <<
"Enum Class Name : " << name_string <<
"\n"
313 <<
"Total State Tracker Units used : " << instance_count_ <<
"\n"
314 <<
"Aggregate Residency Stats: \n";
316 std::vector<std::string> enum_name_strings;
319 fillHistogramLabels_<T>(enum_name_strings);
325 for(
size_t i = 0; i < stats_vector.size() - 1; ++i) {
326 data_file << enum_name_strings[i] <<
" : " << stats_vector[i] <<
"\n";
329 data_file <<
"\n\nAverage Residency Stats: \n";
335 for(
size_t i = 0; i < avg_stats_vector.size() - 1; ++i) {
336 data_file << enum_name_strings[i] <<
" : " << avg_stats_vector[i] <<
"\n";
345 uint64_t instance_count_;
352 std::shared_ptr<StatePool<T>> pool_existence_reference_;
356 std::string tracking_filename_;
360 tracker_queue_ptr<T> available_tracker_queue_;
365 bool extractEnumTypeAsString_(
const std::string & source,
366 const std::string & start,
367 const std::string & end,
368 std::string & result) {
374 constexpr uint16_t redundant_char_length {9};
376 std::size_t start_index = source.find(start);
377 if(start_index == std::string::npos) {
381 start_index += start.length();
383 const std::string::size_type end_index =
384 source.find(end, start_index);
386 if(end_index == std::string::npos) {
390 result = source.substr(start_index, end_index - start_index);
391 result.erase(0, redundant_char_length);
401 typename std::enable_if<has_ostream_operator<U>::value,
void>::type
402 fillHistogramLabels_(std::vector<std::string> & enum_name_strings) {
403 typedef typename std::underlying_type<U>::type enumType;
404 constexpr enumType last_index =
static_cast<enumType
>(U::__LAST);
405 enum_name_strings.reserve(last_index);
406 std::stringstream ss;
407 for(enumType e = 0; e < last_index; ++e) {
408 auto val =
static_cast<U
>(e);
410 enum_name_strings.emplace_back(ss.str());
423 typename std::enable_if<!has_ostream_operator<U>::value,
void>::type
424 fillHistogramLabels_(std::vector<std::string> & enum_name_strings) {
425 typedef typename std::underlying_type<U>::type enumType;
426 constexpr enumType last_index =
static_cast<enumType
>(U::__LAST);
427 enum_name_strings.resize(last_index);
448 return state_pool_manager;
455 is_tracking_enabled_ =
true;
465 unique_pool_type_map_.clear();
477 if(__builtin_expect(is_tracking_enabled_, 0)) {
478 return getStatePool_<T>()->getNewStateTrackerUnit(scheduler_);
496 is_tracking_enabled_ =
true;
497 std::fstream data_file(filename, std::ios::out | std::ios_base::trunc);
499 tracking_filename_ = filename;
504 scheduler_ = scheduler;
509 bool is_tracking_enabled_ {
false};
511 using CachedBase = std::map<size_t, std::unique_ptr<StatePoolBase>>;
512 CachedBase unique_pool_type_map_;
513 std::string tracking_filename_;
523 inline StatePool<T> * getStatePool_() {
524 static StatePool<T> * state_pool {
nullptr};
532 if(__builtin_expect(state_pool !=
nullptr, 1)) {
541 const size_t identifier = StatePool<T>::id();
543 unique_pool_type_map_[identifier].reset(
544 new StatePool<T>(tracking_filename_));
552 state_pool =
static_cast<StatePool<T> *
>(
553 unique_pool_type_map_[identifier].get());
563 template<
typename EnumT>
566 typename std::underlying_type<EnumT>::type> active_state_index;
568 std::vector<sparta::Scheduler::Tick> state_delta_set;
570 explicit StateSet(
const uint64_t num_states) :
571 active_state_starting_time(0),
572 state_delta_set(std::vector<sparta::Scheduler::Tick>(num_states, 0)) {}
577 active_state_index(rval.active_state_index),
578 active_state_starting_time(rval.active_state_starting_time),
579 state_delta_set(std::move(rval.state_delta_set)) {}
586 template<
typename EnumT>
590 scheduler_instance_(scheduler),
591 time_assigned_(scheduler_instance_->getCurrentTick()),
593 static_cast<uint64_t
>(EnumT::__LAST) + 1)) {}
598 scheduler_instance_(rval.scheduler_instance_),
599 time_assigned_(rval.time_assigned_),
600 state_set_(rval.state_set_) {
601 rval.scheduler_instance_ =
nullptr;
606 template<
typename EnumType>
609 scheduler_instance_->getCurrentTick();
610 typename std::underlying_type<EnumT>::type state_index =
611 static_cast<typename std::underlying_type<EnumT>::type
>(state_enum);
612 if(__builtin_expect(state_set_.active_state_index.isValid(), 1)){
613 typename std::underlying_type<EnumT>::type active_state_in_set =
614 state_set_.active_state_index.getValue();
615 if(active_state_in_set == state_index){
621 state_set_.state_delta_set.size());
622 state_set_.active_state_index = state_index;
623 state_set_.active_state_starting_time = current_time;
628 template<
typename EnumType>
630 typename std::underlying_type<EnumT>::type state_index =
631 static_cast<typename std::underlying_type<EnumT>::type
>(state_enum);
633 typename std::underlying_type<EnumT>::type active_state_in_set =
634 state_set_.active_state_index.getValue();
637 state_set_.active_state_index.clearValid();
638 state_set_.active_state_starting_time = 0;
646 if(__builtin_expect(state_set_.active_state_index.isValid(), 1)) {
648 scheduler_instance_->getCurrentTick();
649 typename std::underlying_type<EnumT>::type active_state_in_set =
650 state_set_.active_state_index.getValue();
651 state_set_.state_delta_set[active_state_in_set] +=
652 current_time - state_set_.active_state_starting_time;
653 state_set_.active_state_index.clearValid();
654 state_set_.active_state_starting_time = 0;
661 return scheduler_instance_->getCurrentTick() -
662 state_set_.active_state_starting_time;
670 inline void endTimerState_() noexcept {
672 scheduler_instance_->getCurrentTick();
673 typename std::underlying_type<EnumT>::type active_state_in_set =
674 state_set_.active_state_index.
getValue();
675 state_set_.state_delta_set[active_state_in_set] +=
676 current_time - state_set_.active_state_starting_time;
681 StateSet<EnumT> state_set_ {};
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
File that defines a ValidValue.
A class that lets you schedule events now and in the future.
uint64_t Tick
Typedef for our unit of time.
This is the polymorphic base class for the StatePool template class.
This is a Singleton class which manages all the different StatePool.
static StatePoolManager & getInstance()
This is not a Thread Safe method.
void enableTracking()
This method needs to be public to.
void setTrackingFilename(const std::string &filename)
This filename is the name of the State Tracking File as.
state_tracker_ptr< T > dispatchNewTracker()
This is the public API to get new tracker units.
void setScheduler(Scheduler *scheduler)
Set the scheduler used by the Simulation class.
void flushPool()
This method starts the teardown of all the different.
StatePool class template is templatized on the enum type we are tracking.
StatePool(const std::string &tracking_filename)
A file name is a must when constructing StatePool.
static size_t id() noexcept
Method which associates this StatePool template instantiation.
void transferQueueData(std::deque< state_tracker_ptr< T > > *raw_queue)
This is the main method, the custom deleter of the Tracker Queues.
state_tracker_ptr< T > getNewStateTrackerUnit(Scheduler *scheduler) noexcept
Method which gets invoked whenever a demand for a new.
void releaseToPool(StateTrackerUnit< T > *&raw_ptr)
Method which is invoked when individual State Tracker Units.
StatePool()=delete
The Default Ctor is deleted because StatePool cannot be created.
This is the actual Lightweight Tracker class which does the.
sparta::Scheduler::Tick getActiveTime() const
void updateLastDeltas() noexcept
This method is called right before we send away a.
void startState(const EnumType &state_enum)
This method starts the timer on this particular value of.
void endState(const EnumType &state_enum)
This method stops the timer on this particular value of.
Provides a wrapper around a value to ensure that the value is assigned.
const value_type & getValue() const
Get the value - const version.
char no
Typedef a char array of size one.
char yes[2]
Typedef a char array of size two.
yes & test(std::ostream &)
If the class does have an << operator overloaded,.
no operator<<(std::ostream const &, fallback const &)
Declare a dummy << operator which operates on.
Macros for handling exponential backoff.
This is the Calculation Engine unit inside each State Tracker Unit.
Custom Deleter of individual State Tracker Units.
StateTrackerDeleter(const std::weak_ptr< StatePool< T > > &weak_pool)
Construct the internal weak_ptr from a shared_ptr.
A fallback struct which can create itself.