Skip to content

[improve][ml] Optimize individual-ack filtering by skipping scans for batches without acked entries - #26311

Open
void-ptr974 wants to merge 1 commit into
apache:masterfrom
void-ptr974:codex/optimize-individual-ack-contains-any
Open

[improve][ml] Optimize individual-ack filtering by skipping scans for batches without acked entries#26311
void-ptr974 wants to merge 1 commit into
apache:masterfrom
void-ptr974:codex/optimize-individual-ack-contains-any

Conversation

@void-ptr974

Copy link
Copy Markdown
Contributor

Motivation

ManagedCursorImpl.filterReadEntries uses the global span of individually acknowledged positions to decide whether a read batch needs per-entry filtering.

The span does not represent holes between acknowledged positions or ledgers. A read batch inside such a hole can therefore be treated as potentially overlapping, causing every entry in the batch to be checked and a new result list to be allocated even when the batch contains no acknowledged entries.

Modifications

  • Add PositionRangeSet.containsAny to query whether a ledger-local entry range contains an individually acknowledged position.
  • Use the exact bitmap range query before performing per-entry filtering.
  • Keep a conservative per-entry filtering fallback for unexpected batches that cross ledger boundaries.
  • Add deterministic boundary tests and 96,000 reproducible randomized comparisons against a boolean-array oracle.
  • Add a managed-cursor regression test that verifies a batch inside an individual-ack span hole takes the fast path and returns the original list.
  • Add a JMH benchmark for hit, no-hit, sparse-gap, missing-ledger, and empty-set scenarios.

Verifying this change

  • Make sure that the change passes the CI checks.

This change added tests and can be verified as follows:

./gradlew :managed-ledger:test \
  --tests org.apache.bookkeeper.mledger.impl.PositionRangeSetTest \
  --tests org.apache.bookkeeper.mledger.impl.ManagedCursorTest.testReadEntriesWithSkipDeletedEntries \
  --tests org.apache.bookkeeper.mledger.impl.ManagedCursorTest.testFilterReadEntriesSkipsFilteringForGapBetweenIndividualAcks \
  -PtestRetryCount=0
./gradlew :microbench:compileJava :microbench:checkstyleMain quickCheck

Representative JMH results on Java 21 with a batch size of 100:

Scenario Span-based check Bitmap range check
Sparse gap 4132 ns/op 26 ns/op
Missing ledger 1494 ns/op 5 ns/op
Outside span 79 ns/op 23 ns/op

The no-hit scenarios also avoid the intermediate result-list allocation. Scenarios with acknowledged entries remain comparable because they continue to use the existing per-entry filtering path.

Does this pull request potentially affect one of the following parts:

  • Dependencies (add or upgrade a dependency)
  • The public API
  • The schema
  • The default values of configurations
  • The threading model
  • The binary protocol
  • The REST endpoints
  • The admin CLI options
  • The metrics
  • Anything that affects deployment

@void-ptr974
void-ptr974 marked this pull request as ready for review August 11, 2026 13:17
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.

1 participant