Solidity Gas Profiling
Gas profiling is measuring how much gas two versions of the same task use. The captured run on this toolchain reports each version's figure, and only that run's figures are claimed here.
Two loop versions return the same total
One loop reads the list length on every pass and the other caches it first. Both versions sum the same list to the same total.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract LoopSum {
uint256[] public values;
function addValue(uint256 v) public {
values.push(v);
}
function sumDirect() public view returns (uint256 total) {
for (uint256 i = 0; i < values.length; i++) {
total += values[i];
}
return total;
}
function sumCached() public view returns (uint256 total) {
uint256 len = values.length;
for (uint256 i = 0; i < len; i++) {
total += values[i];
}
return total;
}
}
Two storage-read versions return the same total
One version reads a stored value on every pass and the other caches it once. Both versions return the same total for the same count.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract ReadSum {
uint256 public stored;
function setStored(uint256 v) public {
stored = v;
}
function sumDirect(uint256 n) public view returns (uint256 total) {
for (uint256 i = 0; i < n; i++) {
total += stored;
}
return total;
}
function sumCached(uint256 n) public view returns (uint256 total) {
uint256 v = stored;
for (uint256 i = 0; i < n; i++) {
total += v;
}
return total;
}
}
Two counter styles return the same sum
One loop uses the plain counter step and the other uses an unchecked step. Both versions sum the same calldata list to the same total.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract CountSum {
function sumChecked(uint256[] calldata values) external pure returns (uint256 total) {
for (uint256 i = 0; i < values.length; i++) {
total += values[i];
}
return total;
}
function sumUnchecked(uint256[] calldata values) external pure returns (uint256 total) {
for (uint256 i = 0; i < values.length;) {
total += values[i];
unchecked {
++i;
}
}
return total;
}
}
Example
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract ProfileVault {
uint256 public bonus;
uint256[] public values;
function addValue(uint256 v) public {
values.push(v);
}
function setBonus(uint256 v) public {
bonus = v;
}
function sumDirect() public view returns (uint256 total) {
for (uint256 i = 0; i < values.length; i++) {
total += values[i] + bonus;
}
return total;
}
function sumCached() public view returns (uint256 total) {
uint256 len = values.length;
uint256 b = bonus;
for (uint256 i = 0; i < len; i++) {
total += values[i] + b;
}
return total;
}
}
Key points
- Gas profiling: Gas profiling is measuring how much gas two versions of the same task use.
- Same input: Profiling compares versions on the same input so the comparison is fair.
- Same result: Both versions must return the same result, or the comparison means nothing.
- Captured run: A captured run is the real test run whose figures are printed on the page.
- Restatement: Gas profiling measures two versions of one task on one input and reads the figures from the captured run.
In this example, sumDirect reads the list length and the bonus on every pass. SumCached reads both once before the loop and reuses them inside it. Both versions return 40 for the same list and bonus, and the captured run reports each version's figure.
Note
Figures here come only from the captured run on this toolchain and are never claimed as universal.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Remix IDE
Exercise
What makes a gas comparison fair?