Skip to content

Commit

Permalink
Less allocations
Browse files Browse the repository at this point in the history
  • Loading branch information
benaadams committed Nov 28, 2024
1 parent 8f5f328 commit 061956a
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 25 deletions.
19 changes: 19 additions & 0 deletions src/Nethermind/Nethermind.Core/Threading/ParallelUnbalancedWork.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,25 @@ public static void For<TLocal>(
Action<TLocal> @finally)
=> InitProcessor<TLocal>.For(fromInclusive, toExclusive, parallelOptions, init, default, action, @finally);

/// <summary>
/// Executes a parallel for loop over a range of integers, with thread-local data, initialization, and finalization functions.
/// </summary>
/// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
/// <param name="fromInclusive">The inclusive lower bound of the range.</param>
/// <param name="toExclusive">The exclusive upper bound of the range.</param>
/// <param name="parallelOptions">An object that configures the behavior of this operation.</param>
/// <param name="value">The initial the local data for each thread.</param>
/// <param name="action">The delegate that is invoked once per iteration.</param>
/// <param name="finally">The function to finalize the local data for each thread.</param>
public static void For<TLocal>(
int fromInclusive,
int toExclusive,
ParallelOptions parallelOptions,
TLocal value,
Func<int, TLocal, TLocal> action,
Action<TLocal> @finally)
=> InitProcessor<TLocal>.For(fromInclusive, toExclusive, parallelOptions, null, value, action, @finally);

/// <summary>
/// Executes a parallel for loop over a range of integers, with thread-local data.
/// </summary>
Expand Down
50 changes: 25 additions & 25 deletions src/Nethermind/Nethermind.Trie/TrieNode.Decoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,32 +176,32 @@ private static int GetChildrenRlpLengthForBranchNonRlpParallel(ITrieNodeResolver
{
int totalLength = 0;
ParallelUnbalancedWork.For(0, BranchesCount, RuntimeInformation.ParallelOptionsLogicalCores,
() => 0,
(i, local) =>
(local: 0, item, tree, bufferPool, rootPath),
static (i, state) =>
{
object? data = item._data[i];
object? data = state.item._data[i];
if (ReferenceEquals(data, _nullNode) || data is null)
{
local++;
state.local++;
}
else if (data is Hash256)
{
local += Rlp.LengthOfKeccakRlp;
state.local += Rlp.LengthOfKeccakRlp;
}
else
{
TreePath path = rootPath;
TreePath path = state.rootPath;
path.AppendMut(i);
TrieNode childNode = Unsafe.As<TrieNode>(data);
childNode.ResolveKey(tree, ref path, isRoot: false, bufferPool: bufferPool);
local += childNode.Keccak is null ? childNode.FullRlp.Length : Rlp.LengthOfKeccakRlp;
childNode.ResolveKey(state.tree, ref path, isRoot: false, bufferPool: state.bufferPool);
state.local += childNode.Keccak is null ? childNode.FullRlp.Length : Rlp.LengthOfKeccakRlp;
}
return local;
return state;
},
local =>
state =>
{
Interlocked.Add(ref totalLength, local);
Interlocked.Add(ref totalLength, state.local);
});

return totalLength;
Expand Down Expand Up @@ -237,39 +237,39 @@ private static int GetChildrenRlpLengthForBranchRlpParallel(ITrieNodeResolver tr
{
int totalLength = 0;
ParallelUnbalancedWork.For(0, BranchesCount, RuntimeInformation.ParallelOptionsLogicalCores,
() => 0,
(i, local) =>
(local: 0, item, tree, bufferPool, rootPath),
static (i, state) =>
{
ValueRlpStream rlpStream = item.RlpStream;
item.SeekChild(ref rlpStream, i);
object? data = item._data[i];
ValueRlpStream rlpStream = state.item.RlpStream;
state.item.SeekChild(ref rlpStream, i);
object? data = state.item._data[i];
if (data is null)
{
local += rlpStream.PeekNextRlpLength();
state.local += rlpStream.PeekNextRlpLength();
}
else if (ReferenceEquals(data, _nullNode))
{
local++;
state.local++;
}
else if (data is Hash256)
{
local += Rlp.LengthOfKeccakRlp;
state.local += Rlp.LengthOfKeccakRlp;
}
else
{
TreePath path = rootPath;
TreePath path = state.rootPath;
path.AppendMut(i);
Debug.Assert(data is TrieNode, "Data is not TrieNode");
TrieNode childNode = Unsafe.As<TrieNode>(data);
childNode.ResolveKey(tree, ref path, isRoot: false, bufferPool: bufferPool);
local += childNode.Keccak is null ? childNode.FullRlp.Length : Rlp.LengthOfKeccakRlp;
childNode.ResolveKey(state.tree, ref path, isRoot: false, bufferPool: state.bufferPool);
state.local += childNode.Keccak is null ? childNode.FullRlp.Length : Rlp.LengthOfKeccakRlp;
}
return local;
return state;
},
local =>
state =>
{
Interlocked.Add(ref totalLength, local);
Interlocked.Add(ref totalLength, state.local);
});

return totalLength;
Expand Down

0 comments on commit 061956a

Please sign in to comment.