Home | History | Annotate | Line # | Download | only in bench
      1 /*	$NetBSD: ascii.c,v 1.2 2025/01/26 16:25:47 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 #include <stdbool.h>
     17 #include <stdint.h>
     18 #include <stdio.h>
     19 #include <string.h>
     20 
     21 #include <isc/ascii.h>
     22 #include <isc/random.h>
     23 #include <isc/time.h>
     24 
     25 #define SIZE (1024 * 1024)
     26 
     27 typedef void
     28 copy_fn(void *a, void *b, unsigned int len);
     29 
     30 static void
     31 time_it(copy_fn *copier, void *a, void *b, const char *name) {
     32 	isc_time_t start;
     33 	start = isc_time_now_hires();
     34 
     35 	copier(a, b, SIZE);
     36 
     37 	isc_time_t finish;
     38 	finish = isc_time_now_hires();
     39 
     40 	uint64_t microseconds = isc_time_microdiff(&finish, &start);
     41 	printf("%f for %s\n", (double)microseconds / 1000000.0, name);
     42 }
     43 
     44 static void
     45 copy_raw(void *a, void *b, unsigned int size) {
     46 	memmove(a, b, size);
     47 }
     48 
     49 static void
     50 copy_toupper(void *va, void *vb, unsigned int size) {
     51 	uint8_t *a = va, *b = vb;
     52 	while (size-- > 0) {
     53 		*a++ = isc_ascii_toupper(*b++);
     54 	}
     55 }
     56 
     57 static void
     58 copy_tolower8(void *a, void *b, unsigned int size) {
     59 	isc_ascii_lowercopy(a, b, size);
     60 }
     61 
     62 #define TOLOWER(c) ((c) + ('a' - 'A') * (((c) >= 'A') ^ ((c) > 'Z')))
     63 
     64 static void
     65 copy_tolower1(void *va, void *vb, unsigned int size) {
     66 	for (uint8_t *a = va, *b = vb; size-- > 0; a++, b++) {
     67 		*a = TOLOWER(*b);
     68 	}
     69 }
     70 
     71 static bool
     72 cmp_tolower1(void *va, void *vb, unsigned int size) {
     73 	for (uint8_t *a = va, *b = vb; size-- > 0; a++, b++) {
     74 		if (TOLOWER(*a) != TOLOWER(*b)) {
     75 			return false;
     76 		}
     77 	}
     78 	return true;
     79 }
     80 
     81 static bool oldskool_result;
     82 
     83 static void
     84 cmp_oldskool(void *va, void *vb, unsigned int size) {
     85 	uint8_t *a = va, *b = vb, c;
     86 
     87 	while (size > 3) {
     88 		c = isc_ascii_tolower(a[0]);
     89 		if (c != isc_ascii_tolower(b[0])) {
     90 			goto diff;
     91 		}
     92 		c = isc_ascii_tolower(a[1]);
     93 		if (c != isc_ascii_tolower(b[1])) {
     94 			goto diff;
     95 		}
     96 		c = isc_ascii_tolower(a[2]);
     97 		if (c != isc_ascii_tolower(b[2])) {
     98 			goto diff;
     99 		}
    100 		c = isc_ascii_tolower(a[3]);
    101 		if (c != isc_ascii_tolower(b[3])) {
    102 			goto diff;
    103 		}
    104 		size -= 4;
    105 		a += 4;
    106 		b += 4;
    107 	}
    108 	while (size-- > 0) {
    109 		c = isc_ascii_tolower(*a++);
    110 		if (c != isc_ascii_tolower(*b++)) {
    111 			goto diff;
    112 		}
    113 	}
    114 	oldskool_result = true;
    115 	return;
    116 diff:
    117 	oldskool_result = false;
    118 	return;
    119 }
    120 
    121 static bool tolower1_result;
    122 
    123 static void
    124 vcmp_tolower1(void *a, void *b, unsigned int size) {
    125 	tolower1_result = cmp_tolower1(a, b, size);
    126 }
    127 
    128 static bool swar_result;
    129 
    130 static void
    131 cmp_swar(void *a, void *b, unsigned int size) {
    132 	swar_result = isc_ascii_lowerequal(a, b, size);
    133 }
    134 
    135 static bool chunk_result;
    136 static unsigned int chunk_size;
    137 
    138 static void
    139 cmp_chunks1(void *va, void *vb, unsigned int size) {
    140 	uint8_t *a = va, *b = vb;
    141 
    142 	chunk_result = false;
    143 	while (size >= chunk_size) {
    144 		if (!cmp_tolower1(a, b, chunk_size)) {
    145 			return;
    146 		}
    147 		size -= chunk_size;
    148 		a += chunk_size;
    149 		b += chunk_size;
    150 	}
    151 	chunk_result = cmp_tolower1(a, b, size);
    152 }
    153 
    154 static void
    155 cmp_chunks8(void *va, void *vb, unsigned int size) {
    156 	uint8_t *a = va, *b = vb;
    157 
    158 	while (size >= chunk_size) {
    159 		if (!isc_ascii_lowerequal(a, b, chunk_size)) {
    160 			goto diff;
    161 		}
    162 		size -= chunk_size;
    163 		a += chunk_size;
    164 		b += chunk_size;
    165 	}
    166 	chunk_result = isc_ascii_lowerequal(a, b, size);
    167 	return;
    168 diff:
    169 	chunk_result = false;
    170 	return;
    171 }
    172 
    173 static void
    174 cmp_oldchunks(void *va, void *vb, unsigned int size) {
    175 	uint8_t *a = va, *b = vb;
    176 
    177 	while (size >= chunk_size) {
    178 		cmp_oldskool(a, b, chunk_size);
    179 		if (!oldskool_result) {
    180 			return;
    181 		}
    182 		size -= chunk_size;
    183 		a += chunk_size;
    184 		b += chunk_size;
    185 	}
    186 	cmp_oldskool(a, b, size);
    187 }
    188 
    189 int
    190 main(void) {
    191 	static uint8_t bytes[SIZE];
    192 
    193 	isc_random_buf(bytes, SIZE);
    194 
    195 	static uint8_t raw_dest[SIZE];
    196 	time_it(copy_raw, raw_dest, bytes, "memmove");
    197 
    198 	static uint8_t toupper_dest[SIZE];
    199 	time_it(copy_toupper, toupper_dest, bytes, "toupper");
    200 
    201 	static uint8_t tolower1_dest[SIZE];
    202 	time_it(copy_tolower1, tolower1_dest, bytes, "tolower1");
    203 
    204 	static uint8_t tolower8_dest[SIZE];
    205 	time_it(copy_tolower8, tolower8_dest, bytes, "tolower8");
    206 
    207 	time_it(cmp_oldskool, toupper_dest, tolower1_dest, "oldskool");
    208 	printf("-> %s\n", oldskool_result ? "same" : "WAT");
    209 
    210 	time_it(vcmp_tolower1, tolower1_dest, tolower8_dest, "tolower1");
    211 	printf("-> %s\n", tolower1_result ? "same" : "WAT");
    212 
    213 	time_it(cmp_swar, toupper_dest, tolower8_dest, "swar");
    214 	printf("-> %s\n", swar_result ? "same" : "WAT");
    215 
    216 	for (chunk_size = 3; chunk_size <= 15; chunk_size += 2) {
    217 		time_it(cmp_chunks1, toupper_dest, raw_dest, "chunks1");
    218 		printf("%u -> %s\n", chunk_size, chunk_result ? "same" : "WAT");
    219 		time_it(cmp_chunks8, toupper_dest, raw_dest, "chunks8");
    220 		printf("%u -> %s\n", chunk_size, chunk_result ? "same" : "WAT");
    221 		time_it(cmp_oldchunks, toupper_dest, raw_dest, "oldchunks");
    222 		printf("%u -> %s\n", chunk_size,
    223 		       oldskool_result ? "same" : "WAT");
    224 	}
    225 }
    226