Fix SSE memcmp functions reading beyond the buffer. Add tests to bench them.

remotes/origin/master-1.1.x
Victor Julien 15 years ago
parent 6be38123f0
commit 962462e470

@ -166,6 +166,162 @@ static int MemcmpTest13 (void) {
return 1;
}
#include "util-cpu.h"
#define TEST_RUNS 1000000
static int MemcmpTest14 (void) {
#ifdef PROFILING
uint64_t ticks_start = 0;
uint64_t ticks_end = 0;
char *a[] = { "0123456789012345", "abc", "abcdefghij", "suricata", "test", "xyz", "rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr", "abcdefghijklmnopqrstuvwxyz", NULL };
char *b[] = { "1234567890123456", "abc", "abcdefghik", "suricatb", "test", "xyz", "rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr", "abcdefghijklmnopqrstuvwxyz", NULL };
int t = 0;
int i, j;
int r1 = 0;
printf("\n");
ticks_start = UtilCpuGetTicks();
for (t = 0; t < TEST_RUNS; t++) {
for (i = 0; a[i] != NULL; i++) {
// printf("a[%d] = %s\n", i, a[i]);
size_t alen = strlen(a[i]) - 1;
for (j = 0; b[j] != NULL; j++) {
// printf("b[%d] = %s\n", j, b[j]);
size_t blen = strlen(b[j]) - 1;
r1 += (memcmp((uint8_t *)a[i], (uint8_t *)b[j], (alen < blen) ? alen : blen) ? 1 : 0);
}
}
}
ticks_end = UtilCpuGetTicks();
printf("memcmp(%d) \t\t\t%"PRIu64"\n", TEST_RUNS, ((uint64_t)(ticks_end - ticks_start))/TEST_RUNS);
SCLogInfo("ticks passed %"PRIu64, ticks_end - ticks_start);
printf("r1 %d\n", r1);
if (r1 != (51 * TEST_RUNS))
return 0;
#endif
return 1;
}
static int MemcmpTest15 (void) {
#ifdef PROFILING
uint64_t ticks_start = 0;
uint64_t ticks_end = 0;
char *a[] = { "0123456789012345", "abc", "abcdefghij", "suricata", "test", "xyz", "rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr", "abcdefghijklmnopqrstuvwxyz", NULL };
char *b[] = { "1234567890123456", "abc", "abcdefghik", "suricatb", "test", "xyz", "rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr", "abcdefghijklmnopqrstuvwxyz", NULL };
int t = 0;
int i, j;
int r2 = 0;
printf("\n");
ticks_start = UtilCpuGetTicks();
for (t = 0; t < TEST_RUNS; t++) {
for (i = 0; a[i] != NULL; i++) {
// printf("a[%d] = %s\n", i, a[i]);
size_t alen = strlen(a[i]) - 1;
for (j = 0; b[j] != NULL; j++) {
// printf("b[%d] = %s\n", j, b[j]);
size_t blen = strlen(b[j]) - 1;
r2 += MemcmpLowercase((uint8_t *)a[i], (uint8_t *)b[j], (alen < blen) ? alen : blen);
}
}
}
ticks_end = UtilCpuGetTicks();
printf("MemcmpLowercase(%d) \t\t%"PRIu64"\n", TEST_RUNS, ((uint64_t)(ticks_end - ticks_start))/TEST_RUNS);
SCLogInfo("ticks passed %"PRIu64, ticks_end - ticks_start);
printf("r2 %d\n", r2);
if (r2 != (51 * TEST_RUNS))
return 0;
#endif
return 1;
}
static int MemcmpTest16 (void) {
#ifdef PROFILING
uint64_t ticks_start = 0;
uint64_t ticks_end = 0;
char *a[] = { "0123456789012345", "abc", "abcdefghij", "suricata", "test", "xyz", "rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr", "abcdefghijklmnopqrstuvwxyz", NULL };
char *b[] = { "1234567890123456", "abc", "abcdefghik", "suricatb", "test", "xyz", "rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr", "abcdefghijklmnopqrstuvwxyz", NULL };
int t = 0;
int i, j;
int r3 = 0;
printf("\n");
ticks_start = UtilCpuGetTicks();
for (t = 0; t < TEST_RUNS; t++) {
for (i = 0; a[i] != NULL; i++) {
// printf("a[%d] = %s\n", i, a[i]);
size_t alen = strlen(a[i]) - 1;
for (j = 0; b[j] != NULL; j++) {
// printf("b[%d] = %s\n", j, b[j]);
size_t blen = strlen(b[j]) - 1;
r3 += SCMemcmp((uint8_t *)a[i], (uint8_t *)b[j], (alen < blen) ? alen : blen);
}
}
}
ticks_end = UtilCpuGetTicks();
printf("SCMemcmp(%d) \t\t\t%"PRIu64"\n", TEST_RUNS, ((uint64_t)(ticks_end - ticks_start))/TEST_RUNS);
SCLogInfo("ticks passed %"PRIu64, ticks_end - ticks_start);
printf("r3 %d\n", r3);
if (r3 != (51 * TEST_RUNS))
return 0;
#endif
return 1;
}
static int MemcmpTest17 (void) {
#ifdef PROFILING
uint64_t ticks_start = 0;
uint64_t ticks_end = 0;
char *a[] = { "0123456789012345", "abc", "abcdefghij", "suricata", "test", "xyz", "rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr", "abcdefghijklmnopqrstuvwxyz", NULL };
char *b[] = { "1234567890123456", "abc", "abcdefghik", "suricatb", "test", "xyz", "rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr", "abcdefghijklmnopqrstuvwxyz", NULL };
int t = 0;
int i, j;
int r4 = 0;
printf("\n");
ticks_start = UtilCpuGetTicks();
for (t = 0; t < TEST_RUNS; t++) {
for (i = 0; a[i] != NULL; i++) {
// printf("a[%d] = %s\n", i, a[i]);
size_t alen = strlen(a[i]) - 1;
for (j = 0; b[j] != NULL; j++) {
// printf("b[%d] = %s\n", j, b[j]);
size_t blen = strlen(b[j]) - 1;
r4 += SCMemcmpLowercase((uint8_t *)a[i], (uint8_t *)b[j], (alen < blen) ? alen : blen);
}
}
}
ticks_end = UtilCpuGetTicks();
printf("SCMemcmpLowercase(%d) \t\t%"PRIu64"\n", TEST_RUNS, ((uint64_t)(ticks_end - ticks_start))/TEST_RUNS);
SCLogInfo("ticks passed %"PRIu64, ticks_end - ticks_start);
printf("r4 %d\n", r4);
if (r4 != (51 * TEST_RUNS))
return 0;
#endif
return 1;
}
#endif /* UNITTESTS */
void MemcmpRegisterTests(void) {
@ -183,6 +339,10 @@ void MemcmpRegisterTests(void) {
UtRegisterTest("MemcmpTest11", MemcmpTest11, 1);
UtRegisterTest("MemcmpTest12", MemcmpTest12, 1);
UtRegisterTest("MemcmpTest13", MemcmpTest13, 1);
UtRegisterTest("MemcmpTest14", MemcmpTest14, 1);
UtRegisterTest("MemcmpTest15", MemcmpTest15, 1);
UtRegisterTest("MemcmpTest16", MemcmpTest16, 1);
UtRegisterTest("MemcmpTest17", MemcmpTest17, 1);
#endif /* UNITTESTS */
}

@ -29,6 +29,8 @@
#ifndef __UTIL_MEMCMP_H__
#define __UTIL_MEMCMP_H__
#include "util-optimize.h"
/** \brief compare two patterns, converting the 2nd to lowercase
* \warning *ONLY* the 2nd pattern is converted to lowercase
*/
@ -36,6 +38,21 @@ static inline int SCMemcmpLowercase(void *, void *, size_t);
void MemcmpRegisterTests(void);
static inline int
MemcmpLowercase(void *s1, void *s2, size_t n) {
size_t i;
/* check backwards because we already tested the first
* 2 to 4 chars. This way we are more likely to detect
* a miss and thus speed up a little... */
for (i = n - 1; i; i--) {
if (((uint8_t *)s1)[i] != u8_tolower(*(((uint8_t *)s2)+i)))
return 1;
}
return 0;
}
#if defined(__SSE4_2__)
#include <nmmintrin.h>
@ -121,6 +138,12 @@ static inline int SCMemcmp(void *s1, void *s2, size_t len) {
__m128i b1, b2, c;
do {
/* apparently we can't just read 16 bytes even though
* it almost always works fine :) */
if (likely(len + offset < 16)) {
return memcmp(s1, s2, len - offset) ? 1 : 0;
}
/* do unaligned loads using _mm_loadu_si128. On my Core2 E6600 using
* _mm_lddqu_si128 was about 2% slower even though it's supposed to
* be faster. */
@ -163,6 +186,12 @@ static inline int SCMemcmpLowercase(void *s1, void *s2, size_t len) {
uplow = _mm_set1_epi8(0x20);
do {
/* apparently we can't just read 16 bytes even though
* it almost always works fine :) */
if (likely(len + offset < 16)) {
return MemcmpLowercase(s1, s2, len - offset);
}
/* unaligned loading of the bytes to compare */
b1 = _mm_loadu_si128((const __m128i *) s1);
b2 = _mm_loadu_si128((const __m128i *) s2);
@ -217,6 +246,12 @@ static inline int SCMemcmp(void *s1, void *s2, size_t len) {
__m128i b1, b2, c;
do {
/* apparently we can't just read 16 bytes even though
* it almost always works fine :) */
if (likely(len + offset < 16)) {
return memcmp(s1, s2, len - offset) ? 1 : 0;
}
/* do unaligned loads using _mm_loadu_si128. On my Core2 E6600 using
* _mm_lddqu_si128 was about 2% slower even though it's supposed to
* be faster. */
@ -259,6 +294,12 @@ static inline int SCMemcmpLowercase(void *s1, void *s2, size_t len) {
delta = _mm_set1_epi8(UPPER_DELTA);
do {
/* apparently we can't just read 16 bytes even though
* it almost always works fine :) */
if (likely(len + offset < 16)) {
return MemcmpLowercase(s1, s2, len - offset);
}
/* unaligned loading of the bytes to compare */
b1 = _mm_loadu_si128((const __m128i *) s1);
b2 = _mm_loadu_si128((const __m128i *) s2);
@ -310,19 +351,8 @@ static inline int SCMemcmpLowercase(void *s1, void *s2, size_t len) {
memcmp((a), (b), (c)) ? 1 : 0; \
})
static inline int
SCMemcmpLowercase(void *s1, void *s2, size_t n) {
size_t i;
/* check backwards because we already tested the first
* 2 to 4 chars. This way we are more likely to detect
* a miss and thus speed up a little... */
for (i = n - 1; i; i--) {
if (((uint8_t *)s1)[i] != u8_tolower(*(((uint8_t *)s2)+i)))
return 1;
}
return 0;
static inline int SCMemcmpLowercase(void *s1, void *s2, size_t len) {
return MemcmpLowercase(s1, s2, len);
}
#endif /* SIMD */

Loading…
Cancel
Save