C/timer

From Attie's Wiki
(Difference between revisions)
Jump to: navigation, search
m
m
 
(7 intermediate revisions by one user not shown)
Line 1: Line 1:
 
These macros can be used to perform basic timing on a part of code.
 
These macros can be used to perform basic timing on a part of code.
  
They use braced (<code>{}</code>) contexts.
+
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 14: Line 18:
 
#define TIMER_H
 
#define TIMER_H
  
 +
#include <string.h>
 
#include <time.h>
 
#include <time.h>
  
 
#define TIMER_START_HERE() \
 
#define TIMER_START_HERE() \
        {       struct timespec timer_start; \
+
{ struct timespec timer_start; \
                const int timer_start_line = __LINE__; \
+
const int timer_start_line = __LINE__; \
                clock_gettime(CLOCK_REALTIME, &timer_start);
+
clock_gettime(CLOCK_REALTIME, &timer_start);
  
 
#define TIMER_GET_HERE(v, p) \
 
#define TIMER_GET_HERE(v, p) \
                {       struct timespec __timer; \
+
{ struct timespec __timer; \
                        clock_gettime(CLOCK_REALTIME, &__timer); \
+
clock_gettime(CLOCK_REALTIME, &__timer); \
                        if ((v)) *((long long int*)(v)) = (__timer.tv_sec * 1000000000) + __timer.tv_nsec; \
+
if ((v)) *((long long int*)(v)) = (__timer.tv_sec * 1000000000) + __timer.tv_nsec; \
                        if ((p)) memcpy(((struct timespec*)(p)), &__timer, sizeof(__timer)); \
+
if ((p)) memcpy(((struct timespec*)(p)), &__timer, sizeof(__timer)); \
                }
+
}
  
 
#define TIMER_STAMP_HERE(fmt, ...) \
 
#define TIMER_STAMP_HERE(fmt, ...) \
                {       struct timespec timer; \
+
{ struct timespec timer; \
                        TIMER_GET_HERE(NULL, &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__); \
+
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) \
 
#define TIMER_DIFF_HERE(v, p) \
                {       struct timespec __timer; \
+
{ struct timespec __timer; \
                        clock_gettime(CLOCK_REALTIME, &__timer); \
+
clock_gettime(CLOCK_REALTIME, &__timer); \
                        __timer.tv_sec -= timer_start.tv_sec; \
+
__timer.tv_sec -= timer_start.tv_sec; \
                        __timer.tv_nsec -= timer_start.tv_nsec; \
+
__timer.tv_nsec -= timer_start.tv_nsec; \
                        if (__timer.tv_nsec < 0) { \
+
if (__timer.tv_nsec < 0) { \
                                __timer.tv_sec--; \
+
__timer.tv_sec--; \
                                __timer.tv_nsec += 1000000000; \
+
__timer.tv_nsec += 1000000000; \
                        } \
+
} \
                        if ((v)) *((long long int*)(v)) = (__timer.tv_sec * 1000000000) + __timer.tv_nsec; \
+
if ((v)) *((long long int*)(v)) = (__timer.tv_sec * 1000000000) + __timer.tv_nsec; \
                        if ((p)) memcpy(((struct timespec*)(p)), &__timer, sizeof(__timer)); \
+
if ((p)) memcpy(((struct timespec*)(p)), &__timer, sizeof(__timer)); \
                }
+
}
  
 
#define TIMER_PRINT_HERE(fmt, ...) \
 
#define TIMER_PRINT_HERE(fmt, ...) \
                TIMER_PRINT_HERE2("PRINT", fmt, __VA_ARGS__);
+
TIMER_PRINT_HERE2("PRINT", fmt, __VA_ARGS__);
  
 
#define TIMER_PRINT_HERE2(type, fmt, ...) \
 
#define TIMER_PRINT_HERE2(type, fmt, ...) \
                {       struct timespec timer_diff; \
+
{ struct timespec timer_diff; \
                        TIMER_DIFF_HERE(NULL, &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__); \
+
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) \
 
#define TIMER_SPEED_HERE(label, size) \
                {       unsigned long diff; \
+
{ unsigned long diff; \
                        float speed; \
+
float speed; \
                        TIMER_DIFF_HERE(&diff, NULL); \
+
TIMER_DIFF_HERE(&diff, NULL); \
                        speed = diff; \
+
speed = diff; \
                        speed /= 1000; \
+
speed /= 1000; \
                        speed = size / speed; \
+
speed = size / speed; \
                        fprintf(stderr, "===== SPEED (%s): %d byes in %dns -> %.2f MB/s\n", label, size, diff, speed); \
+
fprintf(stderr, "===== SPEED (%s): %d bytes in %dns -> %.2f MB/s\n", label, size, diff, speed); \
                }
+
}
  
#define TIMER_END_HERE(fmt, ...) \
+
#define TIMER_END_HERE() \
                TIMER_PRINT_HERE2("END", fmt, __VA_ARGS__); \
+
TIMER_PRINT_HERE2("END", "", 0); \
        }
+
}
  
 +
#define TIMER_END_HERE2(fmt, ...) \
 +
TIMER_PRINT_HERE2("END", fmt, __VA_ARGS__); \
 +
}
 +
 +
#define TIMER_END_QUIET() \
 +
}
  
 
#endif /* TIMER_H */
 
#endif /* TIMER_H */
 +
</source>
 +
 +
== For use in the Linux kernel source ==
 +
<source lang="c">
 +
#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 */
 
</source>
 
</source>

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 since TIMER_START_HERE in either a long long int (as nanoseconds), or in a struct 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 as TIMER_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 */
Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox