Skip to content

Improve Block caching and reduce lookup allocations#8943

Open
benaadams wants to merge 9 commits into
masterfrom
blockcaching
Open

Improve Block caching and reduce lookup allocations#8943
benaadams wants to merge 9 commits into
masterfrom
blockcaching

Conversation

@benaadams

@benaadams benaadams commented Jul 5, 2025

Copy link
Copy Markdown
Member

Changes

  • Introduce block hash -> block number cache
  • Layer header cache, depending if difficulty is available or canonical
  • Add ability to only decode tx haches as used by RemoveOldReceipts rather than allocating everything; also use for eth_eth_getBlockBy... when only hashes
  • Delay RemoveOldReceipts by half of the GC delay
  • Introduce fast generic constructor, rather than the slower new T() vis CreateInstanceT
  • Return header directly if found in cache
  • Reduce delayed hash from 32kB to 1kB as it burns through the array pool when decoding blocks

Types of changes

What types of changes does your code introduce?

  • Optimization

Testing

Requires testing

  • No

@benaadams benaadams mentioned this pull request Jul 5, 2025
2 tasks
@benaadams benaadams force-pushed the blockcaching branch 16 times, most recently from 4b1b634 to 8a7564d Compare July 8, 2025 17:36
@benaadams benaadams requested a review from Copilot July 8, 2025 21:32

Copilot AI left a comment

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.

Pull Request Overview

This PR enhances block and transaction caching, introduces a new OnlyHashes RLP decoding behavior to reduce allocations, replaces direct transaction object instantiation with a faster ObjectCreator<T>, and refactors GC and receipt pruning logic to use configuration constants and async methods.

  • Propagate RlpBehaviors.OnlyHashes through RLP decoders to skip full decoding when only hashes are needed.
  • Replace new T() calls with ObjectCreator<T>.Create to leverage expression-based instantiation.
  • Expand caching interfaces (IClockCache), integrate clock-based caches across key-value extensions, header store, block store, and block tree.
  • Refactor GC delay values into GCConfig, update PersistentReceiptStorage to async pruning.

Reviewed Changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/Nethermind/Nethermind.Serialization.Rlp/TxDecoders/BlobTxDecoder.cs Pass forceHashes flag to CalculateHash based on OnlyHashes.
src/Nethermind/Nethermind.Serialization.Rlp/TxDecoders/BaseTxDecoder.cs Expose static CalculateHash with forceHashes parameter.
src/Nethermind/Nethermind.Serialization.Rlp/TxDecoder.cs Handle OnlyHashes case in top‐level decoder.
src/Nethermind/Nethermind.Serialization.Rlp/RlpBehaviors.cs Add new OnlyHashes enum flag.
src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs Extend DecodeArray to accept RlpBehaviors.
src/Nethermind/Nethermind.Serialization.Rlp/KeyValueStoreRlpExtensions.cs Switch to IClockCache<> and add new Get overloads.
src/Nethermind/Nethermind.Serialization.Rlp/BlockDecoder.cs Propagate rlpBehaviors to BlockBodyDecoder.DecodeUnwrapped.
src/Nethermind/Nethermind.Serialization.Rlp/BlockBodyDecoder.cs Use rlpBehaviors to skip header and withdrawal decoding.
src/Nethermind/Nethermind.Merge.Plugin/Handlers/ForkchoiceUpdatedHandler.cs Rename boolean parameters in UpdateMainChain call.
src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs Replace hardcoded delay with GCConfig.GCBlockProcessingDelayMs.
src/Nethermind/Nethermind.Facade/Simulate/SimulateDictionaryHeaderStore.cs Remove unused shouldCache, update Cache signature.
src/Nethermind/Nethermind.Core/Utils/ObjectCreator.cs Add ObjectCreator<T> using expression trees for instantiation.
src/Nethermind/Nethermind.Core/Caching/IClockCache.cs Introduce new IClockCache interface.
src/Nethermind/Nethermind.Core/Caching/ClockCache.cs Implement IClockCache on ClockCache.
src/Nethermind/Nethermind.Config/GCConfig.cs Add static GC delay constant.
src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs Refactor receipt pruning to async using GCConfig.
src/Nethermind/Nethermind.Blockchain/Headers/IHeaderStore.cs Extend header store interface for new caching semantics.
src/Nethermind/Nethermind.Blockchain/Headers/HeaderStore.cs Integrate new header‐number cache and multi‐tier header caches.
src/Nethermind/Nethermind.Blockchain/Blocks/BlockStore.cs Inline cache declaration.
src/Nethermind/Nethermind.Blockchain/BlockTreeMethodOptions.cs Add OnlyTxHashes lookup option.
src/Nethermind/Nethermind.Blockchain/BlockTree.cs Integrate OnlyTxHashes into block tree cache and lookup logic.
src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs Convert tests to async/Task and increase delays.
src/Nethermind/Nethermind.Blockchain.Test/Blocks/HeaderStoreTests.cs Update Cache call to new signature.
Comments suppressed due to low confidence (1)

