Skip to content

Commit c489a91

Browse files
refactor: remove benchmark manager feature
1 parent db65fbe commit c489a91

File tree

4 files changed

+28
-170
lines changed

4 files changed

+28
-170
lines changed

src/ethereum_test_specs/benchmark.py

Lines changed: 3 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,11 @@
11
"""Ethereum benchmark test spec definition and filler."""
22

33
from abc import ABC, abstractmethod
4-
from contextlib import contextmanager
5-
from contextvars import ContextVar
64
from dataclasses import dataclass, field
7-
from enum import Enum
8-
from typing import Any, Callable, ClassVar, Dict, Generator, List, Optional, Sequence, Type
5+
from typing import Callable, ClassVar, Dict, Generator, List, Sequence, Type
96

107
import pytest
11-
from pydantic import ConfigDict, Field, GetCoreSchemaHandler
12-
from pydantic_core.core_schema import (
13-
PlainValidatorFunctionSchema,
14-
no_info_plain_validator_function,
15-
to_string_ser_schema,
16-
)
8+
from pydantic import ConfigDict, Field
179

1810
from ethereum_clis import TransitionTool
1911
from ethereum_test_base_types import HexNumber
@@ -83,88 +75,6 @@ def _validate_code_size(self, code: Bytecode, fork: Fork) -> None:
8375
)
8476

8577

86-
class BenchmarkPhase(Enum):
87-
"""Phases of a benchmark test."""
88-
89-
SETUP = "setup"
90-
EXECUTION = "execution"
91-
92-
93-
_current_phase: ContextVar[Optional[BenchmarkPhase]] = ContextVar("benchmark_phase", default=None)
94-
95-
96-
class BenchmarkManager:
97-
"""Context manager for managing benchmark test phases."""
98-
99-
def __init__(self):
100-
"""Initialize the BenchmarkManager with empty transaction and block lists."""
101-
self.setup_transactions: List[Transaction] = []
102-
self.setup_blocks: List[Block] = []
103-
self.execution_transactions: List[Transaction] = []
104-
self.execution_blocks: List[Block] = []
105-
106-
@contextmanager
107-
def setup(self):
108-
"""Context manager for the setup phase of a benchmark test."""
109-
token = _current_phase.set(BenchmarkPhase.SETUP)
110-
try:
111-
yield self
112-
finally:
113-
_current_phase.reset(token)
114-
115-
@contextmanager
116-
def execution(self):
117-
"""Context manager for the execution phase of a benchmark test."""
118-
token = _current_phase.set(BenchmarkPhase.EXECUTION)
119-
try:
120-
yield self
121-
finally:
122-
_current_phase.reset(token)
123-
124-
def add_transaction(self, tx: Transaction):
125-
"""Add a transaction to the current phase."""
126-
current_phase = _current_phase.get()
127-
if current_phase == BenchmarkPhase.SETUP:
128-
self.setup_transactions.append(tx)
129-
elif current_phase == BenchmarkPhase.EXECUTION:
130-
self.execution_transactions.append(tx)
131-
else:
132-
self.setup_transactions.append(tx)
133-
134-
def add_block(self, block: Block):
135-
"""Add a block to the current phase."""
136-
current_phase = _current_phase.get()
137-
if current_phase == BenchmarkPhase.SETUP:
138-
self.setup_blocks.append(block)
139-
elif current_phase == BenchmarkPhase.EXECUTION:
140-
self.execution_blocks.append(block)
141-
else:
142-
self.setup_blocks.append(block)
143-
144-
def get_current_phase(self) -> Optional[BenchmarkPhase]:
145-
"""Get the current benchmark phase."""
146-
return _current_phase.get()
147-
148-
@classmethod
149-
def __get_pydantic_core_schema__(
150-
cls, source_type: Any, handler: GetCoreSchemaHandler
151-
) -> PlainValidatorFunctionSchema:
152-
"""Provide Pydantic core schema for BenchmarkManager serialization and validation."""
153-
154-
def validate_benchmark_manager(value):
155-
if isinstance(value, cls):
156-
return value
157-
if value is None:
158-
return None
159-
# If value is passed as arguments, create new instance with no args
160-
return cls()
161-
162-
return no_info_plain_validator_function(
163-
validate_benchmark_manager,
164-
serialization=to_string_ser_schema(),
165-
)
166-
167-
16878
class BenchmarkTest(BaseTest):
16979
"""Test type designed specifically for benchmark test cases."""
17080

