trufflesuite / ganache

:warning: The Truffle Suite is being sunset. For information on ongoing support, migration options and FAQs, visit the Consensys blog. Thank you for all the support over the years.
https://consensys.io/blog/consensys-announces-the-sunset-of-truffle-and-ganache-and-new-hardhat?utm_source=github&utm_medium=referral&utm_campaign=2023_Sep_truffle-sunset-2023_announcement_
MIT License
2.62k stars 683 forks source link

Quadratic processing time for array responses #935

Open domohawk opened 3 years ago

domohawk commented 3 years ago

Consider the following contract:

contract Test {
  uint32 constant SIZE = // size here
  uint256[SIZE] private array;
  function get() external view returns (uint256[SIZE] memory) {
    return array;
  }
}

When SIZE is > ~1000 elements, the time spent waiting for a response to a web3 call() to get() starts to grow in a super-linear fashion.

NumElements: Time

1000: 1.0s 2000: 2.9s 3000: 5.6s 4000: 9.2s 5000: 13.9s 6000: 19.4s 7000: 25.9s

I've tested this both with the truffle web3js client as well as the rust-web3 client, both against ganache-cli and truffle develop and I see the same behavior. ganache-cli vs truffle develop have nearly the same response times, which makes leads me to believe there is some super-linear processing in ganache-core.

The cpu is spiked to 100% on a single core during the processing time.

fainashalts commented 3 years ago

Hi @domohawk we're not sure if this is due to a limitation of the vm in general or something with geth as well. This could be a problem with @ethereumjs/vm.

Can you try this with the Ganache canary release to see if the issue persists? You'll need to do the following:

npm uninstall ganache-cli -g && npm install ganache@canary -g

In the meantime we'll try to dig into this on our end. Thanks!

domohawk commented 3 years ago

Thanks for the quick response. I tried out ganache@canary, and while the times are much better they are still growing super-linearly, and it's not really feasible to write tests for arrays larger than a few thousand elements:

ganache@canary NumElements Time
1 0.017s
1000 0.9s
5000 4.6s
25k 40s
50k 114s
100k 388s

It seems like the websocket support in canary currently experimental? Both rust-web3 and truffle web3js cause ganache-cli to crash when initiating the connection with TypeError: r.unmask is not a function

davidmurdoch commented 3 years ago

@domohawk interesting. My hunch is that this is an issue with @ethereum/vm, but i'll have to dig in a bit more.

As for the websocket support... are you on a mac M1 by any chance?

domohawk commented 3 years ago

@davidmurdoch Nope, I'm running arch linux on Intel. If websockets is expected to work in canary I can file a different bug with the stack trace if that's helpful.

davidmurdoch commented 3 years ago

@domohawk which version of node?

domohawk commented 3 years ago

@davidmurdoch node v16.6.1

davidmurdoch commented 3 years ago

@domohawk Ah ok, can you try websockets on v14?

domohawk commented 3 years ago

@davidmurdoch So using node v14 improves the times more, but still same growth behavior. Both websockets and http have the same times.

ganache@canary, node v14.17.5 (both websockets & http) NumElements Time
1 0.015s
1000 0.8s
5000 4.0s
25k 25s
50k 68s
100k 251s
domohawk commented 3 years ago

I can confirm that geth does not seem to have this growth behavior, it seems to grow pretty linearly.

geth 1.10.6-stable, (both websockets & http) NumElements Time
1000 0.006s
5000 0.023s
25k 0.1s
50k 0.2s
100k 0.43s
500k 2.3s
1M 4.7s