Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce parallel prewarming overwork #7983

Merged
merged 7 commits into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ namespace Nethermind.Consensus.Processing;
public sealed class BlockCachePreWarmer(ReadOnlyTxProcessingEnvFactory envFactory, ISpecProvider specProvider, ILogManager logManager, PreBlockCaches? preBlockCaches = null) : IBlockCachePreWarmer
{
private readonly ObjectPool<IReadOnlyTxProcessorSource> _envPool = new DefaultObjectPool<IReadOnlyTxProcessorSource>(new ReadOnlyTxProcessingEnvPooledObjectPolicy(envFactory), Environment.ProcessorCount * 4);
private readonly ObjectPool<SystemTransaction> _systemTransactionPool = new DefaultObjectPool<SystemTransaction>(new DefaultPooledObjectPolicy<SystemTransaction>(), Environment.ProcessorCount * 4);
private readonly ILogger _logger = logManager.GetClassLogger<BlockCachePreWarmer>();

public Task PreWarmCaches(Block suggestedBlock, Hash256? parentStateRoot, IReleaseSpec spec, CancellationToken cancellationToken = default, params ReadOnlySpan<IHasAccessList> systemAccessLists)
Expand Down Expand Up @@ -135,15 +134,13 @@ private void WarmupTransactions(ParallelOptions parallelOptions, IReleaseSpec sp
ParallelUnbalancedWork.For<BlockState>(0, block.Transactions.Length, parallelOptions, new(this, block, stateRoot, spec), static (i, state) =>
{
IReadOnlyTxProcessorSource env = state.PreWarmer._envPool.Get();
SystemTransaction systemTransaction = state.PreWarmer._systemTransactionPool.Get();
Transaction? tx = null;
try
{
// If the transaction has already been processed or being processed, exit early
if (state.Block.TransactionProcessed > i) return state;

tx = state.Block.Transactions[i];
tx.CopyTo(systemTransaction);
using IReadOnlyTxProcessingScope scope = env.Build(state.StateRoot);

Address senderAddress = tx.SenderAddress!;
Expand All @@ -170,7 +167,7 @@ private void WarmupTransactions(ParallelOptions parallelOptions, IReleaseSpec sp
{
scope.WorldState.WarmUp(tx.AccessList); // eip-2930
}
TransactionResult result = scope.TransactionProcessor.Warmup(systemTransaction, new BlockExecutionContext(state.Block.Header.Clone()), NullTxTracer.Instance);
TransactionResult result = scope.TransactionProcessor.Warmup(tx, new BlockExecutionContext(state.BlockHeader), NullTxTracer.Instance);
if (state.PreWarmer._logger.IsTrace) state.PreWarmer._logger.Trace($"Finished pre-warming cache for tx[{i}] {tx.Hash} with {result}");
}
catch (Exception ex) when (ex is EvmException or OverflowException)
Expand All @@ -183,7 +180,6 @@ private void WarmupTransactions(ParallelOptions parallelOptions, IReleaseSpec sp
}
finally
{
state.PreWarmer._systemTransactionPool.Return(systemTransaction);
state.PreWarmer._envPool.Return(env);
}

Expand Down Expand Up @@ -308,12 +304,13 @@ private class ReadOnlyTxProcessingEnvPooledObjectPolicy(ReadOnlyTxProcessingEnvF
public bool Return(IReadOnlyTxProcessorSource obj) => true;
}

private struct BlockState(BlockCachePreWarmer preWarmer, Block block, Hash256 stateRoot, IReleaseSpec spec)
private readonly struct BlockState(BlockCachePreWarmer preWarmer, Block block, Hash256 stateRoot, IReleaseSpec spec)
{
public BlockCachePreWarmer PreWarmer = preWarmer;
public Block Block = block;
public Hash256 StateRoot = stateRoot;
public IReleaseSpec Spec = spec;
public readonly BlockCachePreWarmer PreWarmer = preWarmer;
public readonly Block Block = block;
public readonly Hash256 StateRoot = stateRoot;
public readonly IReleaseSpec Spec = spec;
public readonly BlockHeader BlockHeader => Block.Header;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ protected override TransactionResult Execute(Transaction tx, in BlockExecutionCo
WorldState.CreateAccountIfNotExists(Address.SystemUser, UInt256.Zero, UInt256.Zero);
}

return base.Execute(tx, in blCtx, tracer, (opts != ExecutionOptions.Warmup && !opts.HasFlag(ExecutionOptions.NoValidation))
? opts | (ExecutionOptions)OriginalValidate | ExecutionOptions.NoValidation
return base.Execute(tx, in blCtx, tracer, (opts != ExecutionOptions.SkipValidation && !opts.HasFlag(ExecutionOptions.SkipValidationAndCommit))
? opts | (ExecutionOptions)OriginalValidate | ExecutionOptions.SkipValidationAndCommit
: opts);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,17 @@ protected enum ExecutionOptions
/// <summary>
/// Skip potential fail checks
/// </summary>
Warmup = 4,
SkipValidation = 4,

/// <summary>
/// Skip potential fail checks and commit state after execution
/// </summary>
NoValidation = Commit | Warmup,
SkipValidationAndCommit = Commit | SkipValidation,

/// <summary>
/// Commit and later restore state also skip validation, use for CallAndRestore
/// </summary>
CommitAndRestore = Commit | Restore | NoValidation
CommitAndRestore = Commit | Restore | SkipValidation
}

protected TransactionProcessorBase(
Expand Down Expand Up @@ -115,10 +115,10 @@ public TransactionResult Execute(Transaction transaction, in BlockExecutionConte
ExecuteCore(transaction, in blCtx, txTracer, ExecutionOptions.Commit);

public TransactionResult Trace(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) =>
ExecuteCore(transaction, in blCtx, txTracer, ExecutionOptions.NoValidation);
ExecuteCore(transaction, in blCtx, txTracer, ExecutionOptions.SkipValidationAndCommit);

public TransactionResult Warmup(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) =>
ExecuteCore(transaction, in blCtx, txTracer, ExecutionOptions.Warmup);
ExecuteCore(transaction, in blCtx, txTracer, ExecutionOptions.SkipValidation);

private TransactionResult ExecuteCore(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, ExecutionOptions opts)
{
Expand All @@ -141,7 +141,7 @@ protected virtual TransactionResult Execute(Transaction tx, in BlockExecutionCon
// commit - is for standard execute, we will commit thee state after execution
// !commit - is for build up during block production, we won't commit state after each transaction to support rollbacks
// we commit only after all block is constructed
bool commit = opts.HasFlag(ExecutionOptions.Commit) || (!opts.HasFlag(ExecutionOptions.Warmup) && !spec.IsEip658Enabled);
bool commit = opts.HasFlag(ExecutionOptions.Commit) || (!opts.HasFlag(ExecutionOptions.SkipValidation) && !spec.IsEip658Enabled);

TransactionResult result;
if (!(result = ValidateStatic(tx, header, spec, opts, out long intrinsicGas))) return result;
Expand Down Expand Up @@ -177,7 +177,7 @@ protected virtual TransactionResult Execute(Transaction tx, in BlockExecutionCon
}
else
{
if (!opts.HasFlag(ExecutionOptions.NoValidation))
if (!opts.HasFlag(ExecutionOptions.SkipValidation))
WorldState.AddToBalance(tx.SenderAddress!, senderReservedGasPayment, spec);
DecrementNonce(tx);

Expand Down Expand Up @@ -347,7 +347,7 @@ protected virtual TransactionResult ValidateStatic(
{
intrinsicGas = IntrinsicGasCalculator.Calculate(tx, spec);

bool validate = !opts.HasFlag(ExecutionOptions.NoValidation);
bool validate = !opts.HasFlag(ExecutionOptions.SkipValidation);

if (tx.SenderAddress is null)
{
Expand Down Expand Up @@ -401,7 +401,7 @@ protected virtual bool RecoverSenderIfNeeded(Transaction tx, IReleaseSpec spec,
{
bool commit = opts.HasFlag(ExecutionOptions.Commit) || !spec.IsEip658Enabled;
bool restore = opts.HasFlag(ExecutionOptions.Restore);
bool noValidation = opts.HasFlag(ExecutionOptions.NoValidation);
bool noValidation = opts.HasFlag(ExecutionOptions.SkipValidation);

if (Logger.IsDebug) Logger.Debug($"TX sender account does not exist {sender} - trying to recover it");

Expand Down Expand Up @@ -436,7 +436,7 @@ protected virtual bool RecoverSenderIfNeeded(Transaction tx, IReleaseSpec spec,

protected virtual TransactionResult ValidateSender(Transaction tx, BlockHeader header, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts)
{
bool validate = !opts.HasFlag(ExecutionOptions.NoValidation);
bool validate = !opts.HasFlag(ExecutionOptions.SkipValidation);

if (validate && WorldState.IsInvalidContractSender(spec, tx.SenderAddress!))
{
Expand All @@ -453,7 +453,7 @@ protected virtual TransactionResult BuyGas(Transaction tx, BlockHeader header, I
premiumPerGas = UInt256.Zero;
senderReservedGasPayment = UInt256.Zero;
blobBaseFee = UInt256.Zero;
bool validate = !opts.HasFlag(ExecutionOptions.NoValidation);
bool validate = !opts.HasFlag(ExecutionOptions.SkipValidation);

if (validate)
{
Expand Down Expand Up @@ -579,7 +579,7 @@ private ExecutionEnvironment BuildExecutionEnvironment(
);
}

protected virtual bool ShouldValidate(ExecutionOptions opts) => !opts.HasFlag(ExecutionOptions.NoValidation);
protected virtual bool ShouldValidate(ExecutionOptions opts) => !opts.HasFlag(ExecutionOptions.SkipValidation);

protected virtual void ExecuteEvmCall(
Transaction tx,
Expand Down Expand Up @@ -696,7 +696,7 @@ protected virtual void ExecuteEvmCall(
WorldState.Restore(snapshot);

Complete:
if (!opts.HasFlag(ExecutionOptions.NoValidation))
if (!opts.HasFlag(ExecutionOptions.SkipValidation))
Copy link
Member

Choose a reason for hiding this comment

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

I was worried that we might modify the header, but we probably are not modifying it?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not inside a single tx run as we aren't doing block processing

header.GasUsed += spentGas;
}

Expand Down Expand Up @@ -765,7 +765,7 @@ protected virtual long Refund(Transaction tx, BlockHeader header, IReleaseSpec s
if (Logger.IsTrace)
Logger.Trace("Refunding unused gas of " + unspentGas + " and refund of " + actualRefund);
// If noValidation we didn't charge for gas, so do not refund
if (!opts.HasFlag(ExecutionOptions.NoValidation))
if (!opts.HasFlag(ExecutionOptions.SkipValidation))
WorldState.AddToBalance(tx.SenderAddress!, (ulong)(unspentGas + actualRefund) * gasPrice, spec);
spentGas -= actualRefund;
}
Expand All @@ -776,7 +776,7 @@ protected virtual long Refund(Transaction tx, BlockHeader header, IReleaseSpec s
if (Logger.IsTrace)
Logger.Trace("Refunding delegations only: " + refund);
// If noValidation we didn't charge for gas, so do not refund
if (!opts.HasFlag(ExecutionOptions.NoValidation))
if (!opts.HasFlag(ExecutionOptions.SkipValidation))
WorldState.AddToBalance(tx.SenderAddress!, (ulong)refund * gasPrice, spec);
spentGas -= refund;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Evm/VirtualMachine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2496,7 +2496,7 @@ private EvmExceptionType InstructionLog<TTracing>(EvmState vmState, ref EvmStack

ReadOnlyMemory<byte> data = vmState.Memory.Load(in position, length);
Hash256[] topics = new Hash256[topicsCount];
for (int i = 0; i < topicsCount; i++)
for (int i = 0; i < topics.Length; i++)
{
topics[i] = new Hash256(stack.PopWord256());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ protected override TransactionResult Execute(Transaction tx, in BlockExecutionCo
{
if (!validate)
{
opts |= ExecutionOptions.NoValidation;
opts |= ExecutionOptions.SkipValidation;
}

return base.Execute(tx, in blCtx, tracer, opts);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ protected override TransactionResult BuyGas(Transaction tx, BlockHeader header,
senderReservedGasPayment = UInt256.Zero;
blobBaseFee = UInt256.Zero;

bool validate = !opts.HasFlag(ExecutionOptions.NoValidation);
bool validate = !opts.HasFlag(ExecutionOptions.SkipValidation);

UInt256 senderBalance = WorldState.GetBalance(tx.SenderAddress!);

Expand Down
6 changes: 3 additions & 3 deletions src/Nethermind/Nethermind.Taiko/TaikoTransactionProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ public class TaikoTransactionProcessor(
{
protected override TransactionResult ValidateStatic(Transaction tx, BlockHeader header, IReleaseSpec spec, ExecutionOptions opts,
out long intrinsicGas)
=> base.ValidateStatic(tx, header, spec, tx.IsAnchorTx ? opts | ExecutionOptions.NoValidation : opts, out intrinsicGas);
=> base.ValidateStatic(tx, header, spec, tx.IsAnchorTx ? opts | ExecutionOptions.SkipValidationAndCommit : opts, out intrinsicGas);

protected override TransactionResult BuyGas(Transaction tx, BlockHeader header, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts,
in UInt256 effectiveGasPrice, out UInt256 premiumPerGas, out UInt256 senderReservedGasPayment, out UInt256 blobBaseFee)
=> base.BuyGas(tx, header, spec, tracer, tx.IsAnchorTx ? opts | ExecutionOptions.NoValidation : opts, in effectiveGasPrice, out premiumPerGas, out senderReservedGasPayment, out blobBaseFee);
=> base.BuyGas(tx, header, spec, tracer, tx.IsAnchorTx ? opts | ExecutionOptions.SkipValidationAndCommit : opts, in effectiveGasPrice, out premiumPerGas, out senderReservedGasPayment, out blobBaseFee);

protected override long Refund(Transaction tx, BlockHeader header, IReleaseSpec spec, ExecutionOptions opts,
in TransactionSubstate substate, in long unspentGas, in UInt256 gasPrice, int codeInsertRefunds)
=> base.Refund(tx, header, spec, tx.IsAnchorTx ? opts | ExecutionOptions.NoValidation : opts, substate, unspentGas, gasPrice, codeInsertRefunds);
=> base.Refund(tx, header, spec, tx.IsAnchorTx ? opts | ExecutionOptions.SkipValidationAndCommit : opts, substate, unspentGas, gasPrice, codeInsertRefunds);

protected override void PayFees(Transaction tx, BlockHeader header, IReleaseSpec spec, ITxTracer tracer, in TransactionSubstate substate, in long spentGas, in UInt256 premiumPerGas, in UInt256 blobBaseFee, in byte statusCode)
{
Expand Down
Loading