Skip to content

Commit 0a3ac38

Browse files
committed
Reduce memory usage of tests
- eth/vm/memory.py:Memory.read() used to return a bytes() initialized with the requested memory, this created an often unnecessary copy of the data. It now returns a memoryview(), which is a python wrapper around a pointer to the raw data.
1 parent 90dc15d commit 0a3ac38

File tree

16 files changed

+84
-29
lines changed

16 files changed

+84
-29
lines changed

eth/precompiles/ecadd.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def ecadd(computation: BaseComputation) -> BaseComputation:
3232
computation.consume_gas(constants.GAS_ECADD, reason='ECADD Precompile')
3333

3434
try:
35-
result = _ecadd(computation.msg.data)
35+
result = _ecadd(computation.msg.data_as_bytes)
3636
except ValidationError:
3737
raise VMError("Invalid ECADD parameters")
3838

eth/precompiles/ecmul.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def ecmul(computation: BaseComputation) -> BaseComputation:
3232
computation.consume_gas(constants.GAS_ECMUL, reason='ECMUL Precompile')
3333

3434
try:
35-
result = _ecmull(computation.msg.data)
35+
result = _ecmull(computation.msg.data_as_bytes)
3636
except ValidationError:
3737
raise VMError("Invalid ECMUL parameters")
3838

eth/precompiles/ecpairing.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
VMError,
2020
)
2121

