bloom.rs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #![allow(clippy::arithmetic_side_effects)]
  2. use {
  3. bencher::{benchmark_group, benchmark_main, Bencher},
  4. bv::BitVec,
  5. fnv::FnvHasher,
  6. rand::Rng,
  7. solana_bloom::bloom::{Bloom, BloomHashIndex, ConcurrentBloom},
  8. solana_hash::Hash,
  9. solana_sha256_hasher::hash,
  10. solana_signature::Signature,
  11. std::{collections::HashSet, hash::Hasher},
  12. };
  13. fn bench_bits_set(b: &mut Bencher) {
  14. let mut bits: BitVec<u8> = BitVec::new_fill(false, 38_340_234_u64);
  15. let mut hasher = FnvHasher::default();
  16. b.iter(|| {
  17. let idx = hasher.finish() % bits.len();
  18. bits.set(idx, true);
  19. hasher.write_u64(idx);
  20. });
  21. }
  22. fn bench_bits_set_hasher(b: &mut Bencher) {
  23. let bits: BitVec<u8> = BitVec::new_fill(false, 38_340_234_u64);
  24. let mut hasher = FnvHasher::default();
  25. b.iter(|| {
  26. let idx = hasher.finish() % bits.len();
  27. hasher.write_u64(idx);
  28. });
  29. }
  30. fn bench_sigs_bloom(b: &mut Bencher) {
  31. // 1M TPS * 1s (length of block in sigs) == 1M items in filter
  32. // 1.0E-8 false positive rate
  33. // https://hur.st/bloomfilter/?n=1000000&p=1.0E-8&m=&k=
  34. let blockhash = hash(Hash::default().as_ref());
  35. let keys = (0..27).map(|i| blockhash.hash_at_index(i)).collect();
  36. let mut sigs: Bloom<Signature> = Bloom::new(38_340_234, keys);
  37. let mut id = blockhash;
  38. let mut falses = 0;
  39. let mut iterations = 0;
  40. b.iter(|| {
  41. id = hash(id.as_ref());
  42. let mut sigbytes = Vec::from(id.as_ref());
  43. id = hash(id.as_ref());
  44. sigbytes.extend(id.as_ref());
  45. let sig = Signature::try_from(sigbytes).unwrap();
  46. if sigs.contains(&sig) {
  47. falses += 1;
  48. }
  49. sigs.add(&sig);
  50. sigs.contains(&sig);
  51. iterations += 1;
  52. });
  53. assert_eq!(falses, 0);
  54. }
  55. fn bench_sigs_hashmap(b: &mut Bencher) {
  56. let blockhash = hash(Hash::default().as_ref());
  57. let mut sigs: HashSet<Signature> = HashSet::new();
  58. let mut id = blockhash;
  59. let mut falses = 0;
  60. let mut iterations = 0;
  61. b.iter(|| {
  62. id = hash(id.as_ref());
  63. let mut sigbytes = Vec::from(id.as_ref());
  64. id = hash(id.as_ref());
  65. sigbytes.extend(id.as_ref());
  66. let sig = Signature::try_from(sigbytes).unwrap();
  67. if sigs.contains(&sig) {
  68. falses += 1;
  69. }
  70. sigs.insert(sig);
  71. sigs.contains(&sig);
  72. iterations += 1;
  73. });
  74. assert_eq!(falses, 0);
  75. }
  76. fn bench_add_hash(b: &mut Bencher) {
  77. let mut rng = rand::thread_rng();
  78. let hash_values: Vec<_> = std::iter::repeat_with(Hash::new_unique)
  79. .take(1200)
  80. .collect();
  81. let mut fail = 0;
  82. b.iter(|| {
  83. let mut bloom = Bloom::random(1287, 0.1, 7424);
  84. for hash_value in &hash_values {
  85. bloom.add(hash_value);
  86. }
  87. let index = rng.gen_range(0..hash_values.len());
  88. if !bloom.contains(&hash_values[index]) {
  89. fail += 1;
  90. }
  91. });
  92. assert_eq!(fail, 0);
  93. }
  94. fn bench_add_hash_atomic(b: &mut Bencher) {
  95. let mut rng = rand::thread_rng();
  96. let hash_values: Vec<_> = std::iter::repeat_with(Hash::new_unique)
  97. .take(1200)
  98. .collect();
  99. let mut fail = 0;
  100. b.iter(|| {
  101. let bloom: ConcurrentBloom<_> = Bloom::random(1287, 0.1, 7424).into();
  102. // Intentionally not using parallelism here, so that this and above
  103. // benchmark only compare the bit-vector ops.
  104. // For benchmarking the parallel code, change bellow for loop to:
  105. // hash_values.par_iter().for_each(|v| bloom.add(v));
  106. for hash_value in &hash_values {
  107. bloom.add(hash_value);
  108. }
  109. let index = rng.gen_range(0..hash_values.len());
  110. if !bloom.contains(&hash_values[index]) {
  111. fail += 1;
  112. }
  113. });
  114. assert_eq!(fail, 0);
  115. }
  116. benchmark_group!(
  117. benches,
  118. bench_bits_set,
  119. bench_bits_set_hasher,
  120. bench_sigs_bloom,
  121. bench_sigs_hashmap,
  122. bench_add_hash,
  123. bench_add_hash_atomic
  124. );
  125. benchmark_main!(benches);