src/Nethermind/Nethermind.Serialization.Rlp/KeyValueStoreRlpExtensions.cs:26

  • [nitpick] This overload uses stackalloc for the 40-byte key buffer but lacks [SkipLocalsInit], which could zero-init locals unnecessarily. Consider adding [SkipLocalsInit] for performance.
    public static TItem? Get<TItem>(this IReadOnlyKeyValueStore db, long blockNumber, Hash256 hash, IRlpStreamDecoder<TItem> decoder,

Comment thread src/Nethermind/Nethermind.Blockchain/Headers/HeaderStore.cs
@benaadams benaadams marked this pull request as ready for review July 8, 2025 22:30
@benaadams benaadams marked this pull request as draft July 8, 2025 22:31
@benaadams benaadams force-pushed the blockcaching branch 2 times, most recently from 0211e45 to 8a7564d Compare July 8, 2025 22:53
@benaadams benaadams marked this pull request as ready for review July 8, 2025 23:12
@benaadams benaadams requested a review from asdacap July 9, 2025 09:23
@benaadams benaadams requested a review from LukaszRozmej July 9, 2025 10:37
AllowInvalid = 8,
ExcludeTxHashes = 16,
All = 31
All = 31,

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.

Shouldn't All option also be updated? Or maybe renamed somehow to avoid confusion?

Comment on lines +17 to +19
bool Cache(BlockHeader header, bool hasDifficulty, bool isCanonical = false);
bool TryGetCache(Hash256 blockHash, bool needsDifficulty, bool requiresCanonical, [NotNullWhen(true)] out BlockHeader? header);
void DeleteCanonicalCache(Hash256 blockHash);

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.

a bit weird that caching is exposed


private async Task RemoveOldReceipts(long blockNumber)
{
await Task.Delay(GCConfig.GCBlockProcessingDelayMs / 2);

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.

why delay?

Comment on lines +13 to +29
public static Func<T> Create { get; } = BuildCreator();

private static Func<T> BuildCreator()
{
// find the public parameterless ctor (throws if none)
ConstructorInfo? ci = typeof(T).GetConstructor(BindingFlags.Public | BindingFlags.Instance, []) ??
throw new InvalidOperationException($"{typeof(T).Name} has no parameterless ctor.");

NewExpression newExpr = Expression.New(ci);
Expression<Func<T>> lambda = Expression.Lambda<Func<T>>(
newExpr,
name: $"Create{typeof(T).Name}",
tailCall: false,
parameters: Array.Empty<ParameterExpression>()
);
return lambda.Compile();
}

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.

In newest dotnet Activator isn't similar speed? There were improvements in dontet 8 and 9 to it

@benaadams benaadams mentioned this pull request Oct 27, 2025
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants