Make strcmp do four byte comparisons on aligned strings.

Used libMicro's strcmp test to evaluate performance:
OPTS="-E -C 200 -S -W"
bin/strcmp	$OPTS -N "strcmp_10"	-s 10	-I 10
bin/strcmp	$OPTS -N "strcmp_100"	-s 100	-I 20
bin/strcmp	$OPTS -N "strcmp_1k"	-s 1k	-I 50
bin/strcmp	$OPTS -N "strcmp_10k"	-s 10k	-I 800
bin/strcmp	$OPTS -N "strcmp_1m"	-s 1m   -I 500000
bin/strcmp	$OPTS -N "strcmp_10m"	-s 10m  -I 5000000

Before:
             prc thr   usecs/call      samples   errors cnt/samp     size
strcmp_10      1   1      0.02510          201        0    10000       10
strcmp_100     1   1      0.17520          169        0     5000      100
strcmp_1k      1   1      1.67700          177        0     2000     1024
strcmp_10k     1   1     17.24800          194        0      125    10240
strcmp_1m      1   1  17892.00000          160        0        1  1048576
strcmp_10m     1   1 183136.00000          201        0        1 10485760

After:
strcmp_10      1   1      0.01800          194        0    10000       10
strcmp_100     1   1      0.13540          190        0     5000      100
strcmp_1k      1   1      1.24950          188        0     2000     1024
strcmp_10k     1   1     12.85600          190        0      125    10240
strcmp_1m      1   1  12930.00000          170        0        1  1048576
strcmp_10m     1   1 134382.00000          195        0        1 10485760
This commit is contained in:
Fredrik Holmqvist
2012-08-19 11:39:16 +02:00
parent a1efcf2c7f
commit ac827a2baa
+17
View File
@@ -6,11 +6,28 @@
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <SupportDefs.h>
#define LACKS_ZERO_BYTE(value) \
(((value - 0x01010101) & ~value & 0x80808080) == 0)
int int
strcmp(char const *a, char const *b) strcmp(char const *a, char const *b)
{ {
/* Make sure we don't pass page boundries on a or b when doing four byte
comparisons */
if ((((addr_t)a) & 3) == 0 && (((addr_t)b) && 3) == 0) {
uint32* a32 = (uint32*)a;
uint32* b32 = (uint32*)b;
while (LACKS_ZERO_BYTE(*a32)) {
int32 cmp = *a32++ - *b32++;
if (cmp != 0)
return cmp;
}
return *a32 - *b32;
}
while (true) { while (true) {
int cmp = (unsigned char)*a - (unsigned char)*b++; int cmp = (unsigned char)*a - (unsigned char)*b++;
if (cmp != 0 || *a++ == '\0') if (cmp != 0 || *a++ == '\0')