22+
from eth.typing import (
23+
BytesOrView,
24+
)
25+
2226
from eth.utils.bn128 import (
2327
validate_point,
2428
FQP_point_to_FQ2_point,
@@ -60,7 +64,7 @@ def ecpairing(computation: BaseComputation) -> BaseComputation:
6064
return computation
6165

6266

63-
def _ecpairing(data: bytes) -> bool:
67+
def _ecpairing(data: BytesOrView) -> bool:
6468
exponent = bn128.FQ12.one()
6569

6670
processing_pipeline = (

eth/precompiles/ecrecover.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,17 @@
2727

2828
def ecrecover(computation: BaseComputation) -> BaseComputation:
2929
computation.consume_gas(constants.GAS_ECRECOVER, reason="ECRecover Precompile")
30-
raw_message_hash = computation.msg.data[:32]
30+
data = computation.msg.data_as_bytes
31+
raw_message_hash = data[:32]
3132
message_hash = pad32r(raw_message_hash)
3233

33-
v_bytes = pad32r(computation.msg.data[32:64])
34+
v_bytes = pad32r(data[32:64])
3435
v = big_endian_to_int(v_bytes)
3536

36-
r_bytes = pad32r(computation.msg.data[64:96])
37+
r_bytes = pad32r(data[64:96])
3738
r = big_endian_to_int(r_bytes)
3839

39-
s_bytes = pad32r(computation.msg.data[96:128])
40+
s_bytes = pad32r(data[96:128])
4041
s = big_endian_to_int(s_bytes)
4142

4243
try:

eth/precompiles/identity.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ def identity(computation: BaseComputation) -> BaseComputation:
1414

1515
computation.consume_gas(gas_fee, reason="Identity Precompile")
1616

17-
computation.output = computation.msg.data
17+
computation.output = computation.msg.data_as_bytes
1818
return computation

eth/precompiles/modexp.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,14 @@ def modexp(computation: BaseComputation) -> BaseComputation:
125125
"""
126126
https://github.com/ethereum/EIPs/pull/198
127127
"""
128-
gas_fee = _compute_modexp_gas_fee(computation.msg.data)
128+
data = computation.msg.data_as_bytes
129+
130+
gas_fee = _compute_modexp_gas_fee(data)
129131
computation.consume_gas(gas_fee, reason='MODEXP Precompile')
130132

131-
result = _modexp(computation.msg.data)
133+
result = _modexp(data)
132134

133-
_, _, modulus_length = _extract_lengths(computation.msg.data)
135+
_, _, modulus_length = _extract_lengths(data)
134136

135137
# Modulo 0 is undefined, return zero
136138
# https://math.stackexchange.com/questions/516251/why-is-n-mod-0-undefined

eth/typing.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757

5858
GenesisDict = Dict[str, Union[int, BlockNumber, bytes, Hash32]]
5959

60+
BytesOrView = Union[bytes, memoryview]
61+
6062
Normalizer = Callable[[Dict[Any, Any]], Dict[str, Any]]
6163

6264
RawAccountDetails = TypedDict('RawAccountDetails',

eth/validation.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
UINT_256_MAX,
4141
)
4242

43+
from eth.typing import (
44+
BytesOrView,
45+
)
46+
4347
if TYPE_CHECKING:
4448
from eth.vm.base import BaseVM # noqa: F401
4549

@@ -51,6 +55,14 @@ def validate_is_bytes(value: bytes, title: str="Value") -> None:
5155
)
5256

5357

58+
def validate_is_bytes_or_view(value: BytesOrView, title: str="Value") -> None:
59+
if isinstance(value, (bytes, memoryview)):
60+
return
61+
raise ValidationError(
62+
"{title} must be bytes or memoryview. Got {0}".format(type(value), title=title)
63+
)
64+
65+
5466
def validate_is_integer(value: Union[int, bool], title: str="Value") -> None:
5567
if not isinstance(value, int) or isinstance(value, bool):
5668
raise ValidationError(

eth/vm/computation.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
Halt,
3030
VMError,
3131
)
32+
from eth.typing import (
33+
BytesOrView,
34+
)
3235
from eth.tools.logging import (
3336
ExtendedDebugLogger,
3437
)
@@ -243,12 +246,18 @@ def memory_write(self, start_position: int, size: int, value: bytes) -> None:
243246
"""
244247
return self._memory.write(start_position, size, value)
245248

246-
def memory_read(self, start_position: int, size: int) -> bytes:
249+
def memory_read(self, start_position: int, size: int) -> memoryview:
247250
"""
248-
Read and return ``size`` bytes from memory starting at ``start_position``.
251+
Read and return a view of ``size`` bytes from memory starting at ``start_position``.
249252
"""
250253
return self._memory.read(start_position, size)
251254

255+
def memory_read_bytes(self, start_position: int, size: int) -> bytes:
256+
"""
257+
Read and return ``size`` bytes from memory starting at ``start_position``.
258+
"""
259+
return self._memory.read_bytes(start_position, size)
260+
252261
#
253262
# Gas Consumption
254263
#
@@ -360,7 +369,7 @@ def prepare_child_message(self,
360369
gas: int,
361370
to: Address,
362371
value: int,
363-
data: bytes,
372+
data: BytesOrView,
364373
code: bytes,
365374
**kwargs: Any) -> Message:
366375
"""

eth/vm/logic/context.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def calldataload(computation: BaseComputation) -> None:
4242
"""
4343
start_position = computation.stack_pop(type_hint=constants.UINT256)
4444

45-
value = computation.msg.data[start_position:start_position + 32]
45+
value = computation.msg.data_as_bytes[start_position:start_position + 32]
4646
padded_value = value.ljust(32, b'\x00')
4747
normalized_value = padded_value.lstrip(b'\x00')
4848

@@ -68,7 +68,9 @@ def calldatacopy(computation: BaseComputation) -> None:
6868

6969
computation.consume_gas(copy_gas_cost, reason="CALLDATACOPY fee")
7070

71-
value = computation.msg.data[calldata_start_position: calldata_start_position + size]
71+
value = computation.msg.data_as_bytes[
72+
calldata_start_position: calldata_start_position + size
73+
]
7274
padded_value = value.ljust(size, b'\x00')
7375

7476
computation.memory_write(mem_start_position, size, padded_value)

0 commit comments

Comments
 (0)