Skip to content

Instantly share code, notes, and snippets.

@kazuho
Created October 2, 2014 01:06
Show Gist options
  • Save kazuho/1f64c62e5f059954ead2 to your computer and use it in GitHub Desktop.
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
$ 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