From 5c6572c422a2dc3a8349c4f0f9f6ab31de9c5528 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Fri, 8 Nov 2024 18:51:54 +0100 Subject: [PATCH 1/2] Lib: Optimized printing of IP addresses Makes printing network prefixes ~15x faster. --- lib/ip.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++----- lib/ip.h | 5 ++++ lib/net.c | 2 +- 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/lib/ip.c b/lib/ip.c index 4b28451c..e62f9f53 100644 --- a/lib/ip.c +++ b/lib/ip.c @@ -205,20 +205,88 @@ ip6_shift_right(ip6_addr a, uint bits) } -/* - * Conversion of IPv6 address to presentation format and vice versa. - * Heavily inspired by routines written by Paul Vixie for the BIND project - * and of course by RFC 2373. - */ +static const char numbers[] = { + '0', 0, 0, 0, '1', 0, 0, 0, '2', 0, 0, 0, '3', 0, 0, 0, '4', 0, 0, 0, '5', 0, 0, 0, '6', 0, 0, 0, '7', 0, 0, 0, + '8', 0, 0, 0, '9', 0, 0, 0, '1', '0', 0, 0, '1', '1', 0, 0, '1', '2', 0, 0, '1', '3', 0, 0, '1', '4', 0, 0, '1', '5', 0, 0, + '1', '6', 0, 0, '1', '7', 0, 0, '1', '8', 0, 0, '1', '9', 0, 0, '2', '0', 0, 0, '2', '1', 0, 0, '2', '2', 0, 0, '2', '3', 0, 0, + '2', '4', 0, 0, '2', '5', 0, 0, '2', '6', 0, 0, '2', '7', 0, 0, '2', '8', 0, 0, '2', '9', 0, 0, '3', '0', 0, 0, '3', '1', 0, 0, + '3', '2', 0, 0, '3', '3', 0, 0, '3', '4', 0, 0, '3', '5', 0, 0, '3', '6', 0, 0, '3', '7', 0, 0, '3', '8', 0, 0, '3', '9', 0, 0, + '4', '0', 0, 0, '4', '1', 0, 0, '4', '2', 0, 0, '4', '3', 0, 0, '4', '4', 0, 0, '4', '5', 0, 0, '4', '6', 0, 0, '4', '7', 0, 0, + '4', '8', 0, 0, '4', '9', 0, 0, '5', '0', 0, 0, '5', '1', 0, 0, '5', '2', 0, 0, '5', '3', 0, 0, '5', '4', 0, 0, '5', '5', 0, 0, + '5', '6', 0, 0, '5', '7', 0, 0, '5', '8', 0, 0, '5', '9', 0, 0, '6', '0', 0, 0, '6', '1', 0, 0, '6', '2', 0, 0, '6', '3', 0, 0, + '6', '4', 0, 0, '6', '5', 0, 0, '6', '6', 0, 0, '6', '7', 0, 0, '6', '8', 0, 0, '6', '9', 0, 0, '7', '0', 0, 0, '7', '1', 0, 0, + '7', '2', 0, 0, '7', '3', 0, 0, '7', '4', 0, 0, '7', '5', 0, 0, '7', '6', 0, 0, '7', '7', 0, 0, '7', '8', 0, 0, '7', '9', 0, 0, + '8', '0', 0, 0, '8', '1', 0, 0, '8', '2', 0, 0, '8', '3', 0, 0, '8', '4', 0, 0, '8', '5', 0, 0, '8', '6', 0, 0, '8', '7', 0, 0, + '8', '8', 0, 0, '8', '9', 0, 0, '9', '0', 0, 0, '9', '1', 0, 0, '9', '2', 0, 0, '9', '3', 0, 0, '9', '4', 0, 0, '9', '5', 0, 0, + '9', '6', 0, 0, '9', '7', 0, 0, '9', '8', 0, 0, '9', '9', 0, 0, '1', '0', '0', 0, '1', '0', '1', 0, '1', '0', '2', 0, '1', '0', '3', 0, + '1', '0', '4', 0, '1', '0', '5', 0, '1', '0', '6', 0, '1', '0', '7', 0, '1', '0', '8', 0, '1', '0', '9', 0, '1', '1', '0', 0, '1', '1', '1', 0, + '1', '1', '2', 0, '1', '1', '3', 0, '1', '1', '4', 0, '1', '1', '5', 0, '1', '1', '6', 0, '1', '1', '7', 0, '1', '1', '8', 0, '1', '1', '9', 0, + '1', '2', '0', 0, '1', '2', '1', 0, '1', '2', '2', 0, '1', '2', '3', 0, '1', '2', '4', 0, '1', '2', '5', 0, '1', '2', '6', 0, '1', '2', '7', 0, + '1', '2', '8', 0, '1', '2', '9', 0, '1', '3', '0', 0, '1', '3', '1', 0, '1', '3', '2', 0, '1', '3', '3', 0, '1', '3', '4', 0, '1', '3', '5', 0, + '1', '3', '6', 0, '1', '3', '7', 0, '1', '3', '8', 0, '1', '3', '9', 0, '1', '4', '0', 0, '1', '4', '1', 0, '1', '4', '2', 0, '1', '4', '3', 0, + '1', '4', '4', 0, '1', '4', '5', 0, '1', '4', '6', 0, '1', '4', '7', 0, '1', '4', '8', 0, '1', '4', '9', 0, '1', '5', '0', 0, '1', '5', '1', 0, + '1', '5', '2', 0, '1', '5', '3', 0, '1', '5', '4', 0, '1', '5', '5', 0, '1', '5', '6', 0, '1', '5', '7', 0, '1', '5', '8', 0, '1', '5', '9', 0, + '1', '6', '0', 0, '1', '6', '1', 0, '1', '6', '2', 0, '1', '6', '3', 0, '1', '6', '4', 0, '1', '6', '5', 0, '1', '6', '6', 0, '1', '6', '7', 0, + '1', '6', '8', 0, '1', '6', '9', 0, '1', '7', '0', 0, '1', '7', '1', 0, '1', '7', '2', 0, '1', '7', '3', 0, '1', '7', '4', 0, '1', '7', '5', 0, + '1', '7', '6', 0, '1', '7', '7', 0, '1', '7', '8', 0, '1', '7', '9', 0, '1', '8', '0', 0, '1', '8', '1', 0, '1', '8', '2', 0, '1', '8', '3', 0, + '1', '8', '4', 0, '1', '8', '5', 0, '1', '8', '6', 0, '1', '8', '7', 0, '1', '8', '8', 0, '1', '8', '9', 0, '1', '9', '0', 0, '1', '9', '1', 0, + '1', '9', '2', 0, '1', '9', '3', 0, '1', '9', '4', 0, '1', '9', '5', 0, '1', '9', '6', 0, '1', '9', '7', 0, '1', '9', '8', 0, '1', '9', '9', 0, + '2', '0', '0', 0, '2', '0', '1', 0, '2', '0', '2', 0, '2', '0', '3', 0, '2', '0', '4', 0, '2', '0', '5', 0, '2', '0', '6', 0, '2', '0', '7', 0, + '2', '0', '8', 0, '2', '0', '9', 0, '2', '1', '0', 0, '2', '1', '1', 0, '2', '1', '2', 0, '2', '1', '3', 0, '2', '1', '4', 0, '2', '1', '5', 0, + '2', '1', '6', 0, '2', '1', '7', 0, '2', '1', '8', 0, '2', '1', '9', 0, '2', '2', '0', 0, '2', '2', '1', 0, '2', '2', '2', 0, '2', '2', '3', 0, + '2', '2', '4', 0, '2', '2', '5', 0, '2', '2', '6', 0, '2', '2', '7', 0, '2', '2', '8', 0, '2', '2', '9', 0, '2', '3', '0', 0, '2', '3', '1', 0, + '2', '3', '2', 0, '2', '3', '3', 0, '2', '3', '4', 0, '2', '3', '5', 0, '2', '3', '6', 0, '2', '3', '7', 0, '2', '3', '8', 0, '2', '3', '9', 0, + '2', '4', '0', 0, '2', '4', '1', 0, '2', '4', '2', 0, '2', '4', '3', 0, '2', '4', '4', 0, '2', '4', '5', 0, '2', '4', '6', 0, '2', '4', '7', 0, + '2', '4', '8', 0, '2', '4', '9', 0, '2', '5', '0', 0, '2', '5', '1', 0, '2', '5', '2', 0, '2', '5', '3', 0, '2', '5', '4', 0, '2', '5', '5', 0, +}; +static inline char * +print_u8(char *s, u8 n) +{ + memcpy(s, numbers + n * 4, 4); + return s + 1 + (n >= 10) + (n >= 100); +} char * ip4_ntop(ip4_addr a, char *b) { u32 x = _I(a); - return b + bsprintf(b, "%d.%d.%d.%d", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff); + + b = print_u8(b, (x >> 24) & 0xff); + *b++ = '.'; + b = print_u8(b, (x >> 16) & 0xff); + *b++ = '.'; + b = print_u8(b, (x >> 8) & 0xff); + *b++ = '.'; + b = print_u8(b, x & 0xff); + + return b; } +char * +ip4_px_ntop(ip4_addr a, int len, char *b) +{ + u32 x = _I(a); + + b = print_u8(b, (x >> 24) & 0xff); + *b++ = '.'; + b = print_u8(b, (x >> 16) & 0xff); + *b++ = '.'; + b = print_u8(b, (x >> 8) & 0xff); + *b++ = '.'; + b = print_u8(b, x & 0xff); + *b++ = '/'; + b = print_u8(b, len & 0xff); + + return b; +} + + +/* + * Conversion of IPv6 address to presentation format and vice versa. + * Heavily inspired by routines written by Paul Vixie for the BIND project + * and of course by RFC 2373. + */ char * ip6_ntop(ip6_addr a, char *b) diff --git a/lib/ip.h b/lib/ip.h index 49f28079..661331ec 100644 --- a/lib/ip.h +++ b/lib/ip.h @@ -457,9 +457,14 @@ static inline void * put_ip6(void *buf, ip6_addr a) * Binary/text form conversions */ +#define IP4_BUFFER_SIZE 16 /* Required buffer for ip4_ntop() */ +#define IP4_PX_BUFFER_SIZE 20 /* Required buffer for ip4_ntop_px() */ + char *ip4_ntop(ip4_addr a, char *b); char *ip6_ntop(ip6_addr a, char *b); +char *ip4_px_ntop(ip4_addr a, int len, char *b); + static inline char * ip4_ntox(ip4_addr a, char *b) { return b + bsprintf(b, "%08x", _I(a)); } diff --git a/lib/net.c b/lib/net.c index 76bb3e80..3bd7bc67 100644 --- a/lib/net.c +++ b/lib/net.c @@ -100,7 +100,7 @@ net_format(const net_addr *N, char *buf, int buflen) switch (n->n.type) { case NET_IP4: - return bsnprintf(buf, buflen, "%I4/%d", n->ip4.prefix, n->ip4.pxlen); + return (buflen < IP4_PX_BUFFER_SIZE) ? -1 : ip4_px_ntop(n->ip4.prefix, n->ip4.pxlen, buf) - buf; case NET_IP6: return bsnprintf(buf, buflen, "%I6/%d", n->ip6.prefix, n->ip6.pxlen); case NET_VPN4: From 49be4a0329b218a7c35c9275680de3ca177cd2e7 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Fri, 8 Nov 2024 18:54:13 +0100 Subject: [PATCH 2/2] Lib: Optimized printing of numbers One simple trick makes printing of numbers ~4x faster. --- lib/printf.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/printf.c b/lib/printf.c index 424d545f..68d3bb74 100644 --- a/lib/printf.c +++ b/lib/printf.c @@ -73,10 +73,25 @@ static char * number(char * str, u64 num, uint base, int size, int precision, i = 0; if (num == 0) tmp[i++]='0'; - else while (num != 0) { - uint res = num % base; - num = num / base; - tmp[i++] = digits[res]; + else if (base == 10) { + /* Separate cases to have fixed divisors */ + while (num != 0) { + uint res = num % 10; + num = num / 10; + tmp[i++] = digits[res]; + } + } else if (base == 16) { + while (num != 0) { + uint res = num % 16; + num = num / 16; + tmp[i++] = digits[res]; + } + } else { + while (num != 0) { + uint res = num % base; + num = num / base; + tmp[i++] = digits[res]; + } } if (i > precision) precision = i;