From 56790e9453263dca3ef80e061525b972ce6f44d8 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Tue, 5 Mar 2024 13:05:31 +0530 Subject: [PATCH] detect: optimize group head bitarray handling During startup large rulesets use a lot of large bitarrays, that are frequently merged (OR'd). Optimize this using SSE2 _mm_or_si128. (cherry picked from commit 94b4619) --- src/detect-engine-siggroup.c | 28 ++++++++++++++++++++++++---- src/suricata.c | 3 +++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/detect-engine-siggroup.c b/src/detect-engine-siggroup.c index dde000b49a..a87084916f 100644 --- a/src/detect-engine-siggroup.c +++ b/src/detect-engine-siggroup.c @@ -383,6 +383,24 @@ int SigGroupHeadClearSigs(SigGroupHead *sgh) return 0; } +#ifdef __SSE2__ +#include +static void MergeBitarrays(const uint8_t *src, uint8_t *dst, const uint32_t size) +{ +#define BYTES 16 + const uint8_t *srcptr = src; + uint8_t *dstptr = dst; + for (uint32_t i = 0; i < size; i += 16) { + __m128i s = _mm_load_si128((const __m128i *)srcptr); + __m128i d = _mm_load_si128((const __m128i *)dstptr); + d = _mm_or_si128(s, d); + _mm_store_si128((__m128i *)dstptr, d); + srcptr += BYTES; + dstptr += BYTES; + } +} +#endif + /** * \brief Copies the bitarray holding the sids from the source SigGroupHead to * the destination SigGroupHead. @@ -396,8 +414,6 @@ int SigGroupHeadClearSigs(SigGroupHead *sgh) */ int SigGroupHeadCopySigs(DetectEngineCtx *de_ctx, SigGroupHead *src, SigGroupHead **dst) { - uint32_t idx = 0; - if (src == NULL || de_ctx == NULL) return 0; @@ -406,11 +422,15 @@ int SigGroupHeadCopySigs(DetectEngineCtx *de_ctx, SigGroupHead *src, SigGroupHea if (*dst == NULL) goto error; } + DEBUG_VALIDATE_BUG_ON(src->init->sig_size != (*dst)->init->sig_size); +#ifdef __SSE2__ + MergeBitarrays(src->init->sig_array, (*dst)->init->sig_array, src->init->sig_size); +#else /* do the copy */ - for (idx = 0; idx < src->init->sig_size; idx++) + for (uint32_t idx = 0; idx < src->init->sig_size; idx++) (*dst)->init->sig_array[idx] = (*dst)->init->sig_array[idx] | src->init->sig_array[idx]; - +#endif if (src->init->whitelist) (*dst)->init->whitelist = MAX((*dst)->init->whitelist, src->init->whitelist); diff --git a/src/suricata.c b/src/suricata.c index 1c5ac7c4c1..72aa927e47 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -784,6 +784,9 @@ static void PrintBuildInfo(void) #endif #if defined(__SSE3__) strlcat(features, "SSE_3 ", sizeof(features)); +#endif +#if defined(__SSE2__) + strlcat(features, "SSE_2 ", sizeof(features)); #endif if (strlen(features) == 0) { strlcat(features, "none", sizeof(features)); -- 2.47.2