Skip to content

[improve][ml] Parse message metadata at entry cache insert time instead of under the wrapper write lock - #26463

Open
merlimat wants to merge 1 commit into
apache:masterfrom
merlimat:mmerli/entry-cache-metadata-parse-at-insert
Open

[improve][ml] Parse message metadata at entry cache insert time instead of under the wrapper write lock#26463
merlimat wants to merge 1 commit into
apache:masterfrom
merlimat:mmerli/entry-cache-metadata-parse-at-insert

Conversation

@merlimat

@merlimat merlimat commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Motivation

Profiling a broker under a tailing workload showed EntryImpl.initializeMessageMetadataIfNeeded being invoked from RangeCacheEntryWrapper.withWriteLock, i.e. a write lock taken on the entry cache read path.

Entries reach the cache through two paths. The read-miss path in RangeEntryCacheImpl.readFromStorage already parses the message metadata before inserting. The tailing-write path in OpAddEntry inserts entries with no parsed metadata, so the first cache read of every freshly published entry has to take the wrapper write lock, parse the metadata inside it, and every other cursor reading the same entry is serialized behind that lock. With several subscriptions tailing a topic this is the common case, not the exception.

Modifications

  • RangeEntryCacheImpl.insert now parses the message metadata once before creating the cached entry. Since insert is the single chokepoint for both the add path and the read-miss path, the cached copy always carries its metadata. On the read-miss path this is a no-op because the entry is already parsed.
  • RangeCacheEntryWrapper.withNewInstance marks messageMetadataInitialized when the value already has metadata, so reads stay on the optimistic-read branch and never enter the write lock for it. The lazy initialization is kept as a fallback for values inserted without metadata (non-EntryImpl values or a failed parse).

The parse cost itself is not removed, it moves from the first read to the add path on the managed ledger executor. The net effect is that each entry is parsed exactly once, with no lock and no cross-cursor contention on the read path.

Verifying this change

  • Make sure that the change passes the CI checks.

This change added tests and can be verified as follows:

  • Added RangeEntryCacheImplTest.testInsertParsesMessageMetadata, which inserts an entry built from a real serialized message with no pre-parsed metadata and asserts that the insert itself populated it.
  • Existing RangeCacheTest, RangeCacheRemovalQueueTest and RangeEntryCacheImplTest pass.

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

If the box was checked, please highlight the changes

  • 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

…ad of under the wrapper write lock

Motivation

Profiling showed EntryImpl.initializeMessageMetadataIfNeeded being called
from RangeCacheEntryWrapper.withWriteLock on the cache read path. Entries
inserted from the add path (OpAddEntry) carried no parsed metadata, so the
first cache read of every tailing entry took the wrapper write lock, parsed
the metadata and serialized all concurrent readers of that entry behind it.

Modifications

- RangeEntryCacheImpl.insert parses the message metadata once before creating
  the cached entry, so both the add path and the read-miss path insert
  entries that already carry metadata.
- RangeCacheEntryWrapper marks messageMetadataInitialized at creation when the
  value already has metadata, so reads never take the write lock for it. The
  lazy initialization remains as a fallback for values inserted without it.
- Add a unit test covering insert-time parsing.
@merlimat
merlimat requested a review from lhotari September 4, 2026 17:40

@lhotari lhotari left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@lhotari

lhotari commented Sep 4, 2026

Copy link
Copy Markdown
Member

The tailing-write path in OpAddEntry inserts entries with no parsed metadata

There's a PR to reduce metadata parsing on the publish path, #25555. The metadata gets parsed multiple times currently.
It should be possible to build upon that PR with changes to ensure that entries are added to the cache with parsed metadata.

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.

2 participants