Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Measure Interpreter call stack footprint #305

Closed
rakita opened this issue Dec 23, 2022 · 6 comments · Fixed by #522
Closed

Measure Interpreter call stack footprint #305

rakita opened this issue Dec 23, 2022 · 6 comments · Fixed by #522
Labels
good first issue Good for newcomers

Comments

@rakita
Copy link
Member

rakita commented Dec 23, 2022

For some tests that call multiple contracts in higher depths, revm has a overflow. It will be great to measure and quantitate where is the place that takes most data and how much does the stack rises with every call.

For info pthread_crate default is around 2-4MB. Check Notes here https://man7.org/linux/man-pages/man3/pthread_create.3.html

@rakita rakita changed the title Measure how much stack is used for calls Measure Interpreter call stack footprint Dec 23, 2022
@rakita rakita added the good first issue Good for newcomers label Dec 24, 2022
@valo
Copy link
Contributor

valo commented Jun 4, 2023

This transaction causes the revm to blow the standard stack size: https://etherscan.io/tx/0x0c10fafe0cdbfff32abfe53d57ec861d09986cc1050c850481f79b1a862bb10a

It reaches 266 levels of recursion before it blows up.

@valo
Copy link
Contributor

valo commented Jun 5, 2023

Looks like each call is consuming around 7500 bytes of stack. The way I measured this is by tracking the remaining stack using stacker::remaining_stack() in https://github.com/bluealloy/revm/blob/main/crates/revm/src/inspector/customprinter.rs#L30

After a CALL opcode there is around 7500 bytes of consumed stack.

Still not sure what is the thing that consumes that much stack. I tried to Box the Interpreter as a potential large struct, but it didn't help https://github.com/bluealloy/revm/blob/v24/crates/revm/src/evm_impl.rs#L846

Any ideas are more than welcome 🤔

@rakita
Copy link
Member Author

rakita commented Jun 6, 2023

This transaction causes the revm to blow the standard stack size: https://etherscan.io/tx/0x0c10fafe0cdbfff32abfe53d57ec861d09986cc1050c850481f79b1a862bb10a

It reaches 266 levels of recursion before it blows up.

There are even some tests that fail for SO, so it can be easier to find those tests and just call revme (with e) and do tests there, should be easier. revme can be called as cargo run --release -- statetest path_to_folder.

https://github.com/bluealloy/revm/blob/main/bins/revme/src/statetest/runner.rs#L360

edit: By this I mean you can reduce stack size in revme, run full Ethereum tests from https://github.com/ethereum/tests
with this command cargo run --release -- statetest --single-thread tests/GeneralStateTests/ tests/LegacyTests/Constantinople/GeneralStateTests/ and then just move one of problematic tests to separate folder and use it for debugging. It should be easier to run.

Looks like each call is consuming around 7500 bytes of stack. The way I measured this is by tracking the remaining stack using stacker::remaining_stack() in https://github.com/bluealloy/revm/blob/main/crates/revm/src/inspector/customprinter.rs#L30

After a CALL opcode there is around 7500 bytes of consumed stack.

Still not sure what is the thing that consumes that much stack. I tried to Box the Interpreter as a potential large struct, but it didn't help https://github.com/bluealloy/revm/blob/v24/crates/revm/src/evm_impl.rs#L846

Any ideas are more than welcome 🤔

Oh didn't know about stacker looks nice. 7.5kb per call

I would just spread the println and try to find out where it grows the most. Would focus when call/create is done.

My best bet was that Interpreted, maybe there are some other variables made inside function, or maybe it is related to function inputs as they are put to stack, but idk.

@valo
Copy link
Contributor

valo commented Jun 6, 2023

Oh didn't know about stacker looks nice. 7.5kb per call

I would just spread the println and try to find out where it grows the most. Would focus when call/create is done.

Unfortunately stacker is not that granular and doesn't update the estimation of the remaining stack as you progress inside the function. I managed to hook up lldb debugger, which allows to examine the stack frames and the variables in each frame in detail. As next steps I might try to dump the stack memory, using the stack register and try to get some info from there...

@mattsse
Copy link
Collaborator

mattsse commented Jun 7, 2023

this is another tx that resulted in an overflow

https://etherscan.io/tx/0x4135170d3cdb3c4bf7029d52134b997661b71c3b6509b672e8d77f53bd1026a7/advanced#internal

1024 zero value internal transactions

@rakita
Copy link
Member Author

rakita commented Jun 7, 2023

this is another tx that resulted in an overflow

https://etherscan.io/tx/0x4135170d3cdb3c4bf7029d52134b997661b71c3b6509b672e8d77f53bd1026a7/advanced#internal

1024 zero value internal transactions

lol, someone was live testing evm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants