[Ethereum] Loop Optimisation for gas usage

gasoptimizationsolidity

for (uint8 i = 0; i < total; i++) {
  if (myarray[i].my_int >= maximum && my_array[i].my_second_int <= maximum) {
        result = my_array[i].id;
        break;
  }
}

I've been trying to see if there's any way to optimise this loop so that it consumes less gas, as it is executed a very large number of times in my contract, however, I can think of any obvious optimisations. Am I missing something?

UPDATE

  for (uint8 i = 0; i < total; i++) {
            assembly {
                //We only add 32 bits because my_int is first in the struct.

                my_int := mload(add(add(myarray_slot, 0x20), mul(i, 0x2A0)))

                //We add 288 because my_second)int is second in array

                my_second_int := mload(add(add(myarray_slot, 0x120), mul(i, 0x2A0)))
            }
            if (my_int >= maximum && my_second_int <= maximum) {
                assembly {
                    //We add 512 to get to address position in struct (2 * 256 bit ints) and we multiply with 672 (total size of struct (2 ints * 256 + address of size 160 bits))

                    result := mload(add(add(myarray_slot, 0x220), mul(i, 0x2A0)))
                }
                break;
            }   
    }   

So I added the following code, however now result is always 0. I'm not sure what I'm doing wrong…Please note my_int and my_second_int are both uint256 and id is an address

Best Answer

You could start by using a uint type for the loop variable rather than uint8. This is not obvious, but the compiler introduces extra code to do type-coercion when you use types smaller than 256-bits. This uses extra gas.

The main overhead cost will be the array bounds checking for my_array[i] which the compiler inserts whether you like it or not. Currently the only way to avoid that is to use inline assembly.

Related Topic