@@ -180,7 +90,6 @@ class BenchmarkTest(BaseTest):
18090
env: Environment = Field(default_factory=Environment)
18191
expected_benchmark_gas_used: int | None = None
18292
gas_benchmark_value: int = Field(default_factory=lambda: int(Environment().gas_limit))
183-
benchmark_manager: BenchmarkManager | None = None
18493
code_generator: BenchmarkCodeGenerator | None = None
18594

18695
supported_fixture_formats: ClassVar[Sequence[FixtureFormat | LabeledFixtureFormat]] = [
@@ -274,33 +183,6 @@ def generate_blockchain_test(self, fork: Fork) -> BlockchainTest:
274183
blocks=generated_blocks,
275184
)
276185

277-
elif self.benchmark_manager is not None:
278-
all_blocks = []
279-
gas_limit = fork.transaction_gas_limit_cap() or self.gas_benchmark_value
280-
281-
if self.benchmark_manager.setup_blocks:
282-
all_blocks.extend(self.benchmark_manager.setup_blocks)
283-
elif self.benchmark_manager.setup_transactions:
284-
setup_txs = []
285-
for tx in self.benchmark_manager.setup_transactions:
286-
setup_txs.extend(self.split_transaction(tx, gas_limit))
287-
all_blocks.append(Block(txs=setup_txs))
288-
289-
if self.benchmark_manager.execution_blocks:
290-
all_blocks.extend(self.benchmark_manager.execution_blocks)
291-
elif self.benchmark_manager.execution_transactions:
292-
execution_txs = []
293-
for tx in self.benchmark_manager.execution_transactions:
294-
execution_txs.extend(self.split_transaction(tx, gas_limit))
295-
all_blocks.append(Block(txs=execution_txs))
296-
297-
return BlockchainTest.from_test(
298-
base_test=self,
299-
genesis_environment=self.env,
300-
pre=self.pre,
301-
post=self.post,
302-
blocks=all_blocks,
303-
)
304186
elif self.blocks is not None:
305187
return BlockchainTest.from_test(
306188
base_test=self,
@@ -324,9 +206,7 @@ def generate_blockchain_test(self, fork: Fork) -> BlockchainTest:
324206
genesis_environment=self.env,
325207
)
326208
else:
327-
raise ValueError(
328-
"Cannot create BlockchainTest without transactions, blocks, or benchmark_manager"
329-
)
209+
raise ValueError("Cannot create BlockchainTest without transactions or blocks")
330210

331211
def generate(
332212
self,
@@ -358,10 +238,5 @@ def execute(
358238
raise Exception(f"Unsupported execute format: {execute_format}")
359239

360240

361-
def create_benchmark_manager() -> BenchmarkManager:
362-
"""Create a new BenchmarkManager instance for phase-aware benchmark testing."""
363-
return BenchmarkManager()
364-
365-
366241
BenchmarkTestSpec = Callable[[str], Generator[BenchmarkTest, None, None]]
367242
BenchmarkTestFiller = Type[BenchmarkTest]

tests/benchmark/conftest.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import pytest
66

77
from ethereum_test_forks import Fork
8-
from ethereum_test_specs.benchmark import BenchmarkManager, create_benchmark_manager
98

109
DEFAULT_BENCHMARK_FORK = "Prague"
1110

@@ -68,9 +67,3 @@ def pytest_collection_modifyitems(config, items):
6867
def tx_gas_limit_cap(fork: Fork, gas_benchmark_value: int) -> int:
6968
"""Return the transaction gas limit cap."""
7069
return fork.transaction_gas_limit_cap() or gas_benchmark_value
71-
72-
73-
@pytest.fixture
74-
def benchmark_manager() -> BenchmarkManager:
75-
"""Return a benchmark manager."""
76-
return create_benchmark_manager()

tests/benchmark/test_worst_blocks.py

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@
99

1010
import pytest
1111

12+
from ethereum_test_base_types import Account
1213
from ethereum_test_forks import Fork
13-
from ethereum_test_specs.benchmark import BenchmarkManager
1414
from ethereum_test_tools import (
1515
AccessList,
16-
Account,
1716
Address,
1817
Alloc,
19-
BenchmarkTestFiller,
2018
Block,
19+
BlockchainTestFiller,
2120
Environment,
2221
Hash,
2322
StateTestFiller,
@@ -112,8 +111,7 @@ def ether_transfer_case(
112111
["a_to_a", "a_to_b", "diff_acc_to_b", "a_to_diff_acc", "diff_acc_to_diff_acc"],
113112
)
114113
def test_block_full_of_ether_transfers(
115-
benchmark_test: BenchmarkTestFiller,
116-
benchmark_manager: BenchmarkManager,
114+
blockchain_test: BlockchainTestFiller,
117115
pre: Alloc,
118116
env: Environment,
119117
case_id: str,
@@ -138,18 +136,17 @@ def test_block_full_of_ether_transfers(
138136
# Create a single block with all transactions
139137
txs = []
140138
balances: dict[Address, int] = {}
141-
with benchmark_manager.execution():
142-
for _ in range(iteration_count):
143-
receiver = next(receivers)
144-
balances[receiver] = balances.get(receiver, 0) + transfer_amount
145-
txs.append(
146-
Transaction(
147-
to=receiver,
148-
value=transfer_amount,
149-
gas_limit=intrinsic_cost,
150-
sender=next(senders),
151-
)
139+
for _ in range(iteration_count):
140+
receiver = next(receivers)
141+
balances[receiver] = balances.get(receiver, 0) + transfer_amount
142+
txs.append(
143+
Transaction(
144+
to=receiver,
145+
value=transfer_amount,
146+
gas_limit=intrinsic_cost,
147+
sender=next(senders),
152148
)
149+
)
153150

154151
# Only include post state for non a_to_a cases
155152
post_state = (
@@ -158,8 +155,8 @@ def test_block_full_of_ether_transfers(
158155
else {receiver: Account(balance=balance) for receiver, balance in balances.items()}
159156
)
160157

161-
benchmark_test(
162-
env=env,
158+
blockchain_test(
159+
genesis_environment=env,
163160
pre=pre,
164161
post=post_state,
165162
blocks=[Block(txs=txs)],

tests/benchmark/test_worst_stateful_opcodes.py

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
import pytest
1111

1212
from ethereum_test_forks import Fork
13-
from ethereum_test_specs import BenchmarkTestFiller
14-
from ethereum_test_specs.benchmark import BenchmarkManager
1513
from ethereum_test_tools import (
1614
Account,
1715
Address,
@@ -453,35 +451,30 @@ def test_worst_storage_access_warm(
453451

454452

455453
def test_worst_blockhash(
456-
benchmark_test: BenchmarkTestFiller,
457-
benchmark_manager: BenchmarkManager,
454+
blockchain_test: BlockchainTestFiller,
458455
pre: Alloc,
459456
gas_benchmark_value: int,
460457
):
461458
"""Test running a block with as many blockhash accessing oldest allowed block as possible."""
462459
# Create 256 dummy blocks to fill the blockhash window.
463-
with benchmark_manager.setup():
464-
for _ in range(256):
465-
benchmark_manager.add_block(Block())
460+
blocks = [Block()] * 256
466461

467462
# Always ask for the oldest allowed BLOCKHASH block.
468463
execution_code = Op.PUSH1(1) + While(
469464
body=Op.POP(Op.BLOCKHASH(Op.DUP1)),
470465
)
471466
execution_code_address = pre.deploy_contract(code=execution_code)
472-
with benchmark_manager.execution():
473-
benchmark_manager.add_transaction(
474-
Transaction(
475-
to=execution_code_address,
476-
gas_limit=gas_benchmark_value,
477-
sender=pre.fund_eoa(),
478-
)
479-
)
467+
op_tx = Transaction(
468+
to=execution_code_address,
469+
gas_limit=gas_benchmark_value,
470+
sender=pre.fund_eoa(),
471+
)
472+
blocks.append(Block(txs=[op_tx]))
480473

481-
benchmark_test(
474+
blockchain_test(
482475
pre=pre,
483476
post={},
484-
benchmark_manager=benchmark_manager,
477+
blocks=blocks,
485478
)
486479

487480

0 commit comments

Comments
 (0)