-
Notifications
You must be signed in to change notification settings - Fork 15
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
feat: adds a few more tips #1
base: main
Are you sure you want to change the base?
Conversation
090f23d
to
3afa909
Compare
on it
🤝
Well if it's me i'd like to go straight for the example, and maybe have detail explanation after w links? Once we get a bunch of these we can think of the best ways to group and sort them. Can I ask you @transmissions11 when you think about optimizations does your mental model group them into any categories?
🤝 classy |
src/GolfCourse.sol
Outdated
// SPDX-License-Identifier: GPL-3.0-or-later | ||
pragma solidity ^0.8.6; | ||
|
||
contract GolfCourse { |
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.
for now I've put all these tests in one contract in one file, but I believe you would like to do one contract/file per example - please confirm
src/GolfCourse.sol
Outdated
pragma solidity ^0.8.6; | ||
|
||
contract GolfCourse { | ||
function unoptimizedDivideByTwo() external pure returns (uint256 two) { |
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.
what do you think of the function naming? we could also consider a numbering system
README.md
Outdated
### 1. When dividing by two, use `>> 1` instead of `/ 2` ### | ||
|
||
```solidity | ||
/// 🤦 Unoptimized (gas: 1401) |
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.
what do you think of showing the gas from the test in the comment here?
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.
love it, tho may get hard to maintain after sol upgrades etc...
README.md
Outdated
|
||
The `SHR` opcode is 3 gas cheaper than `DIV` and also bypasses Solidity's division by 0 prevention overhead. | ||
- [Gas Usage]() | ||
- [Full Example](https://github.com/Rari-Capital/golf-course/blob/fc1882bacfec50787d9e9435d59fed4a9091fb21/src/GolfCourse.t.sol#L15) |
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 you mentioned we should link to the test, which is what I've done here, but I was also thinking maybe it would be good to link to the example 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.
yea i think we should do that instead of test tbh wdyt
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.
we could even break convention and put the example code in the test file...
README.md
Outdated
|
||
### 3. Using `!=` is usually cheaper than `>` or `<` ### | ||
```solidity | ||
/// 🤦 Unoptimized (gas: 1423) |
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.
haha, I couldn't get this "tip" to work ... maybe it's a myth?
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 cuz of
- function overhead in dapptools tests
- we're using constants and not dynamic values so the compiler can optimize at compile time
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.
Tried it with dynamic values for both sides of the equation. Also tried different values (like zero and non zero) No matter what I do, I was unable to repro gas savings. Taking this one off the list as well althought I'd be happy to be proved wrong on any of these.
Also, maybe because I'm using pragma 0.8.11???
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.
Actually I figured it out. It only saves gas within a require()
README.md
Outdated
```solidity | ||
// Unoptimized: | ||
uint256 two = 4 / 2; | ||
/// 🤦 Unoptimized (gas: 1535) |
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.
In spite of the increased variable overhead, the gas is still cheaper using the assembly. This kinda goes against our idea of putting in controls to ensure that every "optimization" is less gas than the unoptimized version. Wdyt? Perhaps we could have separate section for optimizing for variable overhead?
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.
very possible its not a saving technique on its on, the savings do come in tho if u're accessing codesize via a library like Address.sol which has function call overhead associated. but yeah maybe not good for this guide then
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.
removing it from tips, we'll put this on the back burner
Hey @transmissions11 I've spent a lot of time thinking about the formatting, and more importantly figuring out how we can get as accurate of gas usage numbers as possible. There are so many things that could affect the gas usage including the ordering of the variables or functions and the Contract names. For that reason, I have decided to use two new contracts (optimized and unoptimized) for each tip. If we had all the tips in one (or two) giant contracts and then we were to subsequently add a tip, it could potentially change all of the reported gas usages for all of the other functions/tests. This way still isn’t perfect, I've noticed in some cases, the gas usage reported by Dapp Tools can change (or not change) based on the name of the contract being different (even with everything else 100% the same). But I think it’s about as close as we can get for now with the tools we have. Anyways, I think we've got some good tips to start out with. Review this and let me know what you think. Maybe we can merge this and do some sort of "soft opening" to the public soon to get comment and maybe some more submissions. |
This may be a stupid idea, but, if contract names can cause problems and we want testing conditions to be as identical as possible, we could import {DivideByTwo as UnoptimizedDivideByTwo} from "src/UnoptimizedDivideByTwo.sol"
import {DivideByTwo as OptimizedDivideByTwo} from "src/OptimizedDivideByTwo.sol" I'm not on my computer now, so I'll try it tomorrow. This should make the testing conditions as identical as possible and could help with writing scripts for calculating gas savings. |
@ZeroEkkusu Sounds like a good idea! I still think we should do the 2 contracts per tip for the reasons I stated, but if your idea works than we don't have to name the contracts |
Okay, so I just tested those but don't get different gas usages because of contract names 🤔 Your solution with separate testing contracts works perfectly, though! But, if you know names could cause a difference, we can name them the same, as I wrote above. |
@ZeroEkkusu Try the reentrancy one. If you copy the optimized code to the unoptimized contract I see a diff in gas
As such I really like your idea of two separate folders with everything else the same including contract names. In fact I've been using your idea to test out some things in other projects and so far seems to work flawlessly. When I have time I will update this pr to use that pattern |
@devtooligan 👍
Drop the |
Improve the "Make functions `payable`" tip
…rse into some-tips-to-start
@ZeroEkkusu I just realized your idea of same named contracts in two different folders only works on Dapp Tools and not foundry :/ Oh well, I've been using Dapp Tools a lot on this one, esp the debugger. |
@devtooligan Why is this a problem? Does naming testing contracts differently cause differences in reported gas savings? I'm using Foundry for the golf-course, btw. I know you can't name testing contracts the same, but haven't noticed any issues with your Will take a closer look at this today. |
@ZeroEkkusu I upgraded the repo to use your suggestion it works great, just doesn't work w Foundry I did find a discrepancy in gas based on contract name for the reentrancy tip. Try copy pasting the code from the unoptimizedRentrancy to the optimizedReentrancy contract so they both have the same code and run the test. |
Dir structure:
Maybe I'm missing something you're saying, @devtooligan. Also, do you know that you have to force recompile when you change something in a core contract because there's currently a bug with Forge? Here's the repo: https://github.com/ZeroEkkusu/golf-test |
@devtooligan Could you clone the repo and try: https://github.com/ZeroEkkusu/golf-test
|
@ZeroEkkusu I will clone ur repo and do that just to further investigate the difference, but anyways I think we're going to drop the reentrancy tip because both DappTools and Foundry are erroneously reporting a large gas savings because neither handle gas refunds properly https://twitter.com/devtooligan/status/1494233623830138880?s=20&t=h7hwmiernm_Li41YClkEJw So I wanna see if I can find another example of contract name causing a difference in reported gas usage as well. |
This pr adds a few more tips to the
README.md
file.Some notes/thoughts:
>>
but on the other hand it's kinda nice to write them out tooRight shift
-- my attempts at using both in the title did not come out well "Use Right shift (>>
) instead of divide by two (/ 2
)" (It looks even worse with >= or >)... Wdyt?two
as a variable name which made sense in that case, but thought it might be more clear if standardize on the commonly usedfoo
andbar
Solcurity standard
but for optimization.