00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef STATS_H1_
00039 #define STATS_H1_
00040 #include <stdlib.h>
00041 #include <string>
00042 #include <sstream>
00043 #include <queue>
00044 #include <limits>
00045 #include "wmp_config.h"
00046
00047 #include "core/include/frames.h"
00048 #include "core/interface/Msg.h"
00049 #include <string.h>
00050 #include "misc.h"
00051
00052 template<class T>
00053 std::string toString(T val, int precision = -1) {
00054 std::ostringstream oss;
00055 oss << std::fixed;
00056 if (precision != -1) {
00057 oss.precision(precision);
00058 }
00059 oss << val;
00060 return oss.str();
00061 }
00062 ;
00063
00064 template<class T>
00065 class CStats {
00066
00067 protected:
00068 int id;
00069 bool id_valid;
00070 std::string name, unit;
00071 T val, sum;
00072 bool valid;
00073 public:
00074 T bookmark, aux1, aux2, partial, total;
00075 long long llaux;
00076 struct stat_t {
00077 T value;
00078 int pos;
00079 };
00080
00081 virtual void init(){
00082 valid=id_valid=false;
00083 sum=id=val=aux1=aux2=bookmark=llaux=partial=total=0;
00084 }
00085
00086 CStats() {
00087 init();
00088 this->name="xxx";
00089 this->unit="yyy";
00090 }
00091 CStats(std::string & name) {
00092 this->name = name;
00093 init();
00094 }
00095
00096 std::string & getName() {
00097 return name;
00098 }
00099
00100 void set(T val) {
00101 this->val = val;
00102 }
00103
00104 T get() {
00105 return this->val;
00106 }
00107 bool isValid() {
00108 return valid;
00109 }
00110
00111 virtual bool new_value(){
00112 partial++;
00113 return true;
00114 }
00115
00116 virtual bool new_touch(){
00117 total++;
00118 return true;
00119 }
00120
00121 double getPercentage(){
00122 if (total!=0){
00123 return (100.0*(double) partial / (double) total);
00124 }else{
00125 return 0;
00126 }
00127 }
00128
00129 std::string & getUnit() {
00130 return unit;
00131 }
00132 };
00133
00134 template<class T>
00135 class PlainCStats: public CStats<T> {
00136 typedef typename CStats<T>::stat_t stat_t;
00137 public:
00138 virtual void init(){
00139 CStats<T>::init();
00140 }
00141 PlainCStats() : CStats<T>() {
00142 init();
00143 }
00144 PlainCStats(std::string name,std::string unit):CStats<T>(name) {
00145 this->unit = unit;
00146 init();
00147 }
00148
00149 void new_value(T value) {
00150 CStats<T>::new_value();
00151 this->valid = true;
00152 this->sum+=value;
00153 }
00154 T getSum() {
00155 return this->sum;
00156 }
00157
00158 };
00159
00160 template<class T>
00161 class MaxMinCStats: public CStats<T> {
00162 typedef typename CStats<T>::stat_t stat_t;
00163 protected:
00164 double mean;
00165 stat_t max, min;
00166 int idx;
00167 std::vector<T> v;
00168 std::vector<T> vpos;
00169 public :
00170 virtual void init() {
00171 CStats<T>::init();
00172 max.value = std::numeric_limits<T>::min();
00173 min.value = std::numeric_limits<T>::max();
00174 max.pos = -1;
00175 min.pos = -1;
00176 idx = 0;
00177 mean = 0;
00178 v.clear();
00179 vpos.clear();
00180 }
00181
00182 void reset(){
00183 max.value = std::numeric_limits<T>::min();
00184 min.value = std::numeric_limits<T>::max();
00185 max.pos = -1;
00186 min.pos = -1;
00187 idx = 0;
00188 mean = 0;
00189 }
00190
00191 MaxMinCStats():CStats<T>() {
00192 init();
00193 }
00194 MaxMinCStats(std::string name, std::string unit):CStats<T>(name) {
00195 this->unit = unit;
00196 init();
00197 }
00198 void new_value(T value, int pos) {
00199 v.push_back(value);
00200 vpos.push_back(pos);
00201 this->valid = true;
00202 if (value > max.value) {
00203 max.value=value;
00204 max.pos = pos;
00205 }
00206 if (value < min.value) {
00207 min.value = value;
00208 min.pos = pos;
00209 }
00210 idx++;
00211 this->sum += value;
00212 }
00213 int getCount() {
00214 return idx;
00215 }
00216
00217 T get(int i){
00218 return v.at(i);
00219 }
00220 T getPos(int i){
00221 return vpos.at(i);
00222 }
00223 stat_t getMax() {
00224 return max;
00225 }
00226 T getMaxVal(){
00227 return max.value;
00228 }
00229
00230 T getMinVal(){
00231 return min.value;
00232 }
00233
00234 T getInterval() {
00235 return (max.value - min.value);
00236 }
00237 stat_t getMin() {
00238 return min;
00239 }
00240 virtual double getMean() {
00241 if (idx!=0){
00242 return (double) this->sum / (double) idx;
00243 } else{
00244 return 0;
00245 }
00246 }
00247 };
00248
00249 template<class T>
00250 class IntervalCStats: public MaxMinCStats<T> {
00251 typedef typename CStats<T>::stat_t stat_t;
00252 stat_t best_max;
00253 stat_t best_min;
00254 int best_count;
00255 public:
00256 virtual void init(){
00257 MaxMinCStats<T>::init();
00258 best_count=0;
00259 }
00260
00261 IntervalCStats():MaxMinCStats<T>() {
00262 init();
00263 }
00264 IntervalCStats(std::string name, std::string unit):MaxMinCStats<T>(name, unit) {
00265 init();
00266 }
00267 void reset() {
00268 done();
00269 MaxMinCStats<T>::reset();
00270 }
00271 void done(){
00272 if (this->idx > best_count) {
00273 best_max = this->max;
00274 best_min = this->min;
00275 best_count = this->idx;
00276 }
00277 }
00278
00279 stat_t getIntervalMax() {
00280 return best_max;
00281 }
00282 stat_t getIntervalMin() {
00283 return best_min;
00284 }
00285 int getIntervalCount() {
00286 return best_count;
00287 }
00288 };
00289
00290 template<class T, class P>
00291 class ThingOverTimeCStats: public MaxMinCStats<T> {
00292 typedef typename CStats<T>::stat_t stat_t;
00293 P things;
00294 public:
00295 virtual void init(){
00296 MaxMinCStats<T>::init();
00297 things = 0;
00298 }
00299 ThingOverTimeCStats():MaxMinCStats<T>() {
00300 this->init();
00301 }
00302 ThingOverTimeCStats(std::string name, std::string unit):MaxMinCStats<T>(name, unit) {
00303 this->init();
00304 }
00305 void new_thing(T size) {
00306 this->things+=size;
00307 }
00308 void new_time(T time) {
00309 this->new_value(time,0);
00310 }
00311 double getToT() {
00312 if ((this->max.value - this->min.value) != 0){
00313 return (double)(((double) things) / ((double) (this->max.value - this->min.value)));
00314 } else{
00315 return 0;
00316 }
00317 }
00318 virtual double getMean() {
00319 return getToT();
00320 }
00321 };
00322
00323 #include <vector>
00324
00325 template<class T>
00326 class ListCStats: public CStats<T> {
00327 typedef typename CStats<T>::stat_t stat_t;
00328 protected:
00329 std::vector<stat_t> v;
00330 std::string child_name;
00331 public:
00332 virtual void init(){
00333 CStats<T>::init();
00334 v.clear();
00335 }
00336 ListCStats(std::string name, std::string child_name) : CStats<T>(name) {
00337 this->child_name = child_name;
00338 init();
00339 }
00340 ListCStats() : CStats<T>() {
00341 init();
00342 }
00343 void new_value(T value, int pos) {
00344 CStats<T>::new_value();
00345 this->valid = true;
00346 stat_t elem;
00347 elem.value=value;
00348 elem.pos=pos;
00349 v.push_back(elem);
00350 }
00351
00352 virtual int getCount() {
00353 return v.size();
00354 }
00355
00356 virtual stat_t getElem(int idx) {
00357 stat_t elem = v.at(idx);
00358 return elem;
00359 }
00360
00361 std::string & getChildName() {
00362 return child_name;
00363 }
00364
00365 };
00366 template<class T>
00367 class DoubleListCStats: public ListCStats<T> {
00368 typedef typename CStats<T>::stat_t stat_t;
00369
00370 public:
00371 DoubleListCStats(std::string name, std::string child_name) : ListCStats<T>(name,child_name) {
00372 }
00373 DoubleListCStats() : ListCStats<T>() {
00374 }
00375
00376 void new_value(T value1, int pos1, T value2, int pos2) {
00377 ListCStats<T>::new_value(value1,pos1);
00378 ListCStats<T>::new_value(value2,pos2);
00379 }
00380 void getElem(int pos, stat_t & v1, stat_t & v2) {
00381 v1 = ListCStats<T>::getElem(pos*2);
00382 v2 = ListCStats<T>::getElem(pos*2+1);
00383 }
00384 virtual int getCount() {
00385 return ListCStats<T>::getCount()/2;
00386 }
00387 stat_t getElem(int idx) {
00388 stat_t elem = ListCStats<T>::getElem(idx*2);
00389 return elem;
00390 }
00391 };
00392
00393 template<class Q>
00394 class MultiCStats {
00395 protected:
00396 std::string name, child_name;
00397 std::vector<Q> v2;
00398 public:
00399 MultiCStats(std::string name, std::string child_name, int nfields) {
00400 this->child_name = child_name;
00401 this->name = name;
00402 v2.resize(nfields);
00403 }
00404 Q & operator[](int id) {
00405 return v2.at(id);
00406 }
00407
00408 Q & get(int id) {
00409 return v2.at(id);
00410 }
00411 std::string & getChildName() {
00412 return child_name;
00413 }
00414 std::string & getName() {
00415 return name;
00416 }
00417 };
00418
00419 #include <map>
00420
00421 class StatsFlow {
00422 struct Interval {
00423 int begin;
00424 int end;
00425 int dest;
00426 int rescheduled;
00427 int prio;
00428 int age;
00429 long long timeBegin, timeEnd, timeLoopBegin;
00430 wmpFrame p;
00431 struct {
00432 unsigned short first;
00433 int firstPos;
00434 unsigned short last;
00435 int lastPos;
00436 } LoopId;
00437 };
00438 std::map<unsigned int, Interval> messages;
00439 std::map<unsigned int, Interval> bc_messages;
00440 std::map<int, MaxMinCStats<long long> * > prio;
00441 std::map<int, MaxMinCStats<long long> * >::iterator prioIt;
00442 MaxMinCStats<long long> mdd;
00443 MaxMinCStats<long long> papMdd;
00444 MaxMinCStats<long long> interAuth;
00445 MaxMinCStats<long long> ctt;
00446 MaxMinCStats<long long> cta;
00447 MaxMinCStats<long long> ctm;
00448
00449
00450 ListCStats<long long> interAuthList;
00451 ListCStats<long long> nrd;
00452 ThingOverTimeCStats<long long, long long> bw;
00453 PlainCStats<int> nmsg;
00454 DoubleListCStats<int> preempted;
00455 ListCStats<int> rescheduled;
00456 ListCStats<int> orphan;
00457 DoubleListCStats<int> o3;
00458 ThingOverTimeCStats<long long, long long> avail;
00459
00460
00461
00462
00463 bool initied, isqos, global_flow, pernode;
00464 int id, from, to, src, dst , begin_id, loop_id, flow_id;
00465
00466 struct {
00467 int Pos, NTPos, MKey, msg_id_pos;
00468 long long NTTime, Time;
00469 unsigned int msg_id;
00470 wmpFrame Frame;
00471 } prev;
00472
00473 public:
00474 virtual void init(){
00475 messages.clear();
00476 mdd.init();
00477
00478 ctt.init();
00479 cta.init();
00480 ctm.init();
00481
00482 interAuth.init();
00483 interAuthList.init();
00484 nrd.init();
00485 bw.init();
00486 nmsg.init();
00487 preempted.init();
00488 rescheduled.init();
00489 papMdd.init();
00490 avail.init();
00491 initied=false;
00492 begin_id=0;
00493 loop_id=0;
00494 memset(&prev,0,sizeof(prev));
00495
00496 prev.NTTime = 0;
00497 prev.NTPos = 0;
00498 }
00499
00500 StatsFlow(int flow_id, int from, int to, bool qos, long long time_begin = 0) :
00501 mdd("Message Delivery Delay", "us"), papMdd("Message Delivery Delay + PAP", "us"), nrd(
00502 "Message Not Reaching Destination", "us"), bw("Bandwidth",
00503 "Kbps"), nmsg("Messages", ""), preempted("Preempted","Msg Univocal Id"), rescheduled("Rescheduled","Id"),orphan("Orphan","Id"),
00504 o3("Out Of Order","Id"), avail("Available time per second","ms"), ctt("Tokens","us"), cta("Auths","us"), ctm("Messages","us"){
00505 this->src=from;
00506 this->dst=to;
00507 this->global_flow = (dst == -1);
00508 this->pernode = (dst == -2);
00509 this->isqos=qos;
00510 this->flow_id = flow_id;
00511 init();
00512 bw.new_time(0);
00513 }
00514 int get_src(){
00515 return src;
00516 }
00517
00518 int get_count(){
00519 return messages.size();
00520 }
00521
00522 int get_dst(){
00523 return dst;
00524 }
00525 bool is_qos(){
00526 return isqos;
00527 }
00528 void new_frame(wmpFrame * p, long long time, int pos){
00529
00530 if (!initied){
00531 begin_id = pos;
00532 prev.Pos = pos;
00533 prev.Time = time;
00534 initied = true;
00535 }
00536
00537 bw.new_time(time);
00538 avail.new_time(time);
00539 if (p->hdr.type == TOKEN){
00540 if (p->tkn.beginner == p->hdr.from){
00541 prev.NTTime = prev.Time;
00542 prev.NTPos = prev.Pos;
00543 loop_id = p->hdr.loop_id;
00544 }
00545 }
00546
00547 if (p->hdr.type == MESSAGE && mBitsIsSet(p->msg.type, 4)){
00548 new_message(p, time, pos);
00549 }
00550
00551 prev.Pos = pos;
00552 prev.Time = time;
00553 prev.Frame = *p;
00554 }
00555
00556 int begin(){
00557 return this->begin_id;
00558 }
00559
00560 void new_message(wmpFrame * p, long long time, int pos) {
00561 int flow_id = p->hdr.to * 100 + p->msg.src + 1;
00562
00563 bool is_first_msg_jump = false;
00564 bool is_reaching_me = false;
00565
00566 if (global_flow){
00567 is_first_msg_jump = (p->msg.src == p->hdr.from);
00568 is_reaching_me = (p->msg.dest & 1 << p->hdr.to);
00569 bool im_interested = is_reaching_me || is_first_msg_jump;
00570 if (!im_interested){
00571 return;
00572 }
00573 }else if (pernode){
00574 bool im_interested = this->src == p->msg.src ;
00575 if (!im_interested){
00576 return;
00577 }
00578 is_first_msg_jump = (p->msg.src == p->hdr.from);
00579 is_reaching_me = (p->msg.dest & 1 << p->hdr.to);
00580 }else{
00581
00582 bool im_interested = this->src == p->msg.src && (p->msg.dest & (1<<dst));
00583 if (!im_interested){
00584 return;
00585 }
00586 is_first_msg_jump = (p->msg.src == p->hdr.from);
00587 is_reaching_me = (p->hdr.to == dst);
00588 }
00589
00590 unsigned int mkey = p->msg.msg_hash*100000 + 1000*abs(p->msg.part_id) + 100*p->msg.port;
00591
00592 if (messages.find(mkey) == messages.end()){
00593 messages[mkey].begin = 0;
00594 messages[mkey].end = 0;
00595 messages[mkey].prio = p->msg.priority;
00596 messages[mkey].age = p->msg.age;
00597 nmsg.new_value(1);
00598 }
00599
00600 if (is_first_msg_jump) {
00601
00602 messages[mkey].begin = pos;
00603 messages[mkey].timeBegin = prev.Time;
00604 messages[mkey].dest = p->msg.dest;
00605
00606 messages[mkey].rescheduled = mBitsIsSet(p->msg.type,2);
00607
00608 messages[mkey].LoopId.first = p->hdr.loop_id;
00609 messages[mkey].LoopId.firstPos = pos;
00610
00611 if (p->hdr.loop_id == loop_id){
00612 messages[mkey].timeLoopBegin = prev.NTTime;
00613 }else{
00614 messages[mkey].timeLoopBegin = 0;
00615 }
00616 }
00617
00618 if (is_reaching_me) {
00619
00620 messages[mkey].end = pos;
00621 messages[mkey].timeEnd = time;
00622 messages[mkey].LoopId.last = p->hdr.loop_id;
00623 messages[mkey].LoopId.lastPos = pos;
00624
00625
00626 bw.new_thing(1000 * 8 * p ->msg.len);
00627 bw.new_time(time);
00628 prev.msg_id = p->msg.msg_hash;
00629 prev.msg_id_pos = pos;
00630 }
00631 prev.Pos = pos;
00632 prev.Time = time;
00633 prev.Frame = *p;
00634 prev.MKey = mkey;
00635
00636 }
00637
00638 void process() {
00639 std::map<unsigned int, Interval>::iterator it;
00640 for (it = messages.begin(); it != messages.end(); ++it) {
00641 Interval be = it->second;
00642
00643 nrd.new_touch();
00644 rescheduled.new_touch();
00645 orphan.new_touch();
00646 preempted.new_touch();
00647 o3.new_touch();
00648
00649 if (be.rescheduled) {
00650 rescheduled.new_value(be.begin, be.end);
00651 }
00652
00653 if (be.begin != 0) {
00654 if (be.end != 0) {
00655 if ((be.timeEnd - be.timeBegin)>=0){
00656 mdd.new_value(be.timeEnd - be.timeBegin, be.begin);
00657 }
00658 if (be.LoopId.first != be.LoopId.last){
00659 preempted.new_value(it->first,be.LoopId.firstPos,it->first,be.LoopId.lastPos);
00660 }
00661 if (be.timeLoopBegin != 0) {
00662 if ((be.timeEnd - be.timeLoopBegin)>0){
00663 papMdd.new_value(be.timeEnd - be.timeLoopBegin, be.end);
00664 if (prio.find(be.prio)==prio.end()){
00665 prio[be.prio] = new MaxMinCStats<long long>("Priority "+toString(be.prio),"us");
00666 }
00667 prio[be.prio]->new_value(be.timeEnd - be.timeLoopBegin, be.begin);
00668
00669
00670 int prioWithAge = be.prio + 1000;
00671 if (prio.find(prioWithAge)==prio.end()){
00672 prio[prioWithAge] = new MaxMinCStats<long long>("Priority " + toString(be.prio) + " (total)", "ms");
00673 }
00674 prio[prioWithAge]->new_value(be.age + (be.timeEnd/1000 - be.timeLoopBegin/1000) , be.begin);
00675
00676
00677 prioWithAge = be.prio + 2000;
00678 if (prio.find(prioWithAge)==prio.end()){
00679 prio[prioWithAge] = new MaxMinCStats<long long>("Priority " + toString(be.prio) + " (age)", "ms");
00680 }
00681 prio[prioWithAge]->new_value(be.age, be.begin);
00682 }
00683 }
00684 } else {
00685 orphan.new_value(be.begin, be.begin);
00686 nrd.new_value(be.begin, be.begin);
00687 }
00688 }
00689 }
00690 }
00691 MaxMinCStats<long long> & getMdd(){
00692 return mdd;
00693 }
00694 void getBegin(){
00695 prioIt=prio.begin();
00696 }
00697 bool hasMore(){
00698 bool ret=(prioIt!=prio.end());
00699 return ret;
00700 }
00701 int getId(){
00702 return prioIt->first;
00703 }
00704 MaxMinCStats<long long> & getNextPrioLoop(){
00705 MaxMinCStats<long long> * ret = prioIt->second;
00706 prioIt++;
00707 return *ret;
00708 }
00709 MaxMinCStats<long long> & getCTT(){
00710 return ctt;
00711 }
00712
00713 MaxMinCStats<long long> & getCTA(){
00714 return cta;
00715 }
00716
00717 MaxMinCStats<long long> & getCTM(){
00718 return ctm;
00719 }
00720
00721 MaxMinCStats<long long> & getPapMdd(){
00722 return papMdd;
00723 }
00724
00725 ListCStats<long long> & getNrd(){
00726 return nrd;
00727 }
00728 ListCStats<int> & getRescheduled(){
00729 return rescheduled;
00730 }
00731 DoubleListCStats<int> & getPreempted(){
00732 return preempted;
00733 }
00734
00735 DoubleListCStats<int> & getO3(){
00736 return o3;
00737 }
00738
00739 ListCStats<int> & getOrphan(){
00740 return orphan;
00741 }
00742
00743 PlainCStats<int> & getNMsg(){
00744 return nmsg;
00745 }
00746 ThingOverTimeCStats<long long, long long> & getBw(){
00747 return bw;
00748 };
00749 ThingOverTimeCStats<long long, long long> & getAvail(){
00750 return avail;
00751 };
00752
00753 void new_time(long long time) {
00754 bw.new_time(time);
00755 }
00756 void reset() {
00757 messages.clear();
00758 }
00759 };
00760
00761 #endif