source: src/Common/Stats/Time.cc @ c58ead7

Last change on this file since c58ead7 was fca6ca6, checked in by tdelisle <tdelisle@…>, 6 years ago

Fixed % of parent when more than one level ends at the same time

  • Property mode set to 100644
File size: 5.2 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Time.cc --
8//
9// Author           : Thierry Delisle
10// Created On       : Mon Mar 04 15:16:07 2019
11// Last Modified By :
12// Last Modified On :
13// Update Count     :
14//
15
16#include "Time.h"
17
18#include <cassert>
19#include <chrono>
20#include <cstdint>
21#include <cstring>
22#include <iostream>
23#include <iomanip>
24#include <stack>
25
26namespace Stats {
27        namespace Time {
28#               if !defined(NO_TIME_STATISTICS)
29                        extern bool enabled;
30
31                        Base::TreeTop top;
32
33                        typedef  std::chrono::time_point<std::chrono::high_resolution_clock> point_t;
34                        std::chrono::duration<double> total;
35
36                        point_t global_begin;
37
38                        int prevl = 0;
39                        int currl = 0;
40
41                        template<typename T>
42                        static inline std::ostream & operator<<(std::ostream & os, const std::chrono::duration<T> & dd) {
43                                auto d = std::chrono::duration_cast<std::chrono::milliseconds>(dd);
44                                auto minutes = std::chrono::duration_cast<std::chrono::minutes>(d);
45                                auto seconds = std::chrono::duration_cast<std::chrono::seconds>(d % std::chrono::minutes(1));
46                                auto millis  = std::chrono::duration_cast<std::chrono::milliseconds>(d % std::chrono::seconds(1));
47
48                                bool zmin = minutes == minutes.zero();
49                                bool zsec = seconds == seconds.zero();
50                                bool zmil = millis  == millis .zero();
51
52                                if(!zmin) {
53                                        os << std::setw(4) << minutes.count() << "m";
54                                } else {
55                                        os << std::string(5, ' ');
56                                }
57
58                                if(!zmin || !zsec) {
59                                        if(!zmin) os << std::setfill('0');
60                                        os << std::setw(2) << seconds.count() << "s";
61                                } else {
62                                        os << std::string(3, ' ');
63                                }
64                                os << std::setfill(' ');
65
66                                if(!zmin || !zsec || !zmil) {
67                                        if(!zmin || !zsec) os << std::setfill('0');
68                                        os << std::setw(3) << millis .count();
69                                } else {
70                                        os << std::string(4, ' ');
71                                }
72                                os << std::setfill(' ');
73
74                                return os;
75                        }
76
77                        class TimerNode : public Base::Tree<top> {
78                        public:
79                                TimerNode(const char * const name )
80                                        : Base::Tree<top>(name)
81                                {}
82
83                                TimerNode(const char * const name, Base::Tree<top> * parent)
84                                        : Base::Tree<top>(name, parent)
85
86                                {}
87
88                                virtual void print(std::ostream & os) override {
89                                        if(currl > prevl) {
90                                                parents.push(last);
91                                        }
92                                        for(auto lvl = prevl - currl; lvl > 0; lvl--) {
93                                                parents.pop();
94                                        }
95                                        last = end - begin;
96
97                                        assert(finished);
98                                        std::chrono::duration<double> diff = end - begin;
99                                        os << diff << " | ";
100                                        if(parents.empty()) {
101                                                os << "     N/A | ";
102                                        } else {
103                                                os << std::setw(7) << std::setprecision(0);
104                                                os << size_t(100.0 * diff.count() / parents.top().count()) << "% | ";
105                                        }
106                                        os << std::setw(5) << std::setprecision(0);
107                                        os << size_t(100.0 * diff.count() / total.count()) << "% ";
108                                }
109
110                                void start() {
111                                        begin = std::chrono::high_resolution_clock::now();
112                                }
113
114                                void finish() {
115                                        end = std::chrono::high_resolution_clock::now();
116                                        finished = true;
117                                }
118
119                        protected:
120                                virtual ~TimerNode() = default;
121
122                        private:
123                                bool finished = false;
124
125                                point_t begin;
126                                point_t end;
127
128                                static std::chrono::duration<double> last;
129                                static std::stack<std::chrono::duration<double>> parents;
130                        };
131
132                        std::stack<TimerNode *> nodes;
133
134                        std::chrono::duration<double> TimerNode::last;
135                        std::stack<std::chrono::duration<double>> TimerNode::parents;
136
137                        void StartGlobal() {
138                                global_begin = std::chrono::high_resolution_clock::now();
139                        }
140
141                        void StartBlock(const char * const name) {
142                                if(!enabled) return;
143                                auto node = nodes.empty()
144                                        ? new TimerNode(name)
145                                        : new TimerNode(name, nodes.top());
146
147                                nodes.push(node);
148                                node->start();
149                        }
150
151                        void StopBlock() {
152                                if(!enabled) return;
153                                nodes.top()->finish();
154                                nodes.pop();
155                        }
156
157                        void print() {
158                                if(!top.head) return;
159                                auto global_end = std::chrono::high_resolution_clock::now();
160                                total = global_end - global_begin;
161
162                                size_t nc = 0;
163                                Base::ForAll(top, 0, [&](Base::TreeImpl * node, size_t level) {
164                                        nc = std::max(nc, (4 * level) + std::strlen(node->name));
165                                });
166
167                                size_t nct = nc + 37;
168                                std::cerr << std::string(nct, '=') << std::endl;
169                                const char * const title = "Timing Results";
170                                std::cerr << std::string((nct - std::strlen(title)) / 2, ' ');
171                                std::cerr << title << std::endl;
172                                std::cerr << std::string(nct, '-') << std::endl;
173                                std::cerr << "Location";
174                                std::cerr << std::string(nc - (std::strlen("Location")), ' ');
175                                std::cerr << " | ";
176                                std::cerr << "       Time | ";
177                                std::cerr << "% parent | ";
178                                std::cerr << "% total |" << std::endl;
179                                std::cerr << std::string(nct, '-') << std::endl;
180
181                                Base::ForAll(top, 0, [&](Base::TreeImpl * node, size_t level) {
182                                        currl = level;
183                                        std::cerr << std::string(level * 4, ' ');
184                                        std::cerr << node->name;
185                                        std::cerr << std::string(nc - ((level * 4) + std::strlen(node->name)), ' ');
186                                        std::cerr << " | ";
187                                        node->print(std::cerr);
188                                        std::cerr << " |";
189                                        std::cerr << '\n';
190                                        prevl = level;
191                                }, true);
192
193                                std::cerr << std::string(nct, '-') << std::endl;
194                                std::cerr << "Total " << total << std::endl;
195                                std::cerr << std::string(nct, '-') << std::endl;
196                        }
197#               endif
198        }
199}
Note: See TracBrowser for help on using the repository browser.