Hash calculation could be accelerated, if string was interpreted as int array (using word-sized type), striding with int until the end of string, doing rest with char.
Omiting possible need for strlen, I estimate effect comparable with simd, used for number crunching. Any string with less length than int size would not need any calculations at all. Though even with strlen - acceleration should be notable, especially with complex hash functions.
char s[] = "...";
unsigned long long hash = 0;
char *c = s;
unsigned *i = (void *)s;
int stride = 0;
while (; *c; ++c) {
stride++;
if (stride == sizeof(*i))
{
hash = ((void*)i > (void*)) ? i[0] : hash * 31 + i[0];
i++, stride=0;
}
}
c = (void *)i;
while (; *c; ++c)
hash = hash * 31 + c[0];
I did not try to even compile it, so don't mindless copy-paste.
Update: simpler approach with length, calculated separately
#include <stdlib.h>
char s[] = "...";
unsigned long long hash = 0;
int len = strlen(s);
unsigned long *u = (void *)s;
ldiv_t len_u = ldiv (len, sizeof(*u));
for (int i = 0; i < len_u.quot; i++)
hash = hash * 31 + u[0];
for (int i = len - len_u.rem - 1; i < len; i++)
hash = hash * 31 + s[i];
And using unsigned auto variable as some kind of buffer
char s[] = "...";
unsigned long long hash = 0;
unsigned buf; // processing unit
char *sp, c; // string pointer & current string
int i; // position in buf
sp = s;
i = 0;
while (( c = *sp ))
{
((char *)&buf)[i] = c;
i = (i + 1) % sizeof(buf);
if (!i) {
hash = hash * 31 + buf;
buf = 0;
}
}
if (buf)
hash = hash * 31 + buf;
```