GCC Code Coverage Report


Directory: src/
File: src/support/mytime.c
Date: 2024-11-22 17:07:10
Exec Total Coverage
Lines: 89 127 70.1%
Functions: 18 22 81.8%
Branches: 25 32 78.1%

Line Branch Exec Source
1 /*********************************************************************************/
2 /* Copyright 2009-2021 Barcelona Supercomputing Center */
3 /* */
4 /* This file is part of the DLB library. */
5 /* */
6 /* DLB is free software: you can redistribute it and/or modify */
7 /* it under the terms of the GNU Lesser General Public License as published by */
8 /* the Free Software Foundation, either version 3 of the License, or */
9 /* (at your option) any later version. */
10 /* */
11 /* DLB is distributed in the hope that it will be useful, */
12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14 /* GNU Lesser General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU Lesser General Public License */
17 /* along with DLB. If not, see <https://www.gnu.org/licenses/>. */
18 /*********************************************************************************/
19
20 #include "support/mytime.h"
21
22 #include "support/debug.h"
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <math.h>
27
28 enum { MS_PER_SECOND = 1000LL };
29 enum { US_PER_SECOND = 1000000LL };
30 enum { NS_PER_SECOND = 1000000000LL };
31
32 3399 void get_time( struct timespec *t ) {
33 3399 clock_gettime( CLOCK_MONOTONIC, t);
34 3399 }
35
36 97 void get_time_coarse( struct timespec *t ) {
37 #ifdef CLOCK_MONOTONIC_COARSE
38 97 clock_gettime( CLOCK_MONOTONIC_COARSE, t);
39 #else
40 clock_gettime( CLOCK_MONOTONIC, t);
41 #endif
42 97 }
43
44 438 void get_time_real(struct timespec *t) {
45 /* Avoid using CLOCK_REALTIME except for pthread_mutex_timedlock,
46 * which does not work with MONOTONIC */
47 438 clock_gettime(CLOCK_REALTIME, t);
48 438 }
49
50 3242 int64_t get_time_in_ns(void) {
51 struct timespec t;
52 3242 get_time(&t);
53 3242 return to_nsecs(&t);
54 }
55
56 9 int diff_time( struct timespec init, struct timespec end, struct timespec* diff ) {
57
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if ( init.tv_sec > end.tv_sec ) {
58 2 return -1;
59 } else {
60
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
7 if ( ( init.tv_sec == end.tv_sec ) && ( init.tv_nsec > end.tv_nsec ) ) {
61 1 return -1;
62 } else {
63
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if ( init.tv_nsec > end.tv_nsec ) {
64 2 diff->tv_sec = end.tv_sec - ( init.tv_sec + 1 );
65 2 diff->tv_nsec = ( end.tv_nsec + NS_PER_SECOND ) - init.tv_nsec;
66 } else {
67 4 diff->tv_sec = end.tv_sec - init.tv_sec;
68 4 diff->tv_nsec = end.tv_nsec - init.tv_nsec;
69 }
70 }
71 }
72
73 6 return 0;
74 }
75
76 2 void add_time( struct timespec t1, struct timespec t2, struct timespec* sum ) {
77 2 sum->tv_nsec = t1.tv_nsec + t2.tv_nsec;
78
79
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if ( sum->tv_nsec >= NS_PER_SECOND ) {
80 1 sum->tv_sec = t1.tv_sec + t2.tv_sec + ( sum->tv_nsec/NS_PER_SECOND );
81 1 sum->tv_nsec = ( sum->tv_nsec % NS_PER_SECOND );
82 } else {
83 1 sum->tv_sec = t1.tv_sec + t2.tv_sec;
84 }
85 2 }
86
87 2 void mult_time( struct timespec t1, int factor, struct timespec* prod ) {
88 2 int64_t nsec = (int64_t)t1.tv_nsec * factor;
89
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (nsec >= NS_PER_SECOND) {
90 1 prod->tv_sec = t1.tv_sec * factor + nsec / NS_PER_SECOND;
91 1 prod->tv_nsec = nsec % NS_PER_SECOND;
92 } else {
93 1 prod->tv_nsec = nsec;
94 1 prod->tv_sec = t1.tv_sec * factor;
95 }
96 2 }
97
98 void diff_time_mult(struct timespec* time, int mult_factor, struct timespec * result){
99 *result = *time;
100 clock_gettime(CLOCK_REALTIME, time);
101 diff_time(*result,*time , result);
102 mult_time(*result,mult_factor,result);
103 }
104
105 1 void reset( struct timespec *t1 ) {
106 1 t1->tv_nsec = 0;
107 1 t1->tv_sec = 0;
108 1 }
109
110 12 double to_secs( struct timespec t1 ) {
111 12 return t1.tv_sec + (double)t1.tv_nsec / NS_PER_SECOND;
112 }
113
114 3248 int64_t to_nsecs( const struct timespec *ts ) {
115 3248 return ts->tv_nsec + (int64_t)ts->tv_sec * NS_PER_SECOND;
116 }
117
118 22 double nsecs_to_secs( int64_t nsecs ) {
119 22 return (double)nsecs / NS_PER_SECOND;
120 }
121
122 // Return timeval diff in us
123 2 int64_t timeval_diff( const struct timeval *init, const struct timeval *end ) {
124 4 return (int64_t)(end->tv_sec - init->tv_sec) * US_PER_SECOND +
125 2 (int64_t)(end->tv_usec - init->tv_usec);
126 }
127
128 // Return timespec diff in ns
129 93 int64_t timespec_diff( const struct timespec *init, const struct timespec *end ) {
130 186 return (int64_t)(end->tv_sec - init->tv_sec) * NS_PER_SECOND +
131 93 (int64_t)(end->tv_nsec - init->tv_nsec);
132 }
133
134 2 void add_tv_to_ts( const struct timeval *t1, const struct timeval *t2,
135 struct timespec *res ) {
136 2 long sec = t2->tv_sec + t1->tv_sec;
137 2 long nsec = (t2->tv_usec + t1->tv_usec) * MS_PER_SECOND;
138
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (nsec >= NS_PER_SECOND) {
139 1 nsec -= NS_PER_SECOND;
140 1 sec++;
141 }
142 2 res->tv_sec = sec;
143 2 res->tv_nsec = nsec;
144 2 }
145
146 35 void ns_to_human( char *buf, size_t size, int64_t ns ) {
147
4/4
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 33 times.
35 if (!buf || !size) return;
148
149 33 const char* const units[] = {"ns", "us", "ms", "s"};
150 33 int decimal_part = 0;
151 33 int64_t integer_part = ns;
152 33 int i = 0;
153
4/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 1 times.
72 while (integer_part > 999 && i<3) {
154 39 decimal_part = integer_part % 1000;
155 39 integer_part = integer_part / 1000;
156 39 ++i;
157 }
158
159 /* Print 0 or 2 decimals */
160 33 decimal_part /= 10;
161
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 18 times.
33 if (decimal_part > 0) {
162 15 snprintf(buf, size, "%"PRId64".%02d %s", integer_part, decimal_part, units[i]);
163 } else {
164 18 snprintf(buf, size, "%"PRId64" %s", integer_part, units[i]);
165 }
166 }
167
168
169 /* Timers */
170
171 enum { TIMER_MAX_KEY_LEN = 128 };
172
173 typedef struct TimerData {
174 char key[TIMER_MAX_KEY_LEN];
175 int64_t acc;
176 int64_t asq;
177 int64_t max;
178 int64_t count;
179 struct timespec start;
180 struct timespec stop;
181 } timer_data_t;
182
183 static timer_data_t *timers = NULL;
184 static int ntimers = 0;
185
186 81 void timer_init(void) {
187 81 }
188
189 void *timer_register(const char *key) {
190 /* Found key if already registered */
191 int i;
192 for (i=0; i<ntimers; ++i) {
193 if (strncmp(timers[i].key, key, TIMER_MAX_KEY_LEN) == 0) {
194 return &timers[i];
195 }
196 }
197
198 /* Reallocate new position in timers array */
199 ++ntimers;
200 void *p = realloc(timers, sizeof(timer_data_t)*ntimers);
201 if (p) timers = p;
202 else fatal("realloc failed");
203
204 /* Initialize timer */
205 timer_data_t *timer = &timers[ntimers-1];
206 snprintf(&timer->key[0], TIMER_MAX_KEY_LEN, "%s", key);
207 timer->acc = 0;
208 timer->asq = 0;
209 timer->max = 0;
210 timer->count = 0;
211 reset(&timer->start);
212 reset(&timer->stop);
213
214 return timer;
215 }
216
217 void timer_start(void *handler) {
218 timer_data_t *timer = (timer_data_t*) handler;
219 timer->count++;
220 get_time(&timer->start);
221 }
222
223 void timer_stop(void *handler) {
224 timer_data_t *timer = (timer_data_t*) handler;
225 get_time(&timer->stop);
226 int64_t elapsed = timespec_diff(&timer->start, &timer->stop);
227 timer->acc += elapsed;
228 timer->asq += elapsed*elapsed;
229 timer->max = elapsed > timer->max ? elapsed : timer->max;
230 }
231
232 79 void timer_finalize(void) {
233 /* Timers Report */
234 int i;
235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 for (i=0; i<ntimers; ++i) {
236 timer_data_t *timer = &timers[i];
237 int64_t avg = timer->acc/timer->count;
238 int64_t stdev = sqrt(timer->asq/timer->count - avg*avg);
239 info("Timer \"%s\" "
240 "n: %"PRId64", avg: %"PRId64", stdev: %"PRId64", max: %"PRId64,
241 timer->key, timer->count, avg, stdev, timer->max);
242 }
243
244 /* De-allocate timers */
245 79 free(timers);
246 79 timers = NULL;
247 79 ntimers = 0;
248 79 }
249
250
251 /* Formatted strings */
252
253 // This function assumes localtime to be used, so no timezone information is specified
254 21 char* get_iso_8601_string(struct tm *tm_info) {
255 // requires 20 characters plus the null terminator
256 21 char *iso_8601_string = malloc(20);
257
258 // Format the tm structure into the ISO 8601 string
259 21 strftime(iso_8601_string, 20, "%Y-%m-%dT%H:%M:%S", tm_info);
260
261 21 return iso_8601_string;
262 }
263