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 thanuint8
. 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.