Skip to content

perf(core): decode aggregated bloom filter rows on demand via raw-blob views - #4022

Open
infrmtcs-agent[bot] wants to merge 1 commit into
mainfrom
dat/optimize-getevents
Open

infrmtcs-agent[bot] wants to merge 1 commit into
mainfrom
dat/optimize-getevents

Conversation

@infrmtcs-agent

@infrmtcs-agent infrmtcs-agent Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

User description

Summary

  • Decode aggregated bloom filter rows on demand via raw-blob views instead of eagerly deserializing full rows

PR Type

Enhancement, Tests


Description

  • Optimize bloom filter decoding performance

    • Introduce AggregatedBloomFilterView to decode rows on demand from raw-blob views.
    • Enhance memory usage in intersectRows and bitset manipulations.
  • Refactor cache and core blockchain logic

    • Update AggregatedBloomFilterCache to manage and return raw-blob views.
    • Introduce blockKeyFilter interface to support both filters and views.
    • Add GetAggregatedBloomFilterView database accessor.
  • Improve testing and benchmarking

    • Parametrize unit tests for both AggregatedBloomFilter and its view.
    • Add BlocksForKeysInto benchmarks to evaluate both implementations.

File Walkthrough

Relevant files
Enhancement
7 files
aggregated_bloom_filter_cache.go
Update cache to use raw-blob views instead of decoded filters
+19/-17 
blockchain.go
Update blockchain fallback to fetch aggregated bloom filter views
+2/-2     
event_matcher.go
Introduce blockKeyFilter interface for event matching abstraction
+10/-1   
accessors.go
Add GetAggregatedBloomFilterView for database retrieval   
+15/-0   
aggregated_bloom_filter.go
Refactor BlocksForKeys to utilize BlocksForKeysInto           
+3/-15   
aggregated_bloom_filter_rows.go
Implement blobRows and optimize row intersection logic     
+59/-28 
aggregated_bloom_filter_view.go
Define AggregatedBloomFilterView and optimize key matching logic
+15/-6   
Tests
3 files
aggregated_bloom_filter_cache_test.go
Adapt cache tests to use raw-blob views helper                     
+19/-2   
aggregated_bloom_filter_bench_test.go
Add benchmarks for filter and view BlocksForKeysInto methods
+48/-0   
aggregated_bloom_filter_test.go
Parametrize tests to cover both decoded filters and raw-blob views
+254/-104

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @infrmtcs-agent[bot]'s task in 4m 36s —— View job


Review: PR #4022 — decode aggregated bloom filter rows on demand

  • Gather context (diff, changed files)
  • Understand the change (bloom filter row decoding via raw-blob views)
  • Review correctness / concurrency / resource-leak concerns
  • Review tests
  • Post findings

Summary: This is a clean, well-executed optimization. AggregatedBloomFilterView/blobRows decode only the rows a query's keys hash to, instead of eagerly materializing all 8192 rows into bitset.BitSets. I traced the aliasing between innerWords and the bitset.BitSet wrapper in filterView.BlocksForKeysInto (core/aggregated_bloom_filter_view.go:48-61) against the bitset.FromWithLength semantics already relied on elsewhere in this package, and the bounds math in rowWords (core/aggregated_bloom_filter_rows.go:109-121) against parseHeader's exact-length check — both hold up. blobRows.unmarshalRows correctly clones the input (bytes.Clone) to satisfy the BinaryUnmarshaler "don't retain data" contract, which matters since the bytes originate from a DB read callback. No concurrency issues: cached *AggregatedBloomFilterView instances are read-only after construction, so concurrent BlocksForKeysInto calls from the LRU cache are safe. Tests are thorough — table-driven corruption tests now correctly distinguish eager (filter) vs. lazy (view) error surfacing, plus a fuzz test and an allocation-count regression test.

No blockers or important issues found.

Nits (informational, not blocking):

  • core/aggregated_bloom_filter_rows.go:26-31: intersectRows's contract now requires indices to be pre-reduced mod EventsBloomLength; if that invariant is ever violated by a future caller it panics (index-out-of-range) rather than returning an error. Currently safe since filterView.BlocksForKeysInto is the only caller and always reduces first — just worth keeping in mind if this interface gains another caller.
  • Row corruption in a blobRows-backed view is only detected the first time a query happens to touch the corrupted row (vs. the eager AggregatedBloomFilter, which validates all rows at decode time). This is intentional and well covered by TestAggregatedBloomFilter_UnmarshalBinary_Corrupt, just a behavior change worth being aware of for anyone relying on "load succeeds ⇒ blob is fully valid."
    · branch: dat/optimize-geteventsdat/bloom-filter-view-layer

@codecov

codecov Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.33962% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.35%. Comparing base (71d25f5) to head (5d05b4d).

Files with missing lines Patch % Lines
blockchain/blockchain.go 50.00% 1 Missing ⚠️
core/accessors.go 83.33% 1 Missing ⚠️
core/aggregated_bloom_filter.go 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4022      +/-   ##
==========================================
- Coverage   79.48%   79.35%   -0.13%     
==========================================
  Files         466      466              
  Lines       36009    36025      +16     
==========================================
- Hits        28620    28587      -33     
- Misses       7380     7429      +49     
  Partials        9        9              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@infrmtcs
infrmtcs requested a review from rodrodros September 4, 2026 04:09
@rodrodros
rodrodros requested a review from EgeCaner September 7, 2026 11:59
Base automatically changed from dat/bloom-filter-view-layer to main September 8, 2026 11:03
@rodrodros

Copy link
Copy Markdown
Contributor

@infrmtcs can you add some numbers to this PR

// indices are raw bloom locations, not yet reduced modulo EventsBloomLength.
intersectRows(rawIndices []uint64, innerMatches *bitset.BitSet) error
// indices are already reduced modulo EventsBloomLength.
intersectRows(indices, acc []uint64) error

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: acc -> accumulator or matchWords

}

// rowWords validates row index's length prefixes and returns its raw word bytes.
func (r blobRows) rowWords(index uint64) ([]byte, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: may rename to rowWordBytes or rowBytes since it doesn't return words

offset := filterHeaderSize + int(index)*filterRowSize
// bitsetLen and blobLen are independent fields, so both are checked.
if blobLen := int(binary.BigEndian.Uint32(r[offset:])); blobLen != filterRowBlobLen {
return nil, ErrBloomFilterSizeMismatch

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: can be wrapped with context to avoid ambiguity with error below

}
offset += filterRowLenSize
if bitsetLen := binary.BigEndian.Uint64(r[offset:]); bitsetLen != NumBlocksPerFilter {
return nil, ErrBloomFilterSizeMismatch

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: can be wrapped with context to avoid ambiguity with error above

}

// parseHeader validates the blob framing and sets v's block range.
func (v *filterView[R, PR]) parseHeader(data []byte) error {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The four checks here return two bare sentinels between them, worth wrapping with the got/want values so a corrupt blob says which check failed instead of just unexpected EOF or bloom filter len mismatch.

@infrmtcs
infrmtcs force-pushed the dat/optimize-getevents branch from b947d69 to 5d05b4d Compare September 15, 2026 10:35
@github-actions

github-actions Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Review in progress

  • Gather context (diff vs origin/main, changed files)
  • Review correctness / concurrency / resource-leak concerns
  • Review tests
  • Post findings

View job run

@infrmtcs
infrmtcs deployed to Development September 15, 2026 10:53 — with GitHub Actions Active
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants