This post is in continuation from the last one which was on saving gas by referencing data from memory. Now we will see a case where this can be contradictory.
Consider the following contracts:
contract varReferencing_1{
uint[] public arr;
uint public arrLength;
function addItem(uint _item) external {
arrLength = arrLength + 1; // updating state
arr.push(_item); // adding element
for (uint i; i < arrLength; i++) {
arr[i] = arrLength + i; // updating state
}
}
}
contract varReferencing_2{
uint[] public arr;
uint public arrLength;
function addItem(uint _item) external {
uint _arrLength = arrLength + 1; // storing into memory
arr.push(_item); // adding element
uint[] memory _arr = arr; // storing into memory
for (uint i; i < _arrLength; i++) {
_arr[i] = _arrLength + i;
}
arr = _arr; // updating state
arrLength = _arrLength; // updating state
}
}
contract varReferencing_3{
uint[] public arr;
uint public arrLength;
function addItem(uint _item) external {
uint _arrLength = arrLength + 1; // storing into memory
arr.push(_item); // adding element
for (uint i; i < _arrLength; i++) {
arr[i] = _arrLength + i;
}
arrLength = _arrLength; // updating state
}
}
All the three contracts have the exact same functionality, to push new element to the array and sum the index of all the elements with new array length and update it in array. (Note: this functions have no use in practical, these are just examples)
Lets see the differences and the gas spent for each contract:
varReferencing_1
addItem
increases the state variable arrLength
by 1, pushes new element _item
to state variable array arr
and updates each array element with new length + index.
varReferencing_2
addItem
increases the copy of state variable _arrLength
by 1, pushes new element _item
to state variable array arr
and makes it's copy in memory. Then these copies are used to perform further operations and then assigned to original state variables.
varReferencing_3
addItem
makes copy of arrLength
state variable in memory, but not of the arr
. And rest of the operations are same.
Conclusion
varReferencing_2 was expected to be most gas efficient because it makes copies of both state variables, but it turned out to be most expensive. This was probably due to copying arr
from storage to memory and then back to storage after all the operations.
In varReferencing_3, we just made copy or arrLength
and that turned out to be the most gas efficient method.
Top comments (0)