Skip to content

Commit

Permalink
Switch to crc32 if available for hashing function (#3803)
Browse files Browse the repository at this point in the history
* Switch to crc32 if available for hashing function

Signed-off-by: Alan Jowett <[email protected]>

* Only do crc32 when keys are directly accessible

Signed-off-by: Alan Jowett <[email protected]>

* Minimize branches and extra ALU ops

Signed-off-by: Alan Jowett <[email protected]>

---------

Signed-off-by: Alan Jowett <[email protected]>
Co-authored-by: Alan Jowett <[email protected]>
  • Loading branch information
Alan-Jowett and Alan Jowett authored Sep 4, 2024
1 parent 725f3f5 commit 06533c8
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 8 deletions.
50 changes: 42 additions & 8 deletions libs/runtime/ebpf_hash_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "ebpf_hash_table.h"
#include "ebpf_random.h"

#include <nmmintrin.h>

// Buckets contain an array of pointers to value and keys.
// Buckets are immutable once inserted in to the hash-table and replaced when
// modified.
Expand Down Expand Up @@ -154,6 +156,33 @@ _ebpf_murmur3_32(_In_reads_((length_in_bits + 7) / 8) const uint8_t* key, size_t
return hash;
}

static unsigned long
_ebpf_compute_crc32(_In_reads_(length_in_bytes) const uint8_t* key, size_t length_in_bytes, uint32_t seed)
{
// First process 8 bytes at a time.
uint32_t crc = seed;
uint8_t* start = (uint8_t*)key;
uint8_t* end = start + length_in_bytes;

while ((end - start) >= 8) {
crc = (uint32_t)_mm_crc32_u64(crc, *(uint64_t*)start);
start += 8;
}

// Process 4 bytes at a time.
while ((end - start) >= 4) {
crc = _mm_crc32_u32(crc, *(uint32_t*)start);
start += 4;
}

// Process remaining bytes.
while ((end - start) > 0) {
crc = _mm_crc32_u8(crc, *start);
start++;
}
return crc;
}

/**
* @brief Compare keys assuming they are integers.
*
Expand Down Expand Up @@ -279,16 +308,18 @@ _ebpf_hash_table_compare(_In_ const ebpf_hash_table_t* hash_table, _In_ const ui
static uint32_t
_ebpf_hash_table_compute_bucket_index(_In_ const ebpf_hash_table_t* hash_table, _In_ const uint8_t* key)
{
size_t length;
const uint8_t* data;
if (hash_table->extract) {
hash_table->extract(key, &data, &length);
if (!hash_table->extract) {
if (ebpf_processor_supports_sse42) {
return _ebpf_compute_crc32(key, hash_table->key_size, hash_table->seed) & hash_table->bucket_count_mask;
} else {
return _ebpf_murmur3_32(key, hash_table->key_size * 8, hash_table->seed) & hash_table->bucket_count_mask;
}
} else {
length = hash_table->key_size * 8;
data = key;
uint8_t* data;
size_t length;
hash_table->extract(key, &data, &length);
return _ebpf_murmur3_32(data, length, hash_table->seed) & hash_table->bucket_count_mask;
}
uint32_t hash_value = _ebpf_murmur3_32(data, length, hash_table->seed);
return hash_value & hash_table->bucket_count_mask;
}

/**
Expand Down Expand Up @@ -758,6 +789,9 @@ ebpf_hash_table_find(_In_ const ebpf_hash_table_t* hash_table, _In_ const uint8_
goto Done;
}

// Prefetch the data on the assumption that it will be used by the caller soon.
_mm_prefetch((const char*)data, _MM_HINT_T0);

*value = data;
if (hash_table->notification_callback) {
hash_table->notification_callback(
Expand Down
11 changes: 11 additions & 0 deletions libs/runtime/ebpf_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ static uint32_t _ebpf_platform_maximum_processor_count = 0;

static bool _ebpf_platform_is_cxplat_initialized = false;

bool ebpf_processor_supports_sse42 = true;

_Ret_range_(>, 0) uint32_t ebpf_get_cpu_count() { return _ebpf_platform_maximum_processor_count; }

void
Expand Down Expand Up @@ -513,12 +515,21 @@ ebpf_allocate_preemptible_work_item(
return ebpf_result_from_cxplat_status(status);
}

#define CPU_INFO_PROCESSOR_INFO_FUNCTION 1
#define CPU_INFO_SSE42_BYTE_OFFSET 2
#define CPU_INFO_SSE32_BIT_OFFSET 20

_Must_inspect_result_ ebpf_result_t
ebpf_platform_initiate()
{
ebpf_result_t result = ebpf_result_from_cxplat_status(cxplat_initialize());
_ebpf_platform_is_cxplat_initialized = (result == EBPF_SUCCESS);
ebpf_initialize_cpu_count();
// Check if processor supports SSE4.2
int cpu_info[4] = {0};
__cpuid(cpu_info, CPU_INFO_PROCESSOR_INFO_FUNCTION);
ebpf_processor_supports_sse42 = (cpu_info[CPU_INFO_SSE42_BYTE_OFFSET] & (1 << CPU_INFO_SSE32_BIT_OFFSET)) != 0;

return result;
}

Expand Down
2 changes: 2 additions & 0 deletions libs/runtime/ebpf_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,8 @@ extern "C"
_Ret_notnull_ DEVICE_OBJECT*
ebpf_driver_get_device_object();

extern bool ebpf_processor_supports_sse42;

#ifdef __cplusplus
}
#endif
Expand Down

0 comments on commit 06533c8

Please sign in to comment.