cuckoo.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
  2. use utils::cuckoo::{Hasher, Parameters};
  3. use utils::hash::AesHashFunction;
  4. const LOG_DOMAIN_SIZES: [u32; 4] = [8, 12, 16, 20];
  5. pub fn bench_hash_domain_into_buckets(c: &mut Criterion) {
  6. for log_domain_size in LOG_DOMAIN_SIZES {
  7. let log_number_inputs = log_domain_size / 2;
  8. let parameters = Parameters::<AesHashFunction<u32>, _>::sample(1 << log_number_inputs);
  9. let hasher = Hasher::new(parameters);
  10. c.bench_with_input(
  11. BenchmarkId::new(
  12. "Hasher<AesHashFunction>.hash_domain_into_buckets",
  13. log_domain_size,
  14. ),
  15. &log_domain_size,
  16. |b, &log_domain_size| {
  17. b.iter(|| hasher.hash_domain_into_buckets(black_box(1 << log_domain_size)))
  18. },
  19. );
  20. }
  21. }
  22. pub fn bench_position_map(c: &mut Criterion) {
  23. let number_inputs = 1_000;
  24. let parameters = Parameters::<AesHashFunction<u32>, _>::sample(number_inputs);
  25. let hasher = Hasher::new(parameters);
  26. let domain_size = 100_000;
  27. let hash_table = hasher.hash_domain_into_buckets(domain_size);
  28. // (ab)use one lookup table to obtain the input pairs for pos
  29. let values =
  30. Hasher::<AesHashFunction<u32>, _>::compute_pos_lookup_table(domain_size, &hash_table);
  31. let pos = |bucket_i: usize, item: u64| -> u64 {
  32. let idx = hash_table[bucket_i].partition_point(|x| x < &item);
  33. assert!(idx != hash_table[bucket_i].len());
  34. assert_eq!(item, hash_table[bucket_i][idx]);
  35. assert!(idx == 0 || hash_table[bucket_i][idx - 1] != item);
  36. idx as u64
  37. };
  38. let mut group = c.benchmark_group("position_map");
  39. group.bench_function("search", |b| {
  40. b.iter(|| {
  41. for item in 0..domain_size {
  42. for &(bucket_i, _) in values[item as usize].iter() {
  43. let idx = pos(bucket_i, item);
  44. black_box(idx);
  45. }
  46. }
  47. })
  48. });
  49. group.bench_function("lookup", |b| {
  50. let pos_lookup_table =
  51. Hasher::<AesHashFunction<u32>, _>::compute_pos_lookup_table(domain_size, &hash_table);
  52. b.iter(|| {
  53. for item in 0..domain_size {
  54. for &(bucket_i, _) in values[item as usize].iter() {
  55. let idx = Hasher::<AesHashFunction<u32>, _>::pos_lookup(
  56. &pos_lookup_table,
  57. bucket_i,
  58. item,
  59. );
  60. black_box(idx);
  61. }
  62. }
  63. })
  64. });
  65. group.bench_function("precomputation+lookup", |b| {
  66. b.iter(|| {
  67. let pos_lookup_table = Hasher::<AesHashFunction<u32>, _>::compute_pos_lookup_table(
  68. domain_size,
  69. &hash_table,
  70. );
  71. for item in 0..domain_size {
  72. for &(bucket_i, _) in values[item as usize].iter() {
  73. let idx = Hasher::<AesHashFunction<u32>, _>::pos_lookup(
  74. &pos_lookup_table,
  75. bucket_i,
  76. item,
  77. );
  78. black_box(idx);
  79. }
  80. }
  81. })
  82. });
  83. group.finish();
  84. }
  85. pub fn bench_cuckoo_hash_items(c: &mut Criterion) {
  86. for log_domain_size in LOG_DOMAIN_SIZES {
  87. let log_number_inputs = log_domain_size / 2;
  88. let parameters = Parameters::<AesHashFunction<u32>, _>::sample(1 << log_number_inputs);
  89. let hasher = Hasher::new(parameters);
  90. let items: Vec<u64> = (0..1 << log_number_inputs).collect();
  91. c.bench_with_input(
  92. BenchmarkId::new("Hasher<AesHashFunction>.cuckoo_hash_items", log_domain_size),
  93. &log_domain_size,
  94. |b, _| b.iter(|| hasher.cuckoo_hash_items(black_box(&items))),
  95. );
  96. }
  97. }
  98. criterion_group!(
  99. benches,
  100. bench_hash_domain_into_buckets,
  101. bench_position_map,
  102. bench_cuckoo_hash_items
  103. );
  104. criterion_main!(benches);