Skip to content

Commit f8b41ed

Browse files
committed
Avoid a mod in the status lookup perfect hash table
1 parent 9b3bdf5 commit f8b41ed

File tree

1 file changed

+20
-8
lines changed

1 file changed

+20
-8
lines changed

src/bin/tools/statuslookupgen.c

+20-8
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ static inline uint32_t rotate(uint32_t v, int n)
1313
return v << (32 - n) | v >> n;
1414
}
1515

16+
static inline uint32_t map_0_to_n(uint32_t value, uint32_t n)
17+
{
18+
return (uint32_t)(((uint64_t)value * (uint64_t)n) >> 32);
19+
}
20+
1621
int main(void)
1722
{
1823
uint32_t max_key = 0;
@@ -49,7 +54,8 @@ int main(void)
4954
int set_bits = 0;
5055

5156
for (int key = 0; key < N_KEYS; key++) {
52-
uint32_t k = rotate((uint32_t)keys[key] - subtract, rot) % mod;
57+
uint32_t k = map_0_to_n(
58+
rotate((uint32_t)keys[key] - subtract, rot), mod);
5359

5460
if (set & 1ull<<k)
5561
break;
@@ -75,11 +81,17 @@ int main(void)
7581
uint64_t set_values = ~0ull;
7682
printf("static ALWAYS_INLINE const char *lwan_lookup_http_status_impl(enum lwan_http_status status) {\n");
7783
printf(" static const char *table[] = {\n");
78-
#define PRINT_V(ignored1, key, short_desc, long_desc) do { \
79-
uint32_t k = rotate((uint32_t)key - (uint32_t)best_subtract, best_rot) % best_mod; \
80-
set_values &= ~(1ull<<k); \
81-
printf(" [%d] = \"%d %s\\0%s\",\n", k, key, short_desc, long_desc); \
82-
} while(0);
84+
85+
#define PRINT_V(ignored1, key, short_desc, long_desc) \
86+
do { \
87+
uint32_t k = map_0_to_n( \
88+
rotate((uint32_t)key - (uint32_t)best_subtract, best_rot), \
89+
best_mod); \
90+
set_values &= ~(1ull << k); \
91+
printf(" [%d] = \"%d %s\\0%s\",\n", k, key, short_desc, \
92+
long_desc); \
93+
} while (0);
94+
8395
FOR_EACH_HTTP_STATUS(PRINT_V)
8496
#undef PRINT_V
8597

@@ -92,12 +104,12 @@ int main(void)
92104

93105
printf("\n");
94106
printf(" const uint32_t k = (uint32_t)status - %d;\n", best_subtract);
95-
printf(" const char *ret = table[((k << %d) | (k >> %d)) %% %d];\n", 32 - best_rot, best_rot, best_mod);
107+
printf(" const uint32_t hash = (k << %d) | (k >> %d);\n", 32 - best_rot, best_rot);
108+
printf(" const char *ret = table[(uint32_t)(((uint64_t)hash * (uint64_t)%d) >> 32)];\n", best_mod);
96109
printf(" assert((uint32_t)(ret[2] - '0') == ((uint32_t)status %% 10));\n");
97110
printf(" assert((uint32_t)(ret[1] - '0') == ((uint32_t)(status / 10) %% 10));\n");
98111
printf(" assert((uint32_t)(ret[0] - '0') == ((uint32_t)(status / 100) %% 10));\n");
99112
printf(" return ret;\n");
100113

101114
printf("}\n");
102-
103115
}

0 commit comments

Comments
 (0)