-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtimequick.h
118 lines (98 loc) · 3.19 KB
/
timequick.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/* timequick.h
Header only library to quickly time things.
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#ifndef TIMEQUICK_H
#define TIMEQUICK_H
/* This allows nesting of start/stop calls, sort of like
matching parentheses. A switch is available because
working with a stack and dynamic allocation might add
too much overhead for a lot of timing purposes.
0 disables nesting.
*/
#define NEST 1
/* Time unit when printing. */
enum tq_unit {
tq_SECONDS,
tq_MILLISECONDS,
tq_MICROSECONDS,
tq_NANOSECONDS
};
/* Nodes of the nesting stack. */
struct tq_node {
struct timespec start_time;
struct tq_node *next;
};
/* Starting time when not nesting. */
static struct timespec tq_start_time = {0, 0};
#if NEST
/* Nesting stack. */
static struct tq_node *tq_stack = NULL;
#endif /* #if NEST */
static enum tq_unit tq_output_unit = tq_SECONDS;
/* Set the time unit for printing. Only affects output, not resolution.
Set to "seconds" by default.
*/
static void tq_set_unit(enum tq_unit unit) {
tq_output_unit = unit;
}
/* Start timing. The next tq_stop will match the latest tq_start, like
matching parentheses. msg is ignored, and only for user's readability.
*/
static void tq_start(char const *msg) {
#if NEST
struct tq_node *new_node = (struct tq_node *)malloc(sizeof(struct tq_node));
assert(new_node && "timequick: malloc failed.");
clock_gettime(CLOCK_REALTIME, &(new_node->start_time));
new_node->next = tq_stack;
tq_stack = new_node;
#else
clock_gettime(CLOCK_REALTIME, &tq_start_time);
#endif /* #if NEST */
}
/* Stop timing, and print the time since the last tq_start with msg. */
static void tq_stop(char const *msg) {
static struct timespec end_time;
static double elapsed_time;
static char const *unit = "s";
/* If nesting, pop the stack, and put the start time into
the global.
*/
#if NEST
assert(tq_stack && "timequick: stack is empty.");
memcpy(&tq_start_time, &(tq_stack->start_time),
sizeof(struct timespec));
struct tq_node *old_top = tq_stack;
tq_stack = tq_stack->next;
free(old_top);
#endif /* if NEST */
clock_gettime(CLOCK_REALTIME, &end_time);
elapsed_time = (end_time.tv_nsec - tq_start_time.tv_nsec)
+ (end_time.tv_sec - tq_start_time.tv_sec)
* 1000000000;
switch (tq_output_unit) {
case tq_SECONDS:
unit = "s";
elapsed_time /= 1000000000;
break;
case tq_MILLISECONDS:
unit = "ms";
elapsed_time /= 1000000;
break;
case tq_MICROSECONDS:
unit = "us";
elapsed_time /= 1000;
break;
case tq_NANOSECONDS:
unit = "ns";
break;
/* elapsed_time is already sorted. */
}
/* Newline at the start to ensure it has it's own line. */
printf("\ntq_stop: %s: %f%s\n", msg, elapsed_time, unit);
}
#endif /* #ifndef TIMEQUICK_H */