From 87bf51e08d1004620b674cf7af8abea257ffe87a Mon Sep 17 00:00:00 2001 From: Ameziane H Date: Tue, 3 Jan 2023 09:28:22 +0100 Subject: [PATCH 1/4] Cache empty slots. Signed-off-by: Ameziane H --- .../bonsai/BonsaiWorldStateUpdater.java | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java index 1eb307adb7e..ec6ce428a57 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java @@ -52,6 +52,7 @@ public class BonsaiWorldStateUpdater extends AbstractWorldUpdater storagePreloader; private final Map> codeToUpdate = new ConcurrentHashMap<>(); private final Set
storageToClear = Collections.synchronizedSet(new HashSet<>()); + private final Set emptySlot = Collections.synchronizedSet(new HashSet<>()); // storage sub mapped by _hashed_ key. This is because in self_destruct calls we need to // enumerate the old storage and delete it. Those are trie stored by hashed key by spec and the @@ -349,18 +350,26 @@ public Optional getStorageValueBySlotHash(final Address address, final return Optional.ofNullable(value.getUpdated()); } } - final Optional valueUInt = - wrappedWorldView().getStorageValueBySlotHash(address, slotHash); - valueUInt.ifPresent( - v -> - storageToUpdate - .computeIfAbsent( - address, - key -> - new StorageConsumingMap<>( - address, new ConcurrentHashMap<>(), storagePreloader)) - .put(slotHash, new BonsaiValue<>(v, v))); - return valueUInt; + final Bytes slot = Bytes.concatenate(Hash.hash(address), slotHash); + if (emptySlot.contains(slot)) { + return Optional.empty(); + } else { + final Optional valueUInt = + wrappedWorldView().getStorageValueBySlotHash(address, slotHash); + valueUInt.ifPresentOrElse( + v -> + storageToUpdate + .computeIfAbsent( + address, + key -> + new StorageConsumingMap<>( + address, new ConcurrentHashMap<>(), storagePreloader)) + .put(slotHash, new BonsaiValue<>(v, v)), + () -> { + emptySlot.add(Bytes.concatenate(Hash.hash(address), slotHash)); + }); + return valueUInt; + } } @Override From 7a89e5103a6664fc33efa9b3ee52c43053ec848f Mon Sep 17 00:00:00 2001 From: Karim TAAM Date: Tue, 3 Jan 2023 14:50:14 +0100 Subject: [PATCH 2/4] clear after each block and copy during clone Signed-off-by: Karim TAAM --- .../besu/ethereum/bonsai/BonsaiWorldStateUpdater.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java index ec6ce428a57..435f7dc155e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java @@ -88,6 +88,7 @@ void cloneFromUpdater(final BonsaiWorldStateUpdater source) { storageToUpdate.putAll(source.storageToUpdate); updatedAccounts.putAll(source.updatedAccounts); deletedAccounts.addAll(source.deletedAccounts); + emptySlot.addAll(source.emptySlot); } @Override @@ -714,6 +715,7 @@ public void reset() { storageToUpdate.clear(); codeToUpdate.clear(); accountsToUpdate.clear(); + emptySlot.clear(); super.reset(); } @@ -723,7 +725,8 @@ public boolean isDirty() { && deletedAccounts.isEmpty() && storageToUpdate.isEmpty() && storageToClear.isEmpty() - && codeToUpdate.isEmpty()); + && codeToUpdate.isEmpty() + && emptySlot.isEmpty()); } public static class AccountConsumingMap extends ForwardingMap { From 541345e4f625ed406245ec006a987291d05a2bbe Mon Sep 17 00:00:00 2001 From: Ameziane H Date: Fri, 6 Jan 2023 10:53:09 +0100 Subject: [PATCH 3/4] add changelog Signed-off-by: Ameziane H --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ac50c5034b..d4858010cb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Default configurations for the deprecated Ropsten, Kiln, Shandong, and Astor networks have been removed from the CLI network list. These networks can currently be accessed but will require a user-provided genesis configuration. [#4896](https://github.com/hyperledger/besu/pull/4869) ### Additions and Improvements +- Improve SLOAD and SSTORE performance by caching empty slots [#4874](https://github.com/hyperledger/besu/pull/4874) ### Bug Fixes From 494e274acdf59894788390099e66980be8d05015 Mon Sep 17 00:00:00 2001 From: Ameziane H Date: Mon, 9 Jan 2023 10:09:48 +0100 Subject: [PATCH 4/4] Avoid triggering a calculate root hash when empty slot cache is not empty. Signed-off-by: Ameziane H --- .../besu/ethereum/bonsai/BonsaiWorldStateUpdater.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java index 435f7dc155e..fd71e6a856e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateUpdater.java @@ -725,8 +725,7 @@ public boolean isDirty() { && deletedAccounts.isEmpty() && storageToUpdate.isEmpty() && storageToClear.isEmpty() - && codeToUpdate.isEmpty() - && emptySlot.isEmpty()); + && codeToUpdate.isEmpty()); } public static class AccountConsumingMap extends ForwardingMap {