count_min_sketch.cpp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #include "count_min_sketch.h"
  2. #include <util/system/compiler.h>
  3. namespace NKikimr {
  4. TCountMinSketch* TCountMinSketch::Create(ui64 width, ui64 depth) {
  5. auto size = StaticSize(width, depth);
  6. auto* data = ::malloc(size);
  7. auto* sketch = reinterpret_cast<TCountMinSketch*>(data);
  8. std::memset(sketch, 0, size);
  9. sketch->Width = width;
  10. sketch->Depth = depth;
  11. sketch->ElementCount = 0;
  12. return sketch;
  13. }
  14. TCountMinSketch* TCountMinSketch::FromString(const char* data, size_t size) {
  15. auto* from = reinterpret_cast<const TCountMinSketch*>(data);
  16. Y_ABORT_UNLESS(StaticSize(from->Width, from->Depth) == size);
  17. auto* dataDst = ::malloc(size);
  18. std::memcpy(dataDst, data, size);
  19. return reinterpret_cast<TCountMinSketch*>(dataDst);
  20. }
  21. void TCountMinSketch::operator delete(void* data) noexcept {
  22. ::free(data);
  23. }
  24. ui64 TCountMinSketch::Hash(const char* data, size_t size, size_t hashIndex) {
  25. // fnv1a
  26. ui64 hash = 14695981039346656037ULL + 31 * hashIndex;
  27. const unsigned char* ptr = (const unsigned char*)data;
  28. for (size_t i = 0; i < size; ++i, ++ptr) {
  29. hash = hash ^ (*ptr);
  30. hash = hash * 1099511628211ULL;
  31. }
  32. return hash;
  33. }
  34. void TCountMinSketch::Count(const char* data, size_t size) {
  35. ui32* start = Buckets();
  36. for (size_t d = 0; d < Depth; ++d, start += Width) {
  37. ui64 hash = Hash(data, size, d);
  38. ui32* bucket = start + hash % Width;
  39. if (Y_LIKELY(*bucket < std::numeric_limits<ui32>::max())) {
  40. ++*bucket;
  41. }
  42. }
  43. ++ElementCount;
  44. }
  45. ui32 TCountMinSketch::Probe(const char* data, size_t size) const {
  46. ui32 minValue = std::numeric_limits<ui32>::max();
  47. const ui32* start = Buckets();
  48. for (size_t d = 0; d < Depth; ++d, start += Width) {
  49. ui64 hash = Hash(data, size, d);
  50. const ui32* bucket = start + hash % Width;
  51. minValue = std::min(minValue, *bucket);
  52. }
  53. return minValue;
  54. }
  55. TCountMinSketch& TCountMinSketch::operator+=(const TCountMinSketch& rhs) {
  56. if (Width != rhs.Width || Depth != rhs.Depth) {
  57. return *this;
  58. }
  59. ui32* dst = Buckets();
  60. const ui32* src = rhs.Buckets();
  61. ui32* end = dst + Width * Depth;
  62. for (; dst != end; ++dst, ++src) {
  63. ui32 sum = *dst + *src;
  64. if (Y_UNLIKELY(sum < *dst)) {
  65. *dst = std::numeric_limits<ui32>::max();
  66. } else {
  67. *dst = sum;
  68. }
  69. }
  70. ElementCount += rhs.ElementCount;
  71. return *this;
  72. }
  73. } // namespace NKikimr