Created
September 27, 2014 16:30
-
-
Save mopp/1ce461fc3e9d98b9dbf3 to your computer and use it in GitHub Desktop.
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 <stddef.h> | |
#include <stdint.h> | |
#include <stdbool.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <time.h> | |
#include <sys/time.h> | |
double gettimeofday_sec() { | |
struct timeval tv; | |
gettimeofday(&tv, NULL); | |
return tv.tv_sec + tv.tv_usec * 1e-6; | |
} | |
static void* memset0(void* s, int c, size_t n) { | |
if (n != 0) { | |
register uintptr_t addr = (uintptr_t)s; | |
register uintptr_t t = addr + n; | |
if (((addr | n) & 1) == 0) { | |
for (unsigned int val = (uint8_t)c | (uint8_t)c << 8; addr < t; addr += sizeof(uint16_t)) { | |
*(uint16_t*)addr = val; | |
} | |
} | |
for (; addr < t; ++addr) | |
*(uint8_t*)addr = c; | |
} | |
return s; | |
} | |
static void* memset0_no(void* s, int c, size_t n) { | |
if (n != 0) { | |
uintptr_t addr = (uintptr_t)s; | |
uintptr_t t = addr + n; | |
if (((addr | n) & 1) == 0) { | |
for (unsigned int val = (uint8_t)c | (uint8_t)c << 8; addr < t; addr += sizeof(uint16_t)) { | |
*(uint16_t*)addr = val; | |
} | |
} | |
for (; addr < t; ++addr) | |
*(uint8_t*)addr = c; | |
} | |
return s; | |
} | |
static void* memset1(void* buf, int ch, size_t n) { | |
unsigned char* t = (unsigned char*)buf; | |
while (0 < n--) { | |
*t++ = (unsigned char const)ch; | |
} | |
return buf; | |
} | |
static void* memset2(void* s, int c, size_t n) { | |
if (s == NULL) { | |
return s; | |
} | |
register uintptr_t itr = (uintptr_t)s; | |
register uintptr_t end = itr + n; | |
uint8_t const uc = (uint8_t const)c; | |
if (((itr | n) & 0x3) == 0) { | |
register uint32_t v = ((uc << 24) | (uc << 16) | (uc << 8) | uc); | |
while (itr < end) { | |
*(uint32_t*)(itr++) = v; | |
itr += sizeof(uint32_t); | |
} | |
} else if (((itr | n) & 0x1) == 0) { | |
/* word */ | |
register uint16_t v = ((uc << 8) | uc); | |
while (itr < end) { | |
*(uint16_t*)(itr++) = v; | |
itr += sizeof(uint16_t); | |
} | |
} | |
/* byte */ | |
while (itr < end) { | |
*(uint8_t*)(itr++) = uc; | |
} | |
return s; | |
} | |
bool validate(register uint8_t* s, register uint8_t c, size_t n) { | |
register uint8_t* e = s + n; | |
while (s < e) { | |
if (*s++ != c) { | |
printf("%p\n", s); | |
return false; | |
} | |
} | |
return true; | |
} | |
void worker(void* (*f)(void*, int, size_t), void* s, int c, size_t n) { | |
static size_t const times = 10; | |
double t1, t2; | |
double ts = 0; | |
for (size_t i = 0; i < 10; i++) { | |
t1 = gettimeofday_sec(); | |
f(s, c, n); | |
t2 = gettimeofday_sec(); | |
double t3 = t2 - t1; | |
printf(" %f\n", t3); | |
ts += t3; | |
if (validate(s, 0xff & c, n) == false) { | |
printf("Validation false !\n"); | |
} | |
} | |
double avg = ts / times; | |
printf(" Avg. %f\n", avg); | |
} | |
int main(void) { | |
static size_t const n = 32 * 1024 * 1024 + 1; | |
void* s = malloc(n); | |
printf("memset 0\n"); | |
worker(memset0, s, 6, n); | |
printf("memset 0 no register\n"); | |
worker(memset0_no, s, 6, n); | |
printf("memset 1\n"); | |
worker(memset1, s, 6, n); | |
printf("memset 2\n"); | |
worker(memset2, s, 6, n); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment