@@ -357,27 +357,80 @@ void executor::scan_collisions() const
357357 // point
358358 // ------------------------------------------------------------------------
359359
360- auto total = zero;
361360 index = max_size_t ;
362361 start = logger::now ();
363362 const auto point_buckets = query_.point_buckets ();
364363 std_vector<size_t > spend (point_buckets, empty);
365- while (!cancel_ && (++index < query_.header_records ()))
364+ auto inserts = zero;
365+
366+ // TODO: expose filter type from hashhead to table.
367+ // /////////////////////////////////////////////////////////////////////////
368+ constexpr size_t m = 32 ;
369+ using bloom_t = bloom<m, 4 >;
370+ using sieve_t = sieve<m, 4 >;
371+ // /////////////////////////////////////////////////////////////////////////
372+
373+ constexpr auto empty_bloom = unmask_right<bloom_t ::type>(m);
374+ std_vector<bloom_t ::type> bloom_filter (point_buckets, empty_bloom);
375+ size_t bloom_collisions{};
376+ size_t bloom_subtotal{};
377+
378+ constexpr auto empty_sieve = unmask_right<sieve_t ::type>(m);
379+ std_vector<sieve_t ::type> sieve_filter (point_buckets, empty_sieve);
380+ size_t sieve_collisions{};
381+ size_t sieve_subtotal{};
382+
383+ size_t coinbases{};
384+ size_t window{};
385+
386+ while (!cancel_ && (++index <= query_.get_top_candidate ()))
366387 {
388+ ++coinbases;
367389 const header_link link{ possible_narrow_cast<hint>(index) };
368390 const auto transactions = query_.to_transactions (link);
369391 for (const auto & transaction: transactions)
370392 {
371393 const auto points = query_.to_points (transaction);
372394 for (const auto & point: points)
373395 {
396+ // If and only if coinbase bucket is one.
374397 const auto key = query_.get_point (point);
375- ++spend.at (database::keys::hash (key) % point_buckets);
376- ++total;
398+ const auto bucket = database::keys::bucket (key, point_buckets);
399+ const auto entropy = database::keys::thumb (key);
400+ ++spend.at (bucket);
401+ ++inserts;
402+ ++window;
403+
404+ auto prev = bloom_filter.at (bucket);
405+ auto next = bloom_t::screen (prev, entropy);
406+ bloom_filter.at (bucket) = next;
407+ auto coll = to_int (bloom_t::is_collision (prev, next));
408+ bloom_collisions += coll;
409+ bloom_subtotal += coll;
410+
411+ prev = sieve_filter.at (bucket);
412+ next = sieve_t::screen (prev, entropy);
413+ sieve_filter.at (bucket) = next;
414+ coll = to_int (sieve_t::is_collision (prev, next));
415+ sieve_collisions += coll;
416+ sieve_subtotal += coll;
417+
418+ if (is_zero (inserts % put_frequency))
419+ {
420+ logger (format (" point: %1% bloom fps %2% rate %3$.7f in %4% secs." ) %
421+ inserts % bloom_collisions %
422+ (to_double (bloom_subtotal) / window) %
423+ duration_cast<seconds>(logger::now () - start).count ());
377424
378- if (is_zero (total % put_frequency))
379- logger (format (" point" BN_READ_ROW) % total %
425+ logger (format (" point: %1% sieve fps %2% rate %3$.7f in %4% secs." ) %
426+ inserts% sieve_collisions %
427+ (to_double (sieve_subtotal) / window) %
380428 duration_cast<seconds>(logger::now () - start).count ());
429+
430+ bloom_subtotal = zero;
431+ sieve_subtotal = zero;
432+ window = zero;
433+ }
381434 }
382435 }
383436 }
@@ -390,15 +443,31 @@ void executor::scan_collisions() const
390443 const auto point_count = count (spend);
391444 span = duration_cast<seconds>(logger::now () - start);
392445 logger (format (" point: %1% in %2%s buckets %3% filled %4% rate %5%" ) %
393- total % span.count () % point_buckets % point_count %
446+ inserts % span.count () % point_buckets % point_count %
394447 (to_double (point_count) / point_buckets));
395448
449+ const auto spends = inserts - coinbases;
450+ const auto bloom_spend_collisions = bloom_collisions - coinbases;
451+ logger (format (" bloom: %1% fps of %2% spends (ex %3% cbs) rate %4%" ) %
452+ bloom_spend_collisions % spends % coinbases %
453+ (to_double (bloom_spend_collisions) / spends));
454+
455+ const auto sieve_spend_collisions = sieve_collisions - coinbases;
456+ logger (format (" sieve: %1% fps of %2% spends (ex %3% cbs) rate %4%" ) %
457+ sieve_spend_collisions % spends % coinbases %
458+ (to_double (sieve_spend_collisions) / spends));
459+
396460 for (const auto & entry: dump (spend))
397461 logger (format (" point: %1% frequency: %2%" ) %
398462 entry.first % entry.second );
399463
400- // //point.clear();
401- // //point.shrink_to_fit();
464+
465+ // //spend.clear();
466+ // //spend.shrink_to_fit();
467+ // //bloom_filter.clear();
468+ // //bloom_filter.shrink_to_fit();
469+ // //sieve_filter.clear();
470+ // //sieve_filter.shrink_to_fit();
402471}
403472
404473} // namespace node
0 commit comments