diff --git a/Makefile.am b/Makefile.am index 2349b5b..8f68f25 100644 --- a/Makefile.am +++ b/Makefile.am @@ -183,6 +183,7 @@ src_backend_libbackend_la_SOURCES = \ src/backend/plugin_manager.cc \ src/backend/policy_parameters.cc \ src/backend/process.cc \ + src/backend/process_statistics.cc \ src/backend/ready_queue.cc \ src/backend/request.cc \ src/backend/resource.cc \ @@ -275,6 +276,7 @@ noinst_HEADERS += \ src/backend/dynamic_schedulable.hh \ src/backend/dynamic_sub_request.hh \ src/backend/dynamic_thread.hh \ + src/backend/process_statistics.hh \ src/backend/static_process.hh \ src/backend/static_request.hh \ src/backend/static_resource.hh \ diff --git a/src/backend/concrete_statistics.cc b/src/backend/concrete_statistics.cc index 11db894..6293f77 100644 --- a/src/backend/concrete_statistics.cc +++ b/src/backend/concrete_statistics.cc @@ -19,16 +19,55 @@ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "concrete_statistics.hh" +#include "sgpemv2/simulation.hh" +#include "sgpemv2/history.hh" +#include "sgpemv2/environment.hh" +#include "sgpemv2/schedulable.hh" +#include "sgpemv2/process.hh" +#include "sgpemv2/thread.hh" +#include "thread_statistics.hh" +#include "process_statistics.hh" + +#include using namespace sgpem; +using namespace std; ConcreteStatistics::ConcreteStatistics() {} -std::vector -ConcreteStatistics::get_schedulable_statistics(const int& instant) const +vector +ConcreteStatistics::get_process_statistics(const int& instant) const { - return std::vector(); + //vector thread_stats; + vector rit; + + const History& hist = Simulation::get_instance().get_history(); + const Environment& env = hist.get_environment_at(instant); + const vector procs = env.get_processes(); + + //first calculate all THREADS statistics + for (uint i_p=0; i_p < procs.size(); i_p++) + { + /*const vector threads = procs[i_p]->get_threads(); + for (uint i_t = 0; i_t < threads.size(); i_t++) + { + ThreadStatistics* s = new ThreadStatistics(threads[i_t], instant); + thread_stats.push_back(s); + rit.push_back(s); + } + */ + rit.push_back(ProcessStatistics(procs[i_p], instant)); + } + /* + //then calculate PROCESSES statistics USING the previous ones + for (uint i_p=0; i_p < procs.size(); i_p++) + { + SchedulableStatistics* s = new ProcessStatistics(procs[i_p], instant, &thread_stats); + rit.push_back(s); + } + */ + return rit; } diff --git a/src/backend/concrete_statistics.hh b/src/backend/concrete_statistics.hh index 818d92c..c597068 100644 --- a/src/backend/concrete_statistics.hh +++ b/src/backend/concrete_statistics.hh @@ -36,7 +36,7 @@ namespace sgpem public: ConcreteStatistics(); - std::vector get_schedulable_statistics(const int& instant) const; + std::vector get_process_statistics(const int& instant) const; }; diff --git a/src/backend/process_statistics.cc b/src/backend/process_statistics.cc new file mode 100644 index 0000000..0d8bef5 --- /dev/null +++ b/src/backend/process_statistics.cc @@ -0,0 +1,193 @@ +// src/backend/process_statistics.cc - Copyright 2005, 2006, University +// of Padova, dept. of Pure and Applied +// Mathematics +// +// This file is part of SGPEMv2. +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// SGPEMv2 is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with SGPEMv2; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#include "process_statistics.hh" +#include "sgpemv2/simulation.hh" +#include "sgpemv2/history.hh" +#include "sgpemv2/environment.hh" +#include "sgpemv2/schedulable.hh" + +#include + +using namespace std; +using namespace sgpem; + +/** + The constructor executes all calculations examinating or only the Thred object, + or the whole History + +*/ +ProcessStatistics::ProcessStatistics(const Process* core, const int& instant): _core(core) +{ + // To calculate Process statistics we need the respective thread statistics + // Calculate them! + + vector threads = core->get_threads(); + for (uint i_t = 0; i_t < threads.size(); i_t++) + _threads_stats.push_back(ThreadStatistics(threads[i_t], instant)); + + //inizialize variables + _total_inactivity = 0; + _execution_time = 0; + _response_time = -1; + _turn_around = 0; + _resource_usage_time = 0; + _resource_waitings_time = 0; + _average_response_time = 0; + int min_reponse = -1; //useful for _response_time + int arrived_threads = 0; //useful for _average_response_time + bool someone_began = false; //useful for _response_time + + //iterate through threads statistics + vector::iterator i; + for(i = _threads_stats.begin(); i != _threads_stats.end(); i++) + { + Thread* t = const_cast((*i).get_core()); + if (t->get_process() == *core) + { //found a thread belonging to "core" + + _execution_time += (*i).get_execution_time(); + _resource_usage_time += (*i).get_resource_usage_time(); + + if ((*i).get_response_time() != -1) + { + _average_response_time += (*i).get_response_time(); + arrived_threads++; + } + + if ((*i).get_response_time() != -1 && someone_began == false) + { + someone_began = true; + min_reponse = (*i).get_response_time(); + } + + if(someone_began && (*i).get_response_time() != -1 && (*i).get_response_time() + (*i).get_real_arrival_time() < min_reponse) + min_reponse = (*i).get_response_time() + (*i).get_real_arrival_time(); + + if ((*i).get_real_arrival_time() + (*i).get_execution_time() + (*i).get_total_inactivity() > _turn_around) + _turn_around = (*i).get_real_arrival_time() + (*i).get_execution_time() + (*i).get_total_inactivity(); + } + } + + //******* AAARRRGGHH!!! + //We have to iterate the whole History ONLY to retreive _resource_waitings_time !! + // + const History& hist = Simulation::get_instance().get_history(); + for (int time=0; time < instant; time++) + { + const Environment& env = hist.get_environment_at(time); + const vector procs = env.get_processes(); + + for (uint i_p=0; i_p < procs.size(); i_p++) + if (*procs[i_p] == *core && procs[i_p]->get_state() == Schedulable::state_blocked) + _resource_waitings_time++; + } + + + + //set other variables + if(core->get_total_cpu_time() != 0) + _execution_progress = (_execution_time*100) / core->get_total_cpu_time(); + else + _execution_progress = 0; + + _total_inactivity = _turn_around - _execution_time; + + if (_turn_around == 0) + _efficency = -1; + else + _efficency = (_execution_time*100)/_turn_around; + + _response_time = min_reponse; + + if (arrived_threads != 0) + _average_response_time = (float)((int)((_average_response_time/arrived_threads)*100))/100; +} + + +ProcessStatistics::~ProcessStatistics() +{ +} + +int +ProcessStatistics::get_execution_time() const +{ + return _execution_time; +} + +int +ProcessStatistics::get_execution_progress() const +{ + return _execution_progress; +} + +int +ProcessStatistics::get_total_inactivity() const +{ + return _total_inactivity; +} + +int +ProcessStatistics::get_response_time() const +{ + return _response_time; +} + +int +ProcessStatistics::get_turn_around() const +{ + return _turn_around; +} + +int +ProcessStatistics::get_efficency() const +{ + return _efficency; +} + +int +ProcessStatistics::get_resource_usage_time() const +{ + return _resource_usage_time; +} + +int +ProcessStatistics::get_resource_waitings_time() const +{ + return _resource_waitings_time; +} + +float +ProcessStatistics::get_average_response_time() const +{ + return _average_response_time; +} + +const Process* +ProcessStatistics::get_core() const +{ + return _core; +} + +vector +ProcessStatistics::get_threads_statistics() const +{ + return _threads_stats; +} diff --git a/src/backend/process_statistics.hh b/src/backend/process_statistics.hh new file mode 100644 index 0000000..70fc578 --- /dev/null +++ b/src/backend/process_statistics.hh @@ -0,0 +1,64 @@ +// src/backend/process_statistics.hh - Copyright 2005, 2006, University +// of Padova, dept. of Pure and Applied +// Mathematics +// +// This file is part of SGPEMv2. +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// SGPEMv2 is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with SGPEMv2; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#ifndef PROCESS_STATISTICS_HH +#define PROCESS_STATISTICS_HH 1 + +#include "config.h" + +#include "sgpemv2/schedulable_statistics.hh" +#include "sgpemv2/process.hh" +#include "thread_statistics.hh" +#include + +#include + + +namespace sgpem +{ + class ProcessStatistics : public SchedulableStatistics + { + public: + ProcessStatistics(const Process* core, const int& instant); + ~ProcessStatistics(); + + int get_execution_time() const; + int get_execution_progress() const; + int get_total_inactivity() const; + int get_response_time() const; + float get_average_response_time() const; + int get_turn_around() const; + int get_efficency() const; + int get_resource_usage_time() const; + int get_resource_waitings_time() const; + + const Process* get_core() const; + + std::vector get_threads_statistics() const; + + private: + + const Process* _core; + float _average_response_time; + std::vector _threads_stats; + }; +} + +#endif diff --git a/src/backend/sgpemv2/schedulable_statistics.hh b/src/backend/sgpemv2/schedulable_statistics.hh index 4cf6782..c03cfd1 100644 --- a/src/backend/sgpemv2/schedulable_statistics.hh +++ b/src/backend/sgpemv2/schedulable_statistics.hh @@ -35,15 +35,28 @@ namespace sgpem virtual ~SchedulableStatistics(); virtual int get_execution_time() const =0; - /*virtual int get_total_waitings() const =0; + virtual int get_execution_progress() const =0; + virtual int get_total_inactivity() const =0; virtual int get_response_time() const =0; virtual int get_turn_around() const =0; - */ + virtual int get_efficency() const =0; + virtual int get_resource_usage_time() const =0; + virtual int get_resource_waitings_time() const =0; + virtual const Schedulable* get_core() const =0; protected: - + SchedulableStatistics(); + + int _execution_time; + int _execution_progress; + int _total_inactivity; + int _response_time; + int _turn_around; + int _efficency; + int _resource_usage_time; + int _resource_waitings_time; }; } diff --git a/src/backend/sgpemv2/statistics.hh b/src/backend/sgpemv2/statistics.hh index 00b89e9..27a751e 100755 --- a/src/backend/sgpemv2/statistics.hh +++ b/src/backend/sgpemv2/statistics.hh @@ -23,7 +23,7 @@ #include "config.h" #include "sgpemv2/templates/singleton.hh" -#include "schedulable_statistics.hh" +#include "process_statistics.hh" #include #include @@ -36,16 +36,16 @@ namespace sgpem class SG_DLLEXPORT Statistics : public Singleton { public: - //typedef std::vector SchedulableStatistics; + virtual ~Statistics() = 0; static Statistics& get_instance(); - virtual std::vector get_schedulable_statistics(const int& instant) const = 0; + virtual std::vector get_process_statistics(const int& instant) const = 0; - protected: - - Statistics(); // Constructor + protected: + + Statistics(); // Constructor }; } diff --git a/src/backend/thread_statistics.cc b/src/backend/thread_statistics.cc index efb2bc0..f1dcff8 100644 --- a/src/backend/thread_statistics.cc +++ b/src/backend/thread_statistics.cc @@ -22,15 +22,112 @@ #include "sgpemv2/simulation.hh" #include "sgpemv2/history.hh" #include "sgpemv2/environment.hh" +#include "sgpemv2/schedulable.hh" +#include "sgpemv2/process.hh" +#include "sgpemv2/thread.hh" +#include "sgpemv2/resource.hh" +#include "sgpemv2/request.hh" +#include - +using namespace std; using namespace sgpem; +/** + The constructor executes all calculations examinating or only the Thread object + or the whole History + +*/ ThreadStatistics::ThreadStatistics(const Thread* core, const int& instant): _core(core) { + //initializations + _total_inactivity = 0; + _execution_time = 0; + _response_time = -1; + _real_arrival_time = -1; + _turn_around = 0; + _resource_usage_time = 0; + _resource_waitings_time = 0; + bool iniziato = false; //useful for _response_time + + const History& hist = Simulation::get_instance().get_history(); //prendo la lista delle risorse + const map res = hist.get_environment_at(0).get_resources(); + + //****** iterate through HISTORY to retreive informations + for (int time=0; time < instant; time++) + { + const Environment& env = hist.get_environment_at(time); + const vector procs = env.get_processes(); + + //looks for the process that owns this thread + for (uint i_p=0; i_p < procs.size(); i_p++) + { + const vector threads = procs[i_p]->get_threads(); + //looks for the thread "core" + for (uint i_t = 0; i_t < threads.size(); i_t++) + { + if ( (*threads[i_t]) == (*core) ) //FOUND!! + { + if (threads[i_t]->get_state() == Schedulable::state_running) + { + iniziato = true; + if( _response_time == -1) //arrives and runs immediately + { + _response_time = 0; + _real_arrival_time = time - procs[i_p]->get_arrival_time() -1; + } + _execution_time++; + } + if (threads[i_t]->get_state() != Schedulable::state_future && + threads[i_t]->get_state() != Schedulable::state_terminated) + { + _turn_around++; + if (!iniziato && _response_time == -1) //arrives and doesn't run + { + _response_time = 0; + _real_arrival_time = time - procs[i_p]->get_arrival_time() -1; + } + } + if (threads[i_t]->get_state() == Schedulable::state_blocked + || threads[i_t]->get_state() == Schedulable::state_ready) + { + _total_inactivity++; + if (!iniziato && _response_time != -1) + _response_time++; + + if (threads[i_t]->get_state() == Schedulable::state_blocked) + _resource_waitings_time++; + } + } + } //threads + } //procs + + + //for each resource check requests at this istant: + //if the request of this thread is allocated then increase _resource_usage_time + Environment::Resources::const_iterator res_iter = res.begin(); + while(res_iter != res.end()) + { + Environment::resource_key_t key = (*res_iter).first; + vector req = env.get_request_queue(key); + for (uint i_r=0; i_r < req.size(); i_r++) + if( (*req[i_r]).get_request().get_thread() == (*core) && (*req[i_r]).get_state() == Request::state_allocated) + _resource_usage_time++; + + res_iter++; + } + + }//istants + + //set other variables + _execution_progress = (100*_execution_time)/core->get_total_cpu_time(); + if (_turn_around == 0) + _efficency = -1; + else + _efficency = (_execution_time*100)/_turn_around; } + ThreadStatistics::~ThreadStatistics() { } @@ -38,9 +135,56 @@ ThreadStatistics::~ThreadStatistics() int ThreadStatistics::get_execution_time() const { - return 99; + return _execution_time; } +int +ThreadStatistics::get_execution_progress() const +{ + return _execution_progress; +} + +int +ThreadStatistics::get_total_inactivity() const +{ + return _total_inactivity; +} + +int +ThreadStatistics::get_response_time() const +{ + return _response_time; +} + +int +ThreadStatistics::get_turn_around() const +{ + return _turn_around; +} + +int +ThreadStatistics::get_efficency() const +{ + return _efficency; +} + +int +ThreadStatistics::get_resource_usage_time() const +{ + return _resource_usage_time; +} + +int +ThreadStatistics::get_resource_waitings_time() const +{ + return _resource_waitings_time; +} + +int +ThreadStatistics::get_real_arrival_time() const +{ + return _real_arrival_time; +} const Thread* ThreadStatistics::get_core() const diff --git a/src/backend/thread_statistics.hh b/src/backend/thread_statistics.hh index 106a971..dad1652 100644 --- a/src/backend/thread_statistics.hh +++ b/src/backend/thread_statistics.hh @@ -18,8 +18,8 @@ // along with SGPEMv2; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -#ifndef CONCRETE_STATISTICS_HH -#define CONCRETE_STATISTICS_HH 1 +#ifndef THREAD_STATISTICS_HH +#define THREAD_STATISTICS_HH 1 #include "config.h" @@ -37,14 +37,22 @@ namespace sgpem ThreadStatistics(const Thread* core, const int& instant); ~ThreadStatistics(); - int get_execution_time() const; - /* int get_total_waitings() const; - int get_response_time() const; - int get_turn_around() const; - */ const Thread* get_core() const; + int get_execution_time() const; + int get_execution_progress() const; + int get_total_inactivity() const; + int get_response_time() const; + int get_turn_around() const; + int get_efficency() const; + int get_resource_usage_time() const; + int get_resource_waitings_time() const; + + const Thread* get_core() const; + + int get_real_arrival_time() const; //useful for ProcessStatistics private: const Thread* _core; + int _real_arrival_time; }; } diff --git a/src/simulation_widget.cc b/src/simulation_widget.cc index 8c0b3a6..fbff192 100644 --- a/src/simulation_widget.cc +++ b/src/simulation_widget.cc @@ -30,6 +30,12 @@ #include +//********************** PROVE di STATISTICS +#include +#include "backend/sgpemv2/statistics.hh" +#include "backend/thread_statistics.hh" +using namespace std; +//************************* #ifndef NDEBUG #include @@ -121,7 +127,7 @@ SimulationWidget::update(const Simulation& /* changed_simulation */ ) } void -SimulationWidget::update(const History& /* changed_history */ ) +SimulationWidget::update(const History& changed_history ) { // Force redraw _last_drawn = 0; @@ -130,7 +136,47 @@ SimulationWidget::update(const History& /* changed_history */ ) // count_elements(); resize_redraw(); - + + + cout << "\n\n****** STATS BEGIN*******\n"; + + vector p_stats = Statistics::get_instance().get_process_statistics(changed_history.get_front()); + + cout << "\n INSTANT = " << (int)changed_history.get_front()-1 << "\n\n"; + + + for(int i_p = 0; i_p < p_stats.size(); i_p++) + { + cout << "\n\n== " << p_stats[i_p].get_core()->get_name().c_str() << + "\t\tRUN= " << p_stats[i_p].get_execution_time() << + "\tPERC= " << p_stats[i_p].get_execution_progress() << "%"<< + "\tTURN= " << p_stats[i_p].get_turn_around() << + "\tRISP= " << p_stats[i_p].get_response_time() << + "\t~RISP= " << p_stats[i_p].get_average_response_time() << + "\tEFF= " << p_stats[i_p].get_efficency() << "%" << + "\tINACTIVE= " << p_stats[i_p].get_total_inactivity() << + "\tRIS_USAGE= " << p_stats[i_p].get_resource_usage_time() << + "\tRIS_BLOCK= " << p_stats[i_p].get_resource_waitings_time() ; + + cout << "\n |"; + + vector t_stats = p_stats[i_p].get_threads_statistics(); + + for(int i_t = 0; i_t < t_stats.size(); i_t++) + cout << "\n |-- " << t_stats[i_t].get_core()->get_name().c_str() << + "\t\tRUN= " << t_stats[i_t].get_execution_time() << + "\tPERC= " << t_stats[i_t].get_execution_progress() << "%" << + "\tINACTIVE= " << t_stats[i_t].get_total_inactivity() << + "\tRISP= " << t_stats[i_t].get_response_time() << + "\tTURN= " << t_stats[i_t].get_turn_around() << + "\tEFF= " << t_stats[i_t].get_efficency() << "%" << + "\tRIS_USAGE= " << t_stats[i_t].get_resource_usage_time() << + "\tRIS_BLOCK= " << t_stats[i_t].get_resource_waitings_time(); + + } + + cout << "\n\n****** STATS END*******\n"; + }