1 /* Copyright (C) 2012-2020 IBM Corp.
2  * This program is Licensed under the Apache License, Version 2.0
3  * (the "License"); you may not use this file except in compliance
4  * with the License. You may obtain a copy of the License at
5  *   http://www.apache.org/licenses/LICENSE-2.0
6  * Unless required by applicable law or agreed to in writing, software
7  * distributed under the License is distributed on an "AS IS" BASIS,
8  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9  * See the License for the specific language governing permissions and
10  * limitations under the License. See accompanying LICENSE file.
11  */
12 #include <algorithm>
13 #include <utility>
14 #include <cstring>
15 #include <ctime>
16 #include <helib/timing.h>
17 
18 namespace helib {
19 
20 #ifdef CLOCK_MONOTONIC
GetTimerClock()21 unsigned long GetTimerClock()
22 {
23   timespec ts;
24 
25   clock_gettime(CLOCK_MONOTONIC, &ts);
26   // clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
27   // clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
28 
29   return ((unsigned long)ts.tv_sec) * 1000000UL +
30          ((unsigned long)ts.tv_nsec / 1000);
31 }
32 
33 const unsigned long CLOCK_SCALE = 1000000UL;
34 
35 #else
36 #warning "using low-resolution clock"
37 
38 // NOTE: the clock used by clock_gettime seems to be much higher
39 // resolution than that used by clock.
40 
GetTimerClock()41 unsigned long GetTimerClock() { return clock(); }
42 
43 const unsigned long CLOCK_SCALE = (unsigned long)CLOCKS_PER_SEC;
44 #endif
45 
timer_compare(const FHEtimer * a,const FHEtimer * b)46 bool timer_compare(const FHEtimer* a, const FHEtimer* b)
47 {
48   return strcmp(a->name, b->name) < 0;
49 }
50 
51 static std::vector<FHEtimer*> timerMap;
52 static HELIB_MUTEX_TYPE timerMapMx;
53 
registerTimer(FHEtimer * timer)54 void registerTimer(FHEtimer* timer)
55 {
56   HELIB_MUTEX_GUARD(timerMapMx);
57   timerMap.push_back(timer);
58 }
59 
60 // Reset a timer for some label to zero
reset()61 void FHEtimer::reset()
62 {
63   numCalls = 0;
64   counter = 0;
65 }
66 
67 // Read the value of a timer (in seconds)
getTime() const68 double FHEtimer::getTime() const // returns time in seconds
69 {
70   // If the counter is currently counting, add the clock() value
71   return ((double)counter) / CLOCK_SCALE;
72 }
73 
74 // Returns number of calls for that timer
getNumCalls() const75 long FHEtimer::getNumCalls() const { return numCalls; }
76 
resetAllTimers()77 void resetAllTimers()
78 {
79   for (long i = 0; i < long(timerMap.size()); i++)
80     timerMap[i]->reset();
81 }
82 
83 // Print the value of all timers to stream
printAllTimers(std::ostream & str)84 void printAllTimers(std::ostream& str)
85 {
86 
87   sort(timerMap.begin(), timerMap.end(), timer_compare);
88 
89   for (long i = 0; i < long(timerMap.size()); i++) {
90     const char* name = timerMap[i]->name;
91     const char* loc = timerMap[i]->loc;
92     double t = timerMap[i]->getTime();
93     long n = timerMap[i]->getNumCalls();
94     double ave;
95     if (n > 0) {
96       ave = t / n;
97     } else {
98       continue;
99     }
100 
101     str << "  " << name << ": " << t << " / " << n << " = " << ave << "   ["
102         << loc << "]\n";
103   }
104 }
105 
getTimerByName(const char * name)106 const FHEtimer* getTimerByName(const char* name)
107 {
108   for (long i = 0; i < long(timerMap.size()); i++) {
109     if (strcmp(name, timerMap[i]->name) == 0)
110       return timerMap[i];
111   }
112 
113   return 0;
114 }
115 
printNamedTimer(std::ostream & str,const char * name)116 bool printNamedTimer(std::ostream& str, const char* name)
117 {
118   for (long i = 0; i < long(timerMap.size()); i++) {
119     if (strcmp(name, timerMap[i]->name) == 0) {
120 
121       long n = timerMap[i]->getNumCalls();
122       if (n > 0) {
123         double t = timerMap[i]->getTime();
124         double ave = t / n;
125 
126         str << "  " << name << ": " << t << " / " << n << " = " << ave << "   ["
127             << timerMap[i]->loc << "]\n";
128       } else {
129         str << "  " << name << " -- [" << timerMap[i]->loc << "]\n";
130       }
131       return true;
132     }
133   }
134   return false;
135 }
136 
137 } // namespace helib
138