Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
#### Performance
- EVM optimisations - Improves 70% of EEST benchmarks [#9775](https://github.com/hyperledger/besu/pull/9775)
- EVM optimisations - Improve SAR, SHR and SHL opcodes performance [#9796](https://github.com/hyperledger/besu/pull/9796)
- Improve DIV and SDIV performance [#9923](https://github.com/hyperledger/besu/pull/9923)

### Bug fixes
- Fix epoch reset not clearing DROP votes in Clique/IBFT/QBFT consensus [#9870](https://github.com/hyperledger/besu/pull/9870)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,119 @@
package org.hyperledger.besu.ethereum.vm.operations;

import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.operation.DivOperation;
import org.hyperledger.besu.evm.operation.DivOperationOptimized;
import org.hyperledger.besu.evm.operation.Operation;

import java.math.BigInteger;
import java.util.Random;

import org.apache.tuweni.bytes.Bytes;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Setup;

public class DivOperationBenchmark extends BinaryOperationBenchmark {

public enum Case {
DIV_32_32(1, 1),
DIV_64_32(2, 1),
DIV_64_64(2, 2),
DIV_128_32(4, 1),
DIV_128_64(4, 2),
DIV_128_128(4, 4),
DIV_192_32(6, 1),
DIV_192_64(6, 2),
DIV_192_128(6, 4),
DIV_192_192(6, 6),
DIV_256_32(8, 1),
DIV_256_64(8, 2),
DIV_256_128(8, 4),
DIV_256_192(8, 6),
DIV_256_256(8, 8),
ZERO_QUOTIENT_0_256(0, 8),
ZERO_QUOTIENT_64_256(2, 8),
ZERO_QUOTIENT_128_256(4, 8),
ZERO_QUOTIENT_192_256(6, 8),
FULL_RANDOM(-1, -1);

final int numSize;
final int denomSize;

Case(final int numSize, final int denomSize) {
this.numSize = numSize;
this.denomSize = denomSize;
}
}

@Param({
"DIV_32_32",
"DIV_64_32",
"DIV_64_64",
"DIV_128_32",
"DIV_128_64",
"DIV_128_128",
"DIV_192_32",
"DIV_192_64",
"DIV_192_128",
"DIV_192_192",
"DIV_256_32",
"DIV_256_64",
"DIV_256_128",
"DIV_256_192",
"DIV_256_256",
"ZERO_QUOTIENT_0_256",
"ZERO_QUOTIENT_64_256",
"ZERO_QUOTIENT_128_256",
"ZERO_QUOTIENT_192_256",
"FULL_RANDOM"
})
String caseName;

@Setup(Level.Iteration)
@Override
public void setUp() {
frame = BenchmarkHelper.createMessageCallFrame();

Case scenario = Case.valueOf(caseName);
aPool = new Bytes[SAMPLE_SIZE];
bPool = new Bytes[SAMPLE_SIZE];

final Random random = new Random();
int aSize;
int bSize;

for (int i = 0; i < SAMPLE_SIZE; i++) {
if (scenario.numSize < 0) aSize = random.nextInt(1, 33);
else aSize = scenario.numSize * 4;
if (scenario.denomSize < 0) bSize = random.nextInt(1, 33);
else bSize = scenario.denomSize * 4;

final byte[] a = new byte[aSize];
final byte[] b = new byte[bSize];
random.nextBytes(a);
random.nextBytes(b);

// Swap a and b if necessary
if ((scenario.numSize != scenario.denomSize)) {
aPool[i] = Bytes.wrap(a);
bPool[i] = Bytes.wrap(b);
} else {
BigInteger aInt = new BigInteger(1, a);
BigInteger bInt = new BigInteger(1, b);
if ((aInt.compareTo(bInt) < 0)) {
aPool[i] = Bytes.wrap(b);
bPool[i] = Bytes.wrap(a);
} else {
aPool[i] = Bytes.wrap(a);
bPool[i] = Bytes.wrap(b);
}
}
}
index = 0;
}

@Override
protected Operation.OperationResult invoke(final MessageFrame frame) {
return DivOperation.staticOperation(frame);
return DivOperationOptimized.staticOperation(frame);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,72 @@

import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.operation.Operation;
import org.hyperledger.besu.evm.operation.SDivOperation;
import org.hyperledger.besu.evm.operation.SDivOperationOptimized;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Random;

import org.apache.tuweni.bytes.Bytes;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Setup;

public class SDivOperationBenchmark extends DivOperationBenchmark {
Comment thread
lu-pinto marked this conversation as resolved.
Outdated

@Setup(Level.Iteration)
@Override
public void setUp() {
frame = BenchmarkHelper.createMessageCallFrame();

DivOperationBenchmark.Case scenario = DivOperationBenchmark.Case.valueOf(caseName);
aPool = new Bytes[SAMPLE_SIZE];
bPool = new Bytes[SAMPLE_SIZE];

final Random random = new Random();
int aSize;
int bSize;

for (int i = 0; i < SAMPLE_SIZE; i++) {
if (scenario.numSize < 0) aSize = random.nextInt(1, 33);
else aSize = scenario.numSize * 4;
if (scenario.denomSize < 0) bSize = random.nextInt(1, 33);
else bSize = scenario.denomSize * 4;

byte[] a = new byte[aSize];
byte[] b = new byte[bSize];
random.nextBytes(a);
random.nextBytes(b);
a = negate(a);
b = negate(b);

// Swap a and b if necessary
if ((scenario.numSize != scenario.denomSize)) {
aPool[i] = Bytes.wrap(a);
bPool[i] = Bytes.wrap(b);
} else {
BigInteger aInt = new BigInteger(a);
BigInteger bInt = new BigInteger(b);
if ((aInt.abs().compareTo(bInt.abs()) < 0)) {
aPool[i] = Bytes.wrap(b);
bPool[i] = Bytes.wrap(a);
} else {
aPool[i] = Bytes.wrap(a);
bPool[i] = Bytes.wrap(b);
}
}
}
index = 0;
}

private static byte[] negate(final byte[] array) {
byte[] tmp = new byte[32];
Arrays.fill(tmp, (byte) 0xFF);
System.arraycopy(array, 0, tmp, 32 - array.length, array.length);
return tmp;
}

public class SDivOperationBenchmark extends BinaryOperationBenchmark {
@Override
protected Operation.OperationResult invoke(final MessageFrame frame) {
return SDivOperation.staticOperation(frame);
return SDivOperationOptimized.staticOperation(frame);
}
}
12 changes: 10 additions & 2 deletions evm/src/main/java/org/hyperledger/besu/evm/EVM.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.hyperledger.besu.evm.operation.ChainIdOperation;
import org.hyperledger.besu.evm.operation.CountLeadingZerosOperation;
import org.hyperledger.besu.evm.operation.DivOperation;
import org.hyperledger.besu.evm.operation.DivOperationOptimized;
import org.hyperledger.besu.evm.operation.DupNOperation;
import org.hyperledger.besu.evm.operation.DupOperation;
import org.hyperledger.besu.evm.operation.ExchangeOperation;
Expand Down Expand Up @@ -64,6 +65,7 @@
import org.hyperledger.besu.evm.operation.Push0Operation;
import org.hyperledger.besu.evm.operation.PushOperation;
import org.hyperledger.besu.evm.operation.SDivOperation;
import org.hyperledger.besu.evm.operation.SDivOperationOptimized;
import org.hyperledger.besu.evm.operation.SGtOperation;
import org.hyperledger.besu.evm.operation.SLtOperation;
import org.hyperledger.besu.evm.operation.SModOperation;
Expand Down Expand Up @@ -246,8 +248,14 @@ public void runToHalt(final MessageFrame frame, final OperationTracer tracing) {
: AddOperation.staticOperation(frame);
case 0x02 -> MulOperation.staticOperation(frame);
case 0x03 -> SubOperation.staticOperation(frame);
case 0x04 -> DivOperation.staticOperation(frame);
case 0x05 -> SDivOperation.staticOperation(frame);
case 0x04 ->
evmConfiguration.enableOptimizedOpcodes()
? DivOperationOptimized.staticOperation(frame)
: DivOperation.staticOperation(frame);
case 0x05 ->
evmConfiguration.enableOptimizedOpcodes()
? SDivOperationOptimized.staticOperation(frame)
: SDivOperation.staticOperation(frame);
case 0x06 ->
evmConfiguration.enableOptimizedOpcodes()
? ModOperationOptimized.staticOperation(frame)
Expand Down
8 changes: 6 additions & 2 deletions evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import org.hyperledger.besu.evm.operation.DelegateCallOperation;
import org.hyperledger.besu.evm.operation.DifficultyOperation;
import org.hyperledger.besu.evm.operation.DivOperation;
import org.hyperledger.besu.evm.operation.DivOperationOptimized;
import org.hyperledger.besu.evm.operation.DupNOperation;
import org.hyperledger.besu.evm.operation.DupOperation;
import org.hyperledger.besu.evm.operation.EqOperation;
Expand Down Expand Up @@ -109,6 +110,7 @@
import org.hyperledger.besu.evm.operation.ReturnOperation;
import org.hyperledger.besu.evm.operation.RevertOperation;
import org.hyperledger.besu.evm.operation.SDivOperation;
import org.hyperledger.besu.evm.operation.SDivOperationOptimized;
import org.hyperledger.besu.evm.operation.SGtOperation;
import org.hyperledger.besu.evm.operation.SLoadOperation;
import org.hyperledger.besu.evm.operation.SLtOperation;
Expand Down Expand Up @@ -205,8 +207,6 @@ private static void registerFrontierOperations(
}
registry.put(new MulOperation(gasCalculator));
registry.put(new SubOperation(gasCalculator));
registry.put(new DivOperation(gasCalculator));
registry.put(new SDivOperation(gasCalculator));
if (evmConfiguration.enableOptimizedOpcodes()) {
registry.put(new AddOperationOptimized(gasCalculator));
registry.put(new ModOperationOptimized(gasCalculator));
Expand All @@ -217,6 +217,8 @@ private static void registerFrontierOperations(
registry.put(new XorOperationOptimized(gasCalculator));
registry.put(new OrOperationOptimized(gasCalculator));
registry.put(new NotOperationOptimized(gasCalculator));
registry.put(new DivOperationOptimized(gasCalculator));
registry.put(new SDivOperationOptimized(gasCalculator));
} else {
registry.put(new AddOperation(gasCalculator));
registry.put(new ModOperation(gasCalculator));
Expand All @@ -227,6 +229,8 @@ private static void registerFrontierOperations(
registry.put(new XorOperation(gasCalculator));
registry.put(new OrOperation(gasCalculator));
registry.put(new NotOperation(gasCalculator));
registry.put(new DivOperation(gasCalculator));
registry.put(new SDivOperation(gasCalculator));
}
registry.put(new ExpOperation(gasCalculator));
registry.put(new SignExtendOperation(gasCalculator));
Expand Down
Loading