Skip to content

Use hashlink over lru for LruCache#8911

Open
macladson wants to merge 1 commit intosigp:unstablefrom
macladson:use-hashlink-over-lru
Open

Use hashlink over lru for LruCache#8911
macladson wants to merge 1 commit intosigp:unstablefrom
macladson:use-hashlink-over-lru

Conversation

@macladson
Copy link
Member

Proposed Changes

Use the LruCache implementation provided by hashlink instead of the current lru one.
This is mostly a 1-to-1 swap with only slight API incompatibilities.
I have decided to leave some config files which previously used NonZeroUsize but they may not be required anymore and could potentially switch to usize.

Additional Info

This also bumps hashlink to 0.11.

Once we update libp2p and discv5, it will remove lru as a dependency outside of the execution_engine_integration testing binary (brought in by alloy-provider).

@macladson macladson added the work-in-progress PR is a work-in-progress label Feb 27, 2026
@macladson macladson requested a review from jxs as a code owner February 27, 2026 16:35
@macladson macladson added code-quality dependencies Pull requests that update a dependency file ready-for-review The code is ready for review and removed work-in-progress PR is a work-in-progress labels Feb 27, 2026
@michaelsproul
Copy link
Member

Are there any benchmarks comparing lru to hashlink? Can you ask Claude to cook some up?

@macladson
Copy link
Member Author

Are there any benchmarks comparing lru to hashlink? Can you ask Claude to cook some up?

I got Claude to write some and here was its analysis (Disclaimer, I did not review the benchmarks):


Key Findings

  1. hashlink is significantly faster for read operations (get, peek, contains_key, get_miss) — consistently 16-26% faster across all cache sizes. This is the most common operation in all hot paths.

  2. lru is slightly faster for insert-with-eviction — about 2-3% faster, which is within noise for most scenarios.

  3. lru is slightly faster for remove — about 5-7% at small sizes, converging at larger sizes.

  4. The mixed-workload hot path simulations show lru winning — this is because the benchmarks include MediumValue allocation (256 bytes) in the entry().or_insert_with() / get_or_insert_mut() pattern. The hashlink entry() API has slightly different ergonomics where the entry value construction may differ from lru's get_or_insert_mut. The data availability and block cache benchmarks show the biggest gap because they involve higher insert ratios with medium-sized values.

  5. For the pre-finalization cache (hottest path), the two are essentially tied (~2% difference, within noise). This cache is dominated by contains_key which hashlink does faster, but the mix includes enough inserts to balance it out.

  6. For the payload ID cache, hashlink is slightly faster — this is a get-heavy workload on a larger cache where hashlink's read advantage shines.

Verdict

The migration is reasonable from a performance perspective. The read-heavy workloads (which dominate in production — the caches are mostly read with occasional writes) favor hashlink. The mixed workloads with medium/large values show a small regression due to insert overhead, but these are not the hottest paths in absolute terms. The pre-finalization cache (the single hottest path) shows no meaningful difference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

code-quality dependencies Pull requests that update a dependency file ready-for-review The code is ready for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants