Created
April 30, 2013 20:42
-
-
Save iwillspeak/5491786 to your computer and use it in GitHub Desktop.
Comparison of the speed of accessing various C structures The timer code is from bitbucket.org/iwillspeak/moonbase
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <inttypes.h> | |
#include "timer.h" | |
struct aligned { | |
uint32_t o:8; | |
uint32_t d:8; | |
uint32_t s1:8; | |
uint32_t s2:8; | |
}; | |
typedef struct aligned aligned_t; | |
static_assert(sizeof(aligned_t) == 4, opcode should be four bytes); | |
void test_aligned_bitfield(const int iterations) | |
{ | |
aligned_t thing = {0}; | |
for (int i = 0; i < iterations; ++i) { | |
thing.o++; | |
thing.d++; | |
thing.s1++; | |
thing.s2++; | |
} | |
} | |
struct unaligned { | |
uint32_t o:6; | |
uint32_t d:5; | |
uint32_t s1:5; | |
uint32_t s2:5; | |
uint32_t padding:11; | |
}; | |
typedef struct unaligned unaligned_t; | |
void test_unaligned_bitfield(const int iterations) | |
{ | |
unaligned_t thing = {0}; | |
for (int i = 0; i < iterations; ++i) { | |
thing.o++; | |
thing.d++; | |
thing.s1++; | |
thing.s2++; | |
} | |
} | |
void test_array(const int iterations) | |
{ | |
uint8_t thing[4] = {0}; | |
for (int i = 0; i < iterations; ++i) { | |
thing[0]++; | |
thing[1]++; | |
thing[2]++; | |
thing[3]++; | |
} | |
} | |
struct bytestruct { | |
uint8_t o, d, s1, s2; | |
}; | |
typedef struct bytestruct bytestruct_t; | |
void test_struct(const int iterations) | |
{ | |
bytestruct_t thing; | |
for (int i = 0; i < iterations; ++i) { | |
thing.o++; | |
thing.d++; | |
thing.s1++; | |
thing.s2++; | |
} | |
} | |
int main(int argc, char* argv[]) | |
{ | |
static const int iterations = 100000; | |
Timer* timer; | |
uintmax_t aligned, unaligned, array, struc; | |
timer = timerCreate(); | |
test_aligned_bitfield(iterations); | |
aligned = timerGetMicrosecondDelta(timer); | |
test_unaligned_bitfield(iterations); | |
unaligned = timerGetMicrosecondDelta(timer); | |
test_array(iterations); | |
array = timerGetMicrosecondDelta(timer); | |
test_struct(iterations); | |
struc = timerGetMicrosecondDelta(timer); | |
free(timer); | |
printf("a\tu\tc\ts\n"); | |
printf("%zu\t%zu\t%zu\t%zu\n", sizeof(aligned_t), sizeof(unaligned_t), | |
sizeof(uint8_t) * 4, sizeof(bytestruct_t)); | |
printf("%"PRIuMAX"\t%"PRIuMAX"\t%"PRIuMAX"\t%"PRIuMAX"\n", | |
aligned, unaligned, array, struc); | |
exit(EXIT_SUCCESS); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "timer.h" | |
#include <stdlib.h> | |
#include <stdio.h> | |
Timer* timerCreate(void) { | |
Timer* t = calloc(1, sizeof(Timer)); | |
timerReset(t); | |
return t; | |
} | |
void timerReset(Timer* timer) { | |
#ifdef __MACH__ | |
gettimeofday(&timer->zero, NULL); | |
#else | |
clock_gettime(CLOCK_MONOTONIC, &timer->zero); | |
#endif | |
} | |
unsigned long timerGetMicroseconds(Timer* timer) { | |
#ifdef __MACH__ | |
struct timeval now; | |
gettimeofday(&now, NULL); | |
return (now.tv_sec-timer->zero.tv_sec)*1000000+(now.tv_usec-timer->zero.tv_usec); | |
#else | |
struct timespec now; | |
clock_gettime(CLOCK_MONOTONIC, &now); | |
return (now.tv_sec-timer->zero.tv_sec)*1000000+(now.tv_nsec-timer->zero.tv_nsec)/1000 ; | |
#endif | |
} | |
unsigned long timerGetMicrosecondDelta(Timer* timer) { | |
unsigned long delta; | |
delta = timerGetMicroseconds(timer); | |
timerReset(timer); | |
return delta; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __TIMER_HEADER__ | |
#define __TIMER_HEADER__ | |
#ifdef __MACH__ | |
#include <sys/time.h> | |
#else | |
#include <time.h> | |
#endif | |
typedef struct Timer_s { | |
#ifdef __MACH__ | |
struct timeval zero; | |
#else | |
struct timespec zero; | |
#endif | |
} Timer; | |
#define smooth(value, delta) (((float)(value)/(float)1000000) * (float)(delta)) | |
/** | |
* Reset the timer | |
* | |
* Delta time values measured will be from the calling of this | |
* method. | |
* | |
* @param timer to reset | |
*/ | |
void timerReset(Timer* timer); | |
/** | |
* Creates a new timer | |
* | |
* @return timer pointer | |
*/ | |
Timer* timerCreate(void); | |
/** | |
* Return the number of microseconds since the timer was reset | |
* | |
* The amount of time since the timer was reset or the last delta was | |
* read is returned. | |
* | |
* @param timer to read | |
* @return time since reset in microseconds | |
*/ | |
unsigned long timerGetMicroseconds(Timer* timer); | |
/** | |
* Gets the delta and resets a timer | |
* | |
* The amount of time since the timer was reset or the last delta was | |
* read is returned and the timer is reset. | |
* | |
* @param timer to read | |
* @return delata in microseconds | |
*/ | |
unsigned long timerGetMicrosecondDelta(Timer* timer); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is the result of compiling and running the above three files on OS X 10.8 with Clang:
And with gcc:
I am interested in the relative speeds on various other platforms.