Last active
December 27, 2015 08:29
-
-
Save tanakamura/7297025 to your computer and use it in GitHub Desktop.
fast-printf
This file contains hidden or 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 <windows.h> | |
#include <stdio.h> | |
#include <ctype.h> | |
#ifdef _WIN32 | |
#include <windows.h> | |
double | |
sec() | |
{ | |
LARGE_INTEGER freq, v; | |
QueryPerformanceFrequency(&freq); | |
QueryPerformanceCounter(&v); | |
return v.QuadPart / (double)freq.QuadPart; | |
} | |
#else | |
#include <sys/time.h> | |
#include <fcntl.h> | |
double | |
sec() | |
{ | |
struct timeval tv; | |
gettimeofday(&tv, NULL); | |
return tv.tv_sec + tv.tv_usec / 1000000.0; | |
} | |
#endif | |
#define BUFSIZE 16384 | |
typedef struct printf_output_ { | |
char *buffer; /* +0 */ | |
int cur; /* +4 */ | |
HANDLE fd; | |
int bufsize; | |
} printf_output; | |
printf_output * | |
printf_open(const char *path) | |
{ | |
printf_output *ret; | |
HANDLE h = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); | |
if (h == INVALID_HANDLE_VALUE) { | |
return NULL; | |
} | |
ret = malloc(sizeof(*ret)); | |
ret->fd = h; | |
ret->cur = 0; | |
ret->bufsize = BUFSIZE; | |
ret->buffer = malloc(BUFSIZE); | |
return ret; | |
} | |
int write_total; | |
printf_output *log_file; | |
FILE *log_file2; | |
static void | |
flush(printf_output *out) | |
{ | |
WriteFile(out->fd, out->buffer, out->cur, NULL, NULL); | |
out->cur = 0; | |
} | |
void | |
printf_close(printf_output *out) | |
{ | |
flush(out); | |
CloseHandle(out->fd); | |
free(out->buffer); | |
free(out); | |
} | |
static __inline void | |
output(int len, printf_output *out, const char *data) | |
{ | |
#if 0 | |
/* len = ecx | |
* out = edx | |
* data = sp[4] */ | |
__asm { | |
mov esi, [esp+4]; /* data */ | |
push edi; | |
push esi; | |
mov edi, [edx]; /* out->buffer */ | |
mov eax, [edx+4]; /* out->cur */ | |
add edi, eax; /* edi = buffer + cur */ | |
add eax, ecx; /* cur += len */ | |
/* ecx = len */ | |
rep movsb; | |
mov [edx+4], eax; /* out->cur = cur */ | |
pop esi; | |
pop edi; | |
ret 4; | |
} | |
#else | |
int i; | |
unsigned char *dst = (unsigned char*)out->buffer + out->cur; | |
//memcpy(dst, data, len); | |
//isdigit(data[0]); | |
for (i=0; i<len; i++) { | |
dst[i] = data[i]; | |
} | |
out->cur += len; | |
#endif | |
} | |
static void | |
reserve(printf_output *out, int len) | |
{ | |
int bufsize = out->bufsize; | |
int cur = out->cur; | |
int rem = bufsize - cur; | |
if (len <= rem) { | |
return; | |
} | |
flush(out); | |
if (len >= bufsize) { | |
bufsize = len * 2; | |
free(out->buffer); | |
out->buffer = malloc(bufsize); | |
} | |
} | |
//int __declspec(noinline) | |
//fast_fprintf(printf_output *out, | |
// const char *fmt, | |
// ...) | |
//{ | |
// //int len = strlen(fmt); | |
// int len = 17; | |
// | |
// reserve(out, len); | |
// output(out, (unsigned char*)fmt, len); | |
// | |
// return len; | |
//} | |
static int | |
output_digit(printf_output *out, int v) | |
{ | |
char buffer[32]; | |
int cur = 31; | |
int neg = 0; | |
int len; | |
if (v < 0) { | |
neg = 1; | |
v = -v; | |
} | |
while (v>=10) { | |
int out = v%10; | |
buffer[cur--] = out + '0'; | |
v /= 10; | |
} | |
buffer[cur--] = v + '0'; | |
if (neg) { | |
buffer[cur--] = '-'; | |
} | |
len = 31-cur; | |
reserve(out, len); | |
output(len, out, buffer + cur + 1); | |
return len; | |
} | |
static int | |
output_hex(printf_output *out, unsigned int v) | |
{ | |
char buffer[32]; | |
int cur = 31; | |
static const char tbl[] = "0123456789abcdef"; | |
int len; | |
while (v>=16) { | |
int out = v&15; | |
buffer[cur--] = tbl[out]; | |
v >>= 4; | |
} | |
buffer[cur--] = tbl[v]; | |
len = 31-cur; | |
reserve(out, len); | |
output(len, out, buffer + cur + 1); | |
return len; | |
} | |
int __declspec(noinline) | |
fast_fprintf(printf_output *out, | |
const char *fmt, | |
int v0, int v1, int v2) | |
{ | |
int len = 2 + 3 + 5 + 1; | |
reserve(out, 2); | |
output(2, out, "x="); | |
len += output_digit(out, v0); | |
reserve(out, 3); | |
output(3, out, " y="); | |
len += output_digit(out, v1); | |
reserve(out, 5); | |
output(5, out, " sum="); | |
len += output_digit(out, v2); | |
reserve(out, 1); | |
output(1, out, "\n"); | |
return len; | |
} | |
int | |
sum_printf2(unsigned char *data, int w, int h) | |
{ | |
int ret = 0; | |
int xi, yi; | |
for (yi=0; yi<h; yi++) { | |
for (xi=0; xi<w; xi++) { | |
ret += data[yi*w + xi]; | |
//isdigit((char)ret); | |
write_total += fast_fprintf(log_file, "x=%d y=%d sum=%d\n", xi, yi, ret); | |
//write_total += fprintf(log_file2, "x=%d y=%d sum=%d\n", xi, yi, ret); | |
} | |
} | |
return ret; | |
} | |
int main(int argc, char **argv) | |
{ | |
unsigned char *data; | |
int w = 640, h = 480; | |
int v; | |
double start, end; | |
int i; | |
if (argc >= 3) { | |
w = atoi(argv[1]); | |
h = atoi(argv[2]); | |
} | |
log_file = printf_open("log.txt"); | |
log_file2 = fopen("log2.txt", "w"); | |
data = malloc(w*h); | |
memset(data, 0, w*h); | |
for (i=0; i<5; i++) { | |
double dt; | |
const char *name = "??"; | |
write_total = 0; | |
start = sec(); | |
v = sum_printf2(data, w, h); | |
name = "printf2"; | |
end = sec(); | |
dt = end-start; | |
printf("%10s: %d %d %d %f[usec] %f[nsec/byte]\n", name, w, h, v, dt*1000*1000.0, dt/(write_total)*1000*1000*1000.0); | |
} | |
printf_close(log_file); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment