Created
October 2, 2014 01:06
-
-
Save kazuho/1f64c62e5f059954ead2 to your computer and use it in GitHub Desktop.
converting an IPv4 address to string would become x7.6 faster if the format string of sprintf was parsed at compile-time
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
$ cat ipv4addr.c | |
#include <stdio.h> | |
struct ct_printf_t { | |
char *str; | |
size_t off; | |
}; | |
struct ct_printf_t ct_printf_init(char *str) | |
{ | |
struct ct_printf_t ret; | |
ret.str = str; | |
ret.off = 0; | |
return ret; | |
} | |
struct ct_printf_t ct_printf_c(struct ct_printf_t ctx, const char c) | |
{ | |
ctx.str[ctx.off++] = c; | |
return ctx; | |
} | |
struct ct_printf_t ct_printf_u(struct ct_printf_t ctx, unsigned v) | |
{ | |
char tmp[10]; | |
int i = sizeof(tmp); | |
if (v == 0) { | |
ctx.str[ctx.off++] = '0'; | |
return ctx; | |
} | |
do { | |
tmp[--i] = '0' + v % 10; | |
} while ((v /= 10) != 0); | |
do { | |
ctx.str[ctx.off++] = tmp[i++]; | |
} while (i != sizeof(tmp)); | |
return ctx; | |
} | |
int main(int argc, char **argv) | |
{ | |
char buf[sizeof("255.255.255.255")]; | |
int i; | |
unsigned addr; | |
if (sscanf(argv[1], "%u", &addr) != 1) { | |
fprintf(stderr, "usage: %s <addr-as-number>\n", argv[0]); | |
return 1; | |
} | |
for (i = 0; i != 10000000; ++i) { | |
#ifdef USE_SPRINTF | |
sprintf(buf, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); | |
#else | |
ct_printf_u(ct_printf_c(ct_printf_u(ct_printf_c(ct_printf_u(ct_printf_c(ct_printf_u( | |
ct_printf_init(buf), | |
(addr >> 24) & 0xff), | |
'.'), | |
(addr >> 16) & 0xff), | |
'.'), | |
(addr >> 8) & 0xff), | |
'.'), | |
addr & 0xff).off; | |
#endif | |
} | |
printf("result: %s\n", buf); | |
return 0; | |
} | |
$ gcc -DUSE_SPRINTF -O2 ipv4addr.c && time ./a.out 1234567890 | |
result: 73.150.2.210 | |
real 0m2.110s | |
user 0m2.112s | |
sys 0m0.000s | |
$ gcc -O2 ipv4addr.c && time ./a.out 1234567890 | |
result: 73.150.2.210 | |
real 0m0.275s | |
user 0m0.274s | |
sys 0m0.002s |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment