dapphub / dapptools

Dapp, Seth, Hevm, and more
https://dapp.tools
2.09k stars 323 forks source link

investigate hevm memory usage / performance #395

Open MrChico opened 4 years ago

MrChico commented 4 years ago

recently, a couple of memory intensive tests started failing on ci with error message:

Return50000_d0g1v0_Istanbul hevm: internal error: Unable to commit 1048576 bytes of memory

although the error message reports this as a ghc bug, people suggest this is rarely the case. Granted, these are pretty extreme test cases, but would still be interesting to see if there are any easy ways to tackle the memory footprint

d-xo commented 4 years ago

I ran the Return5000 tests with profiling enabled (cabal new-run hevm -- compliance --tests ~/code/github.com/ethereum/tests/ --timeout 999999999 --match Return50000 +RTS -p) and got the following trace: https://ipfs.io/ipfs/QmeLEYpgYahNMxaxtDz74z5FPzrS1w358Y2evjUkXoKNcs/hevm.prof

It looks like a lot (~40%) of the allocation is happening in <!> from Options.Applicative.Internal

MrChico commented 4 years ago

hmmm, I wonder how to interpret that... hevm compliance is kinda weird because it invokes hevm bc-test through a bash script we might get better results if the logic of the run-blockchain tests was just done in hevm directly. It would also be pretty straightforward to run the tests in parallell then as well

d-xo commented 4 years ago

Maybe it’s better to just profile hevm bc-test directly?

MrChico commented 4 years ago

probably. Unless the culprit is actually the launchscript oddity

d-xo commented 4 years ago

results of running cabal new-run hevm -- bc-test --file ~/code/github.com/ethereum/tests/BlockchainTests/GeneralStateTests/stQuadraticComplexityTest/Return50000.json --timeout 99999999 +RTS -p:

https://ipfs.io/ipfs/QmcMTQ6jEHk65xnGFHVvxxjCgtvwSxPaFDmRatn1D8hkCP/hevm.prof

This time we're getting 40% of the alloc from byteStringSliceWithDefaultZeroes in Concrete.hs

MrChico commented 4 years ago

wowow

MrChico commented 4 years ago

maybe https://stackoverflow.com/questions/18350177/why-creating-and-disposing-temporal-bytestrings-eats-up-my-memory-in-haskell

MrChico commented 4 years ago

something should be strict that isn't here

d-xo commented 4 years ago

So I made byteStringSliceWithDefaultZeroes as strict as I know how (see here), and the memory usage didn't seem to change anything (profiling output here).

Not really sure how to proceed.

MrChico commented 4 years ago

some useful benchmarking scripts can be found at https://github.com/MrChico/evmbench/

rainbreak commented 4 years ago

Last year I considered changing the memory stuff to work with LazyByteString, which could help here (?), but it seemed like a lot of work.

MrChico commented 4 years ago

Another thing that might help with performance in general is to experiment with {-## Inline f -##}. This seems like it can be quite effective, especially when inlining causes specialization of functions. Also note that we only started compiling hevm with O2 optimization as of https://github.com/dapphub/dapptools/pull/460

MrChico commented 3 years ago

another thing that can be done here is to unify mkCodeOps and mkOpIx