Guest User

Untitled

a guest
May 28th, 2018
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.48 KB | None | 0 0
  1. #include <stdint.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <benchmark/benchmark.h>
  5.  
  6. unsigned int odd_constant = 0xdeadbeef | 1;
  7.  
  8. static unsigned int hash_crc32_orig(const void *keyptr)
  9. {
  10. unsigned int hash = odd_constant;
  11. const char *key = (const char *)keyptr;
  12. size_t len = strlen(key);
  13.  
  14. #if __x86_64__
  15. while (len >= sizeof(uint64_t)) {
  16. uint64_t data;
  17. memcpy(&data, key, sizeof(data));
  18. hash = (unsigned int)__builtin_ia32_crc32di(hash, data);
  19. key += sizeof(uint64_t);
  20. len -= sizeof(uint64_t);
  21. }
  22. #endif /* __x86_64__ */
  23. while (len >= sizeof(uint32_t)) {
  24. uint32_t data;
  25. memcpy(&data, key, sizeof(data));
  26. hash = __builtin_ia32_crc32si(hash, data);
  27. key += sizeof(uint32_t);
  28. len -= sizeof(uint32_t);
  29. }
  30. if (*key && *(key + 1)) {
  31. uint16_t data;
  32. memcpy(&data, key, sizeof(data));
  33. hash = __builtin_ia32_crc32hi(hash, data);
  34. key += sizeof(uint16_t);
  35. }
  36. /* Last byte might be the terminating NUL or the last character.
  37. * For a hash, this doesn't matter, and shaves off a branch.
  38. */
  39. hash = __builtin_ia32_crc32qi(hash, (unsigned char)*key);
  40.  
  41. return hash;
  42. }
  43.  
  44. #ifdef __x86_64__
  45. static inline uint64_t has_zero8(const char *ptr)
  46. {
  47. uint64_t v;
  48.  
  49. memcpy(&v, ptr, sizeof(v));
  50.  
  51. return ((v - 0x0101010101010101ull) & ~v & 0x8080808080808080ull);
  52. }
  53. #endif
  54.  
  55. static inline uint32_t has_zero4(const char *ptr)
  56. {
  57. uint32_t v;
  58.  
  59. memcpy(&v, ptr, sizeof(v));
  60.  
  61. return ((v - 0x01010101ul) & ~v & 0x80808080ul);
  62. }
  63.  
  64. static unsigned int hash_crc32_new(const void *keyptr)
  65. {
  66. unsigned int hash = odd_constant;
  67. const char *key = (const char *)keyptr;
  68.  
  69. #if __x86_64__
  70. while (!has_zero8(key)) {
  71. uint64_t data;
  72.  
  73. memcpy(&data, key, sizeof(data));
  74.  
  75. hash = (unsigned int)__builtin_ia32_crc32di(hash, data);
  76. key += sizeof(uint64_t);
  77. }
  78. #endif /* __x86_64__ */
  79.  
  80. while (!has_zero4(key)) {
  81. uint32_t data;
  82.  
  83. memcpy(&data, key, sizeof(data));
  84.  
  85. hash = __builtin_ia32_crc32si(hash, data);
  86. key += sizeof(uint32_t);
  87. }
  88.  
  89. if (*key && *(key + 1)) {
  90. uint16_t data;
  91.  
  92. memcpy(&data, key, sizeof(data));
  93.  
  94. hash = __builtin_ia32_crc32hi(hash, data);
  95. key += sizeof(uint16_t);
  96. }
  97. /* Last byte might be the terminating NUL or the last character.
  98. * For a hash, this doesn't matter, and shaves off a branch.
  99. */
  100. hash = __builtin_ia32_crc32qi(hash, (unsigned char)*key);
  101.  
  102. return hash;
  103. }
  104.  
  105. template <unsigned int (*hash_func)(const void *ptr)>
  106. static void bm_crc(benchmark::State& state)
  107. {
  108. while (state.KeepRunning()) {
  109. benchmark::DoNotOptimize(hash_func("a"));
  110. benchmark::DoNotOptimize(hash_func("ab"));
  111. benchmark::DoNotOptimize(hash_func("abc"));
  112. benchmark::DoNotOptimize(hash_func("abcde"));
  113. benchmark::DoNotOptimize(hash_func("banana"));
  114. benchmark::DoNotOptimize(hash_func("uma string maior"));
  115. benchmark::DoNotOptimize(hash_func("uma string bem grande e que vai testar bem os limites"));
  116. benchmark::DoNotOptimize(hash_func("uma string bem grande e que vai testar bem os limites"
  117. "uma string bem grande e que vai testar bem os limites"
  118. "uma string bem grande e que vai testar bem os limites"
  119. "uma string bem grande e que vai testar bem os limites"
  120. "uma string bem grande e que vai testar bem os limites"
  121. "uma string bem grande e que vai testar bem os limites"
  122. "uma string bem grande e que vai testar bem os limites"
  123. "uma string bem grande e que vai testar bem os limites"
  124. "uma string bem grande e que vai testar bem os limites"
  125. "uma string bem grande e que vai testar bem os limites"
  126. "uma string bem grande e que vai testar bem os limites"
  127. "uma string bem grande e que vai testar bem os limites"
  128. "uma string bem grande e que vai testar bem os limites"
  129. "uma string bem grande e que vai testar bem os limites"
  130. "uma string bem grande e que vai testar bem os limites"
  131. "uma string bem grande e que vai testar bem os limites"
  132. "uma string bem grande e que vai testar bem os limites"));
  133. }
  134. }
  135.  
  136. int main(int argc, char *argv[])
  137. {
  138. benchmark::RegisterBenchmark("orig", bm_crc<hash_crc32_orig>);
  139. benchmark::RegisterBenchmark("new", bm_crc<hash_crc32_new>);
  140.  
  141. benchmark::Initialize(&argc, argv);
  142. benchmark::RunSpecifiedBenchmarks();
  143.  
  144. return 0;
  145. }
Add Comment
Please, Sign In to add comment