tracking_collisions.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /* This is a small program used in order to understand the collison rate
  2. * of CRC64 (ISO version) VS other stronger hashing functions in the context
  3. * of hashing keys for the Redis "tracking" feature (client side caching
  4. * assisted by the server).
  5. *
  6. * The program attempts to hash keys with common names in the form of
  7. *
  8. * prefix:<counter>
  9. *
  10. * And counts the resulting collisons generated in the 24 bits of output
  11. * needed for the tracking feature invalidation table (16 millions + entries)
  12. *
  13. * Compile with:
  14. *
  15. * cc -O2 ./tracking_collisions.c ../src/crc64.c ../src/sha1.c
  16. * ./a.out
  17. *
  18. * --------------------------------------------------------------------------
  19. *
  20. * Copyright (C) 2019 Salvatore Sanfilippo
  21. * This code is released under the BSD 2 clause license.
  22. */
  23. #include <stdlib.h>
  24. #include <stdint.h>
  25. #include <string.h>
  26. #include <stdio.h>
  27. #include "../src/crc64.h"
  28. #include "../src/sha1.h"
  29. #define TABLE_SIZE (1<<24)
  30. int Table[TABLE_SIZE];
  31. uint64_t crc64Hash(char *key, size_t len) {
  32. return crc64(0,(unsigned char*)key,len);
  33. }
  34. uint64_t sha1Hash(char *key, size_t len) {
  35. SHA1_CTX ctx;
  36. unsigned char hash[20];
  37. SHA1Init(&ctx);
  38. SHA1Update(&ctx,(unsigned char*)key,len);
  39. SHA1Final(hash,&ctx);
  40. uint64_t hash64;
  41. memcpy(&hash64,hash,sizeof(hash64));
  42. return hash64;
  43. }
  44. /* Test the hashing function provided as callback and return the
  45. * number of collisions found. */
  46. unsigned long testHashingFunction(uint64_t (*hash)(char *, size_t)) {
  47. unsigned long collisions = 0;
  48. memset(Table,0,sizeof(Table));
  49. char *prefixes[] = {"object", "message", "user", NULL};
  50. for (int i = 0; prefixes[i] != NULL; i++) {
  51. for (int j = 0; j < TABLE_SIZE/2; j++) {
  52. char keyname[128];
  53. size_t keylen = snprintf(keyname,sizeof(keyname),"%s:%d",
  54. prefixes[i],j);
  55. uint64_t bucket = hash(keyname,keylen) % TABLE_SIZE;
  56. if (Table[bucket]) {
  57. collisions++;
  58. } else {
  59. Table[bucket] = 1;
  60. }
  61. }
  62. }
  63. return collisions;
  64. }
  65. int main(void) {
  66. printf("SHA1 : %lu\n", testHashingFunction(sha1Hash));
  67. printf("CRC64: %lu\n", testHashingFunction(crc64Hash));
  68. return 0;
  69. }