0
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

  • Can you show us the context? eg from that we can't see what's in memory and what's in storage, or whether any matching entry in that array would do or whether you need the first one you come to. – Edmund Edgar Nov 18 '17 at 21:32
3

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.

  • could you please have a look at the edit? – mankee Nov 19 '17 at 0:13
  • It's a bit hard to debug without the whole code. But some observations: (1) Memory calculation for mload should be in bytes, not bits; (2) Inside the if block, your comment says add 512, but you actually add 544, and it probably ought to be 96 = 0x60 in bytes anyway; (3) you don't need to use assembly inside the if block really since it is executed only once (unless there is another outer loop you are not showing us). – benjaminion Nov 19 '17 at 5:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.