C/timer
From Attie's Wiki
(Difference between revisions)
m |
m |
||
(3 intermediate revisions by one user not shown) | |||
Line 3: | Line 3: | ||
You will need to link with librt... so add <code>-lrt</code> to your link command. | You will need to link with librt... so add <code>-lrt</code> to your link command. | ||
− | + | The macros use braced (<code>{}</code>) contexts. | |
* <code>TIMER_START_HERE</code> opens the context and grabs the 'start time' | * <code>TIMER_START_HERE</code> opens the context and grabs the 'start time' | ||
* <code>TIMER_GET_HERE</code> allows the user to grab the time since <code>TIMER_START_HERE</code> in either a <code>long long int</code> (as nanoseconds), or in a <code>struct timespec</code>. | * <code>TIMER_GET_HERE</code> allows the user to grab the time since <code>TIMER_START_HERE</code> in either a <code>long long int</code> (as nanoseconds), or in a <code>struct timespec</code>. | ||
* <code>TIMER_PRINT_HERE</code> will printf the given message and parameters, along with file, line number and time taken - two parameters are ''required'' (sorry) | * <code>TIMER_PRINT_HERE</code> will printf the given message and parameters, along with file, line number and time taken - two parameters are ''required'' (sorry) | ||
* <code>TIMER_SPEED_HERE</code> will print the rate in MB/s with a given label | * <code>TIMER_SPEED_HERE</code> will print the rate in MB/s with a given label | ||
− | * <code>TIMER_END_HERE</code> prints a message (same arguments as <code>TIMER_PRINT_HERE</code>, and closes the context | + | * <code>TIMER_END_HERE</code> prints a message (with no arguments), and closes the context |
+ | * <code>TIMER_END_HERE2</code> prints a message (same arguments as <code>TIMER_PRINT_HERE</code>), and closes the context | ||
+ | * <code>TIMER_END_QUIET</code> silently closes the context | ||
It is worth noting that due to the use of contexts, any <code>TIMER_START_HERE</code> that is 'inside' a <code>TIMER_START_HERE</code>, will have the effect of moving the start time. Once a <code>TIMER_END_HERE</code> is used, this start time will revert to that of the 'outer' <code>TIMER_START_HERE</code>. | It is worth noting that due to the use of contexts, any <code>TIMER_START_HERE</code> that is 'inside' a <code>TIMER_START_HERE</code>, will have the effect of moving the start time. Once a <code>TIMER_END_HERE</code> is used, this start time will revert to that of the 'outer' <code>TIMER_START_HERE</code>. | ||
Line 16: | Line 18: | ||
#define TIMER_H | #define TIMER_H | ||
+ | #include <string.h> | ||
#include <time.h> | #include <time.h> | ||
Line 68: | Line 71: | ||
} | } | ||
− | #define TIMER_END_HERE(fmt, ...) \ | + | #define TIMER_END_HERE() \ |
+ | TIMER_PRINT_HERE2("END", "", 0); \ | ||
+ | } | ||
+ | |||
+ | #define TIMER_END_HERE2(fmt, ...) \ | ||
TIMER_PRINT_HERE2("END", fmt, __VA_ARGS__); \ | TIMER_PRINT_HERE2("END", fmt, __VA_ARGS__); \ | ||
+ | } | ||
+ | |||
+ | #define TIMER_END_QUIET() \ | ||
} | } | ||
Line 132: | Line 142: | ||
} | } | ||
− | #define TIMER_END_HERE(fmt, ...) \ | + | #define TIMER_END_HERE() \ |
+ | TIMER_PRINT_HERE2("END", "", 0); \ | ||
+ | } | ||
+ | |||
+ | #define TIMER_END_HERE2(fmt, ...) \ | ||
TIMER_PRINT_HERE2("END", fmt, __VA_ARGS__); \ | TIMER_PRINT_HERE2("END", fmt, __VA_ARGS__); \ | ||
} | } |
Latest revision as of 20:54, 9 September 2015
These macros can be used to perform basic timing on a part of code.
You will need to link with librt... so add -lrt
to your link command.
The macros use braced ({}
) contexts.
-
TIMER_START_HERE
opens the context and grabs the 'start time' -
TIMER_GET_HERE
allows the user to grab the time sinceTIMER_START_HERE
in either along long int
(as nanoseconds), or in astruct timespec
. -
TIMER_PRINT_HERE
will printf the given message and parameters, along with file, line number and time taken - two parameters are required (sorry) -
TIMER_SPEED_HERE
will print the rate in MB/s with a given label -
TIMER_END_HERE
prints a message (with no arguments), and closes the context -
TIMER_END_HERE2
prints a message (same arguments asTIMER_PRINT_HERE
), and closes the context -
TIMER_END_QUIET
silently closes the context
It is worth noting that due to the use of contexts, any TIMER_START_HERE
that is 'inside' a TIMER_START_HERE
, will have the effect of moving the start time. Once a TIMER_END_HERE
is used, this start time will revert to that of the 'outer' TIMER_START_HERE
.
#ifndef TIMER_H #define TIMER_H #include <string.h> #include <time.h> #define TIMER_START_HERE() \ { struct timespec timer_start; \ const int timer_start_line = __LINE__; \ clock_gettime(CLOCK_REALTIME, &timer_start); #define TIMER_GET_HERE(v, p) \ { struct timespec __timer; \ clock_gettime(CLOCK_REALTIME, &__timer); \ if ((v)) *((long long int*)(v)) = (__timer.tv_sec * 1000000000) + __timer.tv_nsec; \ if ((p)) memcpy(((struct timespec*)(p)), &__timer, sizeof(__timer)); \ } #define TIMER_STAMP_HERE(fmt, ...) \ { struct timespec timer; \ TIMER_GET_HERE(NULL, &timer); \ fprintf(stderr, "###### TIMER(STAMP) ###### -> file:%s line:%d time:%ld.%09ld " fmt "\n", __FILE__, __LINE__, timer.tv_sec, timer.tv_nsec, __VA_ARGS__); \ } #define TIMER_DIFF_HERE(v, p) \ { struct timespec __timer; \ clock_gettime(CLOCK_REALTIME, &__timer); \ __timer.tv_sec -= timer_start.tv_sec; \ __timer.tv_nsec -= timer_start.tv_nsec; \ if (__timer.tv_nsec < 0) { \ __timer.tv_sec--; \ __timer.tv_nsec += 1000000000; \ } \ if ((v)) *((long long int*)(v)) = (__timer.tv_sec * 1000000000) + __timer.tv_nsec; \ if ((p)) memcpy(((struct timespec*)(p)), &__timer, sizeof(__timer)); \ } #define TIMER_PRINT_HERE(fmt, ...) \ TIMER_PRINT_HERE2("PRINT", fmt, __VA_ARGS__); #define TIMER_PRINT_HERE2(type, fmt, ...) \ { struct timespec timer_diff; \ TIMER_DIFF_HERE(NULL, &timer_diff); \ fprintf(stderr, "###### TIMER(" type ") ###### -> file:%s lines:%d-%d took:%ld.%09ld seconds " fmt "\n", __FILE__, timer_start_line, __LINE__, timer_diff.tv_sec, timer_diff.tv_nsec, __VA_ARGS__); \ } #define TIMER_SPEED_HERE(label, size) \ { unsigned long diff; \ float speed; \ TIMER_DIFF_HERE(&diff, NULL); \ speed = diff; \ speed /= 1000; \ speed = size / speed; \ fprintf(stderr, "===== SPEED (%s): %d bytes in %dns -> %.2f MB/s\n", label, size, diff, speed); \ } #define TIMER_END_HERE() \ TIMER_PRINT_HERE2("END", "", 0); \ } #define TIMER_END_HERE2(fmt, ...) \ TIMER_PRINT_HERE2("END", fmt, __VA_ARGS__); \ } #define TIMER_END_QUIET() \ } #endif /* TIMER_H */
[edit] For use in the Linux kernel source
#ifndef ATTIE_TIMER_H #define ATTIE_TIMER_H #include <linux/time.h> #define TIMER_START_HERE() \ { struct timespec timer_start; \ const int timer_start_line = __LINE__; \ getrawmonotonic(&timer_start); #define TIMER_GET_HERE(v, p) \ { struct timespec __timer; \ getrawmonotonic(&__timer); \ if ((v)) *((long long int*)(v)) = (__timer.tv_sec * 1000000000) + __timer.tv_nsec; \ if ((p)) memcpy(((struct timespec*)(p)), &__timer, sizeof(__timer)); \ } #define TIMER_STAMP_HERE(fmt, ...) \ { struct timespec timer; \ TIMER_GET_HERE(NULL, &timer); \ printk(KERN_EMERG "###### TIMER(STAMP) ###### -> file:%s line:%d time:%ld.%09ld " fmt "\n", __FILE__, __LINE__, timer.tv_sec, timer.tv_nsec, __VA_ARGS__); \ } #define TIMER_DIFF_HERE(v, p) \ { struct timespec __timer; \ getrawmonotonic(&__timer); \ __timer.tv_sec -= timer_start.tv_sec; \ __timer.tv_nsec -= timer_start.tv_nsec; \ if (__timer.tv_nsec < 0) { \ __timer.tv_sec--; \ __timer.tv_nsec += 1000000000; \ } \ if ((v)) *((long long int*)(v)) = (__timer.tv_sec * 1000000000) + __timer.tv_nsec; \ if ((p)) memcpy(((struct timespec*)(p)), &__timer, sizeof(__timer)); \ } #define TIMER_PRINT_HERE(fmt, ...) \ TIMER_PRINT_HERE2("PRINT", fmt, __VA_ARGS__); #define TIMER_PRINT_HERE2(type, fmt, ...) \ { struct timespec timer_diff; \ TIMER_DIFF_HERE(NULL, &timer_diff); \ printk(KERN_EMERG "###### TIMER(" type ") ###### -> file:%s lines:%d-%d took:%ld.%09ld seconds " fmt "\n", __FILE__, timer_start_line, __LINE__, timer_diff.tv_sec, timer_diff.tv_nsec, __VA_ARGS__); \ } #define TIMER_SPEED_HERE(label, size) \ { unsigned long diff; \ float speed; \ TIMER_DIFF_HERE(&diff, NULL); \ speed = diff; \ speed /= 1000; \ speed = size / speed; \ printk(KERN_EMERG "===== SPEED (%s): %d bytes in %dns -> %.2f MB/s\n", label, size, diff, speed); \ } #define TIMER_END_HERE() \ TIMER_PRINT_HERE2("END", "", 0); \ } #define TIMER_END_HERE2(fmt, ...) \ TIMER_PRINT_HERE2("END", fmt, __VA_ARGS__); \ } #endif /* ATTIE_TIMER_H */