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
Maintain Gas Estimation Metrics #594
Conversation
c9313a7
to
e997104
Compare
Do you think it's useful to add this script as a build to our CI workflow as its own job? One benefit of this is that It will introduce an automation step for this script, preventing it from growing stale with future development. |
It will help to keep up-to-date this script, so I like idea with CI |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! 🐧
tests/metrics/estimate_gas_tester.py
Outdated
providers=(pyevm_provider,)) # use custom test provider | ||
solidity_compiler = SolidityCompiler(test_contract_dir=CONTRACTS_DIR) | ||
memory_registry = InMemoryEthereumContractRegistry() | ||
circumflex = BlockchainDeployerInterface(provider_uri="tester://pyevm", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
circumflex circumflexing
tests/metrics/estimate_gas_tester.py
Outdated
def __call__(self, event, *args, **kwargs): | ||
if event.get('log_namespace') == LOG_NAME: | ||
message = event.get("log_format") | ||
if not re.match(r'.*\s=\s\d+$', message): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice
51a6b35
to
1657c4c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐧
53e67f2
to
bf62f92
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work!
My main comment is that I think there's room for improvement re: code verbosity and repeated patterns.
tests/metrics/estimate_gas_tester.py
Outdated
.transact({'from': ursula2}) | ||
testerchain.wait_for_receipt(tx) | ||
tx = token_agent.contract.functions.approve(miner_agent.contract_address, constants.MIN_ALLOWED_LOCKED * 6)\ | ||
tx = token_agent.contract.functions.approve(miner_agent.contract_address, MIN_ALLOWED_LOCKED * 6)\ | ||
.transact({'from': ursula3}) | ||
testerchain.wait_for_receipt(tx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the clarity of previous lines would benefit from having a variable functions = token_agent.contract.functions
(or some other similar name), so lines length can be reduced reduced, and hopefully, become one-liners.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried only to maintain and not change the logic of this script at all during the course of this PR.
Of course this is not a pubic API, we typically use higher-level methods to wrap these contract calls - are made at one of the lowest levels in the stack, executing EVM contract code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I named the contract function callers ✔️
tests/metrics/estimate_gas_tester.py
Outdated
.estimateGas({'from': ursula3}))) | ||
tx = miner_agent.contract.functions.deposit(constants.MIN_ALLOWED_LOCKED * 2, int(constants.MIN_LOCKED_PERIODS))\ | ||
tx = miner_agent.contract.functions.deposit(MIN_ALLOWED_LOCKED * 2, int(MIN_LOCKED_PERIODS))\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same, but for miner_agent.contract.functions
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
tests/metrics/estimate_gas_tester.py
Outdated
.estimateGas({'from': ursula1}))) | ||
tx = miner_agent.contract.functions.confirmActivity().transact({'from': ursula1}) | ||
testerchain.wait_for_receipt(tx) | ||
print("Divide stake (next period is confirmed) = " + | ||
str(miner_agent.contract.functions.divideStake(0, int(constants.MIN_ALLOWED_LOCKED), 2) | ||
str(miner_agent.contract.functions.divideStake(0, int(MIN_ALLOWED_LOCKED), 2) | ||
.estimateGas({'from': ursula1}))) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seems to be a lot of repeated logic for Ursulas 1, 2, and 3. This can be error-prone. Perhaps do this more generically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm interested in your suggestions - What can we do better here?
We do want to keep this script as simple as possible and not let it become a time sink.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tagging @szotov - the original author
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This script is some common cases and some edge cases that shows where optimization goes. Almost each line depends on executing previous code because each function changes storage of contracts. So it's why this looks like repeated functions but it's not
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But is it possible to make Ursula a parameter here? And then reuse the code for Ursulas 1, 2 and 3.
tests/metrics/estimate_gas_tester.py
Outdated
return | ||
label, gas = (s.strip() for s in message.split('=')) | ||
print('{label} {dots} {gas:,}'.format(label=label, | ||
dots='.' * (65 - len(label)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of explicitly computing the number of dots, you can just right-pad the label with '*'
:
label.ljust(65, '*')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! ✔️
Co-Authored-By: KPrasch <kieranprasch@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't say I've fine-toothed it, but I don't see anything totally outrageous.
Restores the
estimate_gas.py
scenario-based metrics script. Uses the twisted logger facilities to collect, store, and view gas estimation data. Log files can possibly be used as a build artefact, or extended for further analysis. Fixes #602Example Build: https://circleci.com/gh/nucypher/nucypher/8175#artifacts/containers/0
Example Artefact: https://8175-100446516-gh.circle-artifacts.com/0/home/circleci/nucypher-depends/tests/metrics/results/1544742453-estimate-gas.json