Optimize the symbol name hash table to reduce collision and improve
performance, especially on RISC-V architecture where symbol lookup
is a hotspot.
Changes:
- Increase SYMNAME_HASH from 512 to 16384 (32x) to reduce collisions
- Replace simple hash with FNV-1a algorithm for better distribution
- Remove strlen() call, compute hash in single pass
This reduces the average chain length in hash buckets significantly,
improving symbol lookup performance at the cost of ~248KB additional
memory.
Signed-off-by: Rui Qi <qirui.001(a)bytedance.com>
---
defs.h | 2 +-
symbols.c | 15 +++++++++------
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/defs.h b/defs.h
index a6f43725b6b8..4cf062894ebe 100644
--- a/defs.h
+++ b/defs.h
@@ -2900,7 +2900,7 @@ struct downsized {
#define SYMVAL_HASH_INDEX(vaddr) \
(((vaddr) >> machdep->pageshift) % SYMVAL_HASH)
-#define SYMNAME_HASH (512)
+#define SYMNAME_HASH (16384)
#define PATCH_KERNEL_SYMBOLS_START ((char *)(1))
#define PATCH_KERNEL_SYMBOLS_STOP ((char *)(2))
diff --git a/symbols.c b/symbols.c
index e6865cabef74..afdf4a61cea2 100644
--- a/symbols.c
+++ b/symbols.c
@@ -1170,16 +1170,19 @@ symname_hash_init(void)
static unsigned int
symname_hash_index(char *name)
{
- unsigned int len, value;
- unsigned char *array = (unsigned char *)name;
+ unsigned int hash = 2166136261U;
+ unsigned char *p = (unsigned char *)name;
- len = strlen(name);
- if (!len)
+ if (!*p)
error(FATAL, "The length of the symbol name is zero!\n");
- value = array[len - 1] * array[len / 2];
+ /* FNV-1a hash algorithm for better distribution */
+ while (*p) {
+ hash ^= *p++;
+ hash *= 16777619;
+ }
- return (array[0] ^ value) % SYMNAME_HASH;
+ return hash % SYMNAME_HASH;
}
/*
--
2.20.1