-
Notifications
You must be signed in to change notification settings - Fork 5k
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
Contract leak fix #3866
Contract leak fix #3866
Conversation
Pull Request Test Coverage Report for Build 511416922
💛 - Coveralls |
@koraykoska lets take a look at this. Relevant for the refactor |
2c31aaf
to
ffb976d
Compare
Just want to let you know I am reviewing this, but I'm taking some extra care to better understand if there are any odd implications by removing the |
@jchancehud Can you explain how you discovered this was the solution? |
@GregTheGreek Sure, I initially thought the reference to So I looked at it more and realized each |
c2b67d3
to
f399b7d
Compare
@jchancehud Thanks! We're still investigating the scoping that this PR affects (inheriting some old code). Hopefully if all things are good we can get this in! |
Great, just ping me if/when it's ready and I'll do a final rebase. |
2. Test refining 3. #3866 4. Test fixing 5. Contract Updates 6. COntract Updates 7. Move functions inside for now 8. Merge files to index again. Think about remiving them later 9. Remove multiline declarations
2. Test refining 3. #3866 4. Test fixing 5. Contract Updates 6. COntract Updates 7. Move functions inside for now 8. Merge files to index again. Think about remiving them later 9. Remove multiline declarations 10. Remove Object.defines 11. Test refining 12. Revert 13. Revert Object.defines 14. Implement custom this selector 15. Test refining 16. Replace Object.defines (again)
just ran into this... this should be a top priority. initializing a lot of contracts will eat up gigbabytes |
Yea, I'd like an update on this as well. @GregTheGreek is there something specific holding this up? |
Hi everybody, this should be 1st priority to work with. |
Also running into this |
I'm experiencing huge memory leaks overtime in my dapp, probably because of this, any ETA on PR merge? |
Hello. This issue is also affecting me and causing me a lot of headaches. Why is it taking so long for this fix to be merged? |
Bump, it's been a cool 5 months on this. |
merge pls lmao |
This PR has been automatically marked as stale beacause it has not had recent activity. It will be closed in 7 days if no further activity occurs. Thank you for your contributions. If you believe this was a mistake, please comment. |
bump |
Bump |
Hi, ended up on this thread after huge memory leak in our node App, seems like it's coming from Web3's Contract setprovider... so bump ! |
Bump! |
Having this issue as well, please review! |
Really need this reviewed! Thanks |
Related with #4580 |
As explained in the #4580 (comment) this PR is introducing a breaking change to fix the the problem (which actually is a desired behavior). To update current provider for all instances of the contracts created, we have to keep reference of all objects. That is a memory leak in a sense but can't be fixed without introducing breaking changed in an expected behavior. This PR fixes the leak, but introduces breaking change in the behavior of updating current provider of all contract instances. As explained in #4580 (comment) we will look into some workaround for it in 4.x. For now would be really nice to open a PR for updating 1.x documentation by mentioning this expected behavior. |
@nazarhussain could you document (even here, in a github comment) the desired behaviour that is broken by this change? We're facing this issue and would like to find a workaround for 1.x - we are considering forking the repo or monkeypatching the code to address this temporarily while we wait for 4.x). Thank you :) |
@janeklb As of the 1.x the behavior is as follows.
To have this behavior, we have to keep the reference of all contract instances created so that when const c1 = new web3.eth.Contract([...abi], address1);
const c2 = new web3.eth.Contract([...abi], address1); If we call any of following: web3.eth.Contract.setProvider or c1.setProvider it will update the provider for both In your application if you feel there is a memory leak because of this behavior, then you must improve the logic of your initiating the contract in your code. The contract objects should not be created aggressively, rather created once on a global scope and then used else where. For the 4.x compatibility with the 1.x we kept the behavior as it is for now. After 4.x alpha released we may think of changing this behavior within a major release. |
Thanks @nazarhussain! In our case we do not call const BaseContract = require('web3-eth-contract');
module.exports = {
patchWeb3: function (web3) {
// create a very bare-bones contract class by extending BaseContract and not plugging into setProvider at all basically replacing all of
// https://github.com/ChainSafe/web3.js/blob/b32555cfeedde128c657dabbba201102f691f955/packages/web3-eth/src/index.js#L340-L363
class Contract extends BaseContract {}
// and then just update all the references as web3.eth already does
// https://github.com/ChainSafe/web3.js/blob/b32555cfeedde128c657dabbba201102f691f955/packages/web3-eth/src/index.js#L365-L377
web3.eth.Contract = Contract;
Contract.defaultAccount = web3.eth.defaultAccount;
Contract.defaultBlock = web3.eth.defaultBlock;
Contract.transactionBlockTimeout = web3.eth.transactionBlockTimeout;
Contract.transactionConfirmationBlocks = web3.eth.transactionConfirmationBlocks;
Contract.transactionPollingTimeout = web3.eth.transactionPollingTimeout;
Contract.transactionPollingInterval = web3.eth.transactionPollingInterval;
Contract.blockHeaderTimeout = web3.eth.blockHeaderTimeout;
Contract.handleRevert = web3.eth.handleRevert;
Contract._requestManager = web3.eth._requestManager;
Contract._ethAccounts = web3.eth.accounts;
Contract.currentProvider = web3.eth._requestManager.provider;
return web3;
},
}; then just call const web3 = patchWeb3(new Web3("...")); Given that we do not explicitly call |
FWIW this isn't really possible for us -- we deal with an unbound number of addresses so we can't really re-use Contracts (afaiu at least.. you can't/shouldn't update the address on a contract after it;s been created) |
@janeklb That seems good to me. I personally are not the fan of this feature, but as of policy for not making any breaking changes in 1.x we can't remove it. In 4.x I believe we can get rid of this behavior completely. User don't need to change the provider of all contracts often and if they need they should manage instances of contracts themselves the way their application architecture is. Due to 4.x compatibility with 1.x we are keeping this behavior in 4.x-alpha release, but it would be very easy to remove after 4.x release as we will have continuous cycle of introducing breaking changes to improve the wbe3.js. |
Had the same issue with memory leak. It was necessary to create many contract instances during the lifetime of the application. Few lines below helped me to solve this issue for v1.7.4: const Contract = require('web3-eth-contract')
const Web3 = require('web3')
const contractAddress = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'
const ABI = [{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]
const nodeUrl = '...'
const web3 = new Web3(nodeUrl)
Contract.setProvider(web3.currentProvider)
const contract = new Contract(ABI, contractAddress) |
Can you expand a bit on how this works? I have an express served that leverages web3 and have about 7/8 contracts created within one function. |
Description
Removes
setProvider
variable insideContract
constructor. This solves the memory leak when creating contract objects usingnew web3.eth.Contract(...)
. This fix is tested here.Fixes #3042
Type of change
Checklist:
npm run dtslint
with success and extended the tests and types if necessary.npm run test:unit
with success.npm run test:cov
and my test cases cover all the lines and branches of the added code.npm run build
and testeddist/web3.min.js
in a browser.CHANGELOG.md
file in the root folder.