I've been debating on whether I should use <
or <=
in a for
loop.
So I decided to conduct a small test and verify that their gas costs are the same.
Here is my contract:
pragma solidity 0.4.24;
contract MyContract {
uint public value;
function func1(uint x) external {
for (uint i = 0; i < x; i++)
value += i;
}
function func2(uint x) external {
for (uint i = 0; i <= x; i++)
value += i;
}
}
And here is my Truffle test:
contract("MyContract", function(accounts) {
it("func1", async function() {
const myContract = await artifacts.require("MyContract").new();
const response = await myContract.func1(11);
console.log(response.receipt.gasUsed);
});
it("func2", async function() {
const myContract = await artifacts.require("MyContract").new();
const response = await myContract.func2(10);
console.log(response.receipt.gasUsed);
});
it("func1", async function() {
const myContract = await artifacts.require("MyContract").new();
const response = await myContract.func1(101);
console.log(response.receipt.gasUsed);
});
it("func2", async function() {
const myContract = await artifacts.require("MyContract").new();
const response = await myContract.func2(100);
console.log(response.receipt.gasUsed);
});
it("func1", async function() {
const myContract = await artifacts.require("MyContract").new();
const response = await myContract.func1(1001);
console.log(response.receipt.gasUsed);
});
it("func2", async function() {
const myContract = await artifacts.require("MyContract").new();
const response = await myContract.func2(1000);
console.log(response.receipt.gasUsed);
});
});
The results show in a conclusive manner that <=
is cheaper than <
:
Contract: MyContract func1: 94494
Contract: MyContract func2: 94436
Contract: MyContract func1: 567714
Contract: MyContract func2: 567386
Contract: MyContract func1: 5299978
Contract: MyContract func2: 5296950
Does that make any since at all? AFAIK, both operations (LT and LTE) cost 3 gas units!
I've disassembled the contract, here are the relevant parts:
For the <
operation:
/* "MyContract.sol":142:143 x */
dup2
/* "MyContract.sol":138:139 i */
dup2
/* "MyContract.sol":138:143 i < x */
lt
For the <=
operation:
/* "MyContract.sol":247:253 i <= x */
dup2
dup2
gt
They indeed look different (though mostly in the comments for some reason).
And to be honest, I'm not quite sure why gt
is used in the <=
case.
But other than that, it still doesn't strike me as to why the gas cost is different here.
For all it matters, I've used the default optimization settings (optimize-runs=200
).
Thank you.