blob: 0b5d755a351ef2d171af06a646e9c18bb1745155 [file] [log] [blame]
Willy Tarreau58ef7022007-05-08 23:22:43 +02001#include <stdio.h>
Willy Tarreauae5f7da2007-05-13 11:40:04 +02002#include <string.h>
3#include <arpa/inet.h>
Willy Tarreau58ef7022007-05-08 23:22:43 +02004
5#define NSERV 10
6#define MAXLINE 1000
7
8char line[MAXLINE];
9
10int counts_gd1[NSERV][NSERV];
11static unsigned long hash_gd1(char *uri)
12{
13 unsigned long hash = 0;
14 int c;
15
Willy Tarreauae5f7da2007-05-13 11:40:04 +020016 while ((c = *uri++))
Willy Tarreau58ef7022007-05-08 23:22:43 +020017 hash = c + (hash << 6) + (hash << 16) - hash;
18
19 return hash;
20}
21
22int counts_gd2[NSERV][NSERV];
23static unsigned long hash_gd2(char *uri)
24{
25 unsigned long hash = 0;
26 int c;
27
Willy Tarreauae5f7da2007-05-13 11:40:04 +020028 while ((c = *uri++)) {
Willy Tarreau58ef7022007-05-08 23:22:43 +020029 if (c == '?' || c == '\n')
30 break;
31 hash = c + (hash << 6) + (hash << 16) - hash;
32 }
33
34 return hash;
35}
36
37
38int counts_gd3[NSERV][NSERV];
39static unsigned long hash_gd3(char *uri)
40{
41 unsigned long hash = 0;
42 int c;
43
Willy Tarreauae5f7da2007-05-13 11:40:04 +020044 while ((c = *uri++)) {
Willy Tarreau58ef7022007-05-08 23:22:43 +020045 if (c == '?' || c == '\n')
46 break;
47 hash = c - (hash << 3) + (hash << 15) - hash;
48 }
49
50 return hash;
51}
52
53
54int counts_gd4[NSERV][NSERV];
55static unsigned long hash_gd4(char *uri)
56{
57 unsigned long hash = 0;
58 int c;
59
Willy Tarreauae5f7da2007-05-13 11:40:04 +020060 while ((c = *uri++)) {
Willy Tarreau58ef7022007-05-08 23:22:43 +020061 if (c == '?' || c == '\n')
62 break;
63 hash = hash + (hash << 6) - (hash << 15) - c;
64 }
65
66 return hash;
67}
68
69
70int counts_gd5[NSERV][NSERV];
71static unsigned long hash_gd5(char *uri)
72{
73 unsigned long hash = 0;
74 int c;
75
Willy Tarreauae5f7da2007-05-13 11:40:04 +020076 while ((c = *uri++)) {
Willy Tarreau58ef7022007-05-08 23:22:43 +020077 if (c == '?' || c == '\n')
78 break;
79 hash = hash + (hash << 2) - (hash << 19) - c;
80 }
81
82 return hash;
83}
84
85
86int counts_gd6[NSERV][NSERV];
87static unsigned long hash_gd6(char *uri)
88{
89 unsigned long hash = 0;
90 int c;
91
Willy Tarreauae5f7da2007-05-13 11:40:04 +020092 while ((c = *uri++)) {
Willy Tarreau58ef7022007-05-08 23:22:43 +020093 if (c == '?' || c == '\n')
94 break;
95 hash = hash + (hash << 2) - (hash << 22) - c;
96 }
97
98 return hash;
99}
100
101
102int counts_wt1[NSERV][NSERV];
103static unsigned long hash_wt1(int hsize, char *string) {
104 int bits;
105 unsigned long data, val;
106
107 bits = val = data = 0;
108 while (*string) {
109 if (*string == '?' || *string == '\n')
110 break;
111 data |= ((unsigned long)(unsigned char)*string) << bits;
112 bits += 8;
113 while (bits >= hsize) {
114 val ^= data - (val >> hsize);
115 bits -= hsize;
116 data >>= hsize;
117 }
118 string++;
119 }
120 val ^= data;
121 while (val > ((1 << hsize) - 1)) {
122 val = (val & ((1 << hsize) - 1)) ^ (val >> hsize);
123 }
124 return val;
125}
126
127/*
128 * efficient hash : no duplicate on the first 65536 values of 2 bytes.
129 * less than 0.1% duplicates for the first 1.6 M values of 3 bytes.
130 */
131int counts_wt2[NSERV][NSERV];
132typedef unsigned int u_int32_t;
133
134static inline u_int32_t shl32(u_int32_t i, int count) {
135 if (count == 32)
136 return 0;
137 return i << count;
138}
139
140static inline u_int32_t shr32(u_int32_t i, int count) {
141 if (count == 32)
142 return 0;
143 return i >> count;
144}
145
146static unsigned int rev32(unsigned int c) {
147 c = ((c & 0x0000FFFF) << 16)| ((c & 0xFFFF0000) >> 16);
148 c = ((c & 0x00FF00FF) << 8) | ((c & 0xFF00FF00) >> 8);
149 c = ((c & 0x0F0F0F0F) << 4) | ((c & 0xF0F0F0F0) >> 4);
150 c = ((c & 0x33333333) << 2) | ((c & 0xCCCCCCCC) >> 2);
151 c = ((c & 0x55555555) << 1) | ((c & 0xAAAAAAAA) >> 1);
152 return c;
153}
154
155int hash_wt2(const char *src, int len) {
156 unsigned int i = 0x3C964BA5; /* as many ones as zeroes */
Willy Tarreauae5f7da2007-05-13 11:40:04 +0200157 unsigned int j;
Willy Tarreau58ef7022007-05-08 23:22:43 +0200158 unsigned int ih, il;
159 int bit;
160
161 while (len--) {
162 j = (unsigned char)*src++;
163 if (j == '?' || j == '\n')
164 break;
165 bit = rev32(j - i);
166 bit = bit - (bit >> 3) + (bit >> 16) - j;
167
168 bit &= 0x1f;
169 ih = shr32(i, bit);
170 il = i & (shl32(1, bit) - 1);
171 i = shl32(il, 32-bit) - ih - ~j;
172 }
173 return i;
174}
175
Willy Tarreauae5f7da2007-05-13 11:40:04 +0200176
177//typedef unsigned int uint32_t;
178//typedef unsigned short uint8_t;
179//typedef unsigned char uint16_t;
180
181/*
182 * http://www.azillionmonkeys.com/qed/hash.html
183 */
184#undef get16bits
185#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
186 || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
187#define get16bits(d) (*((const uint16_t *) (d)))
188#endif
189
190#if !defined (get16bits)
191#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
192 +(uint32_t)(((const uint8_t *)(d))[0]) )
193#endif
194
195/*
196 * This function has a hole of 11 unused bits in bytes 2 and 3 of each block of
197 * 32 bits.
198 */
199int counts_SuperFastHash[NSERV][NSERV];
200
201uint32_t SuperFastHash (const char * data, int len) {
202uint32_t hash = len, tmp;
203int rem;
204
205 if (len <= 0 || data == NULL) return 0;
206
207 rem = len & 3;
208 len >>= 2;
209
210 /* Main loop */
211 for (;len > 0; len--) {
212 hash += get16bits (data);
213 tmp = (get16bits (data+2) << 11) ^ hash;
214 hash = (hash << 16) ^ tmp;
215 data += 2*sizeof (uint16_t);
216 hash += hash >> 11;
217 }
218
219 /* Handle end cases */
220 switch (rem) {
221 case 3: hash += get16bits (data);
222 hash ^= hash << 16;
223 hash ^= data[sizeof (uint16_t)] << 18;
224 hash += hash >> 11;
225 break;
226 case 2: hash += get16bits (data);
227 hash ^= hash << 11;
228 hash += hash >> 17;
229 break;
230 case 1: hash += *data;
231 hash ^= hash << 10;
232 hash += hash >> 1;
233 }
234
235 /* Force "avalanching" of final 127 bits */
236 hash ^= hash << 3;
237 hash += hash >> 5;
238 hash ^= hash << 4;
239 hash += hash >> 17;
240 hash ^= hash << 25;
241 hash += hash >> 6;
242
243 return hash;
244}
245
246/*
247 * This variant uses all bits from the input block, and is about 15% faster.
248 */
249int counts_SuperFastHash2[NSERV][NSERV];
250uint32_t SuperFastHash2 (const char * data, int len) {
251uint32_t hash = len, tmp;
252int rem;
253
254 if (len <= 0 || data == NULL) return 0;
255
256 rem = len & 3;
257 len >>= 2;
258
259 /* Main loop */
260 for (;len > 0; len--) {
261 register uint32_t next;
262 next = get16bits(data+2);
263 hash += get16bits(data);
264 tmp = ((next << 11) | (next >> 21)) ^ hash;
265 hash = (hash << 16) ^ tmp;
266 data += 2*sizeof (uint16_t);
267 hash += hash >> 11;
268 }
269
270 /* Handle end cases */
271 switch (rem) {
272 case 3: hash += get16bits (data);
273 hash ^= hash << 16;
274 hash ^= data[sizeof (uint16_t)] << 18;
275 hash += hash >> 11;
276 break;
277 case 2: hash += get16bits (data);
278 hash ^= hash << 11;
279 hash += hash >> 17;
280 break;
281 case 1: hash += *data;
282 hash ^= hash << 10;
283 hash += hash >> 1;
284 }
285
286 /* Force "avalanching" of final 127 bits */
287 hash ^= hash << 3;
288 hash += hash >> 5;
289 hash ^= hash << 4;
290 hash += hash >> 17;
291 hash ^= hash << 25;
292 hash += hash >> 6;
293
294 return hash;
295}
296
297/* len 4 for ipv4 and 16 for ipv6 */
298int counts_srv[NSERV][NSERV];
299unsigned int haproxy_server_hash(const char *addr, int len){
300 unsigned int h, l;
301 l = h = 0;
302
303 while ((l + sizeof (int)) <= len) {
304 h ^= ntohl(*(unsigned int *)(&addr[l]));
305 l += sizeof (int);
306 }
307 return h;
308}/* end haproxy_server_hash() */
309
310
311
Willy Tarreau58ef7022007-05-08 23:22:43 +0200312void count_hash_results(unsigned long hash, int counts[NSERV][NSERV]) {
313 int srv, nsrv;
314
315 for (nsrv = 0; nsrv < NSERV; nsrv++) {
316 srv = hash % (nsrv + 1);
317 counts[nsrv][srv]++;
318 }
319}
320
321void dump_hash_results(char *name, int counts[NSERV][NSERV]) {
322 int srv, nsrv;
323
324 printf("%s:\n", name);
325 for (nsrv = 0; nsrv < NSERV; nsrv++) {
326 printf("%02d srv: ", nsrv+1);
327 for (srv = 0; srv <= nsrv; srv++) {
328 //printf("%6d ", counts[nsrv][srv]);
329 //printf("%3.1f ", (100.0*counts[nsrv][srv]) / (double)counts[0][0]);
330 printf("%3.1f ", 100.0*(counts[nsrv][srv] - (double)counts[0][0]/(nsrv+1)) / (double)counts[0][0]);
331 }
332 printf("\n");
333 }
334 printf("\n");
335}
336
Willy Tarreauae5f7da2007-05-13 11:40:04 +0200337int main() {
Willy Tarreau58ef7022007-05-08 23:22:43 +0200338 memset(counts_gd1, 0, sizeof(counts_gd1));
339 memset(counts_gd2, 0, sizeof(counts_gd2));
340 memset(counts_gd3, 0, sizeof(counts_gd3));
341 memset(counts_gd4, 0, sizeof(counts_gd4));
342 memset(counts_gd5, 0, sizeof(counts_gd5));
343 memset(counts_gd6, 0, sizeof(counts_gd6));
344 memset(counts_wt1, 0, sizeof(counts_wt1));
345 memset(counts_wt2, 0, sizeof(counts_wt2));
Willy Tarreauae5f7da2007-05-13 11:40:04 +0200346 memset(counts_srv, 0, sizeof(counts_srv));
347 memset(counts_SuperFastHash, 0, sizeof(counts_SuperFastHash));
348 memset(counts_SuperFastHash2, 0, sizeof(counts_SuperFastHash2));
Willy Tarreau58ef7022007-05-08 23:22:43 +0200349
350 while (fgets(line, MAXLINE, stdin) != NULL) {
351 count_hash_results(hash_gd1(line), counts_gd1);
352 count_hash_results(hash_gd2(line), counts_gd2);
353 count_hash_results(hash_gd3(line), counts_gd3);
354 count_hash_results(hash_gd4(line), counts_gd4);
355 count_hash_results(hash_gd5(line), counts_gd5);
356 count_hash_results(hash_gd6(line), counts_gd6);
357 count_hash_results(hash_wt1(31, line), counts_wt1);
358 count_hash_results(hash_wt2(line, strlen(line)), counts_wt2);
Willy Tarreauae5f7da2007-05-13 11:40:04 +0200359 count_hash_results(haproxy_server_hash(line, strlen(line)), counts_srv);
360 count_hash_results(SuperFastHash(line, strlen(line)), counts_SuperFastHash);
361 count_hash_results(SuperFastHash2(line, strlen(line)), counts_SuperFastHash2);
Willy Tarreau58ef7022007-05-08 23:22:43 +0200362 }
363
364 dump_hash_results("hash_gd1", counts_gd1);
365 dump_hash_results("hash_gd2", counts_gd2);
366 dump_hash_results("hash_gd3", counts_gd3);
367 dump_hash_results("hash_gd4", counts_gd4);
368 dump_hash_results("hash_gd5", counts_gd5);
369 dump_hash_results("hash_gd6", counts_gd6);
370 dump_hash_results("hash_wt1", counts_wt1);
371 dump_hash_results("hash_wt2", counts_wt2);
Willy Tarreauae5f7da2007-05-13 11:40:04 +0200372 dump_hash_results("haproxy_server_hash", counts_srv);
373 dump_hash_results("SuperFastHash", counts_SuperFastHash);
374 dump_hash_results("SuperFastHash2", counts_SuperFastHash2);
375
376 return 0;
Willy Tarreau58ef7022007-05-08 23:22:43 +0200377}