Optimización de bucle para el uso de gas

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;
  }
}

He estado tratando de ver si hay alguna forma de optimizar este bucle para que consuma menos gas, ya que se ejecuta una gran cantidad de veces en mi contrato, sin embargo, puedo pensar en optimizaciones obvias. ¿Me estoy perdiendo de algo?

ACTUALIZAR

  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;
            }   
    }   

Así que agregué el siguiente código, sin embargo, ahora resultsiempre es 0. No estoy seguro de lo que estoy haciendo mal... Tenga en cuenta que my_int y my_second_int son ambos uint256y ides una dirección

¿Puedes mostrarnos el contexto? por ejemplo, a partir de eso no podemos ver qué hay en la memoria y qué hay en el almacenamiento, o si cualquier entrada coincidente en esa matriz funcionaría o si necesita la primera a la que llega.

Respuestas (1)

Podría comenzar usando un uinttipo para la variable de bucle en lugar de uint8. Esto no es obvio, pero el compilador introduce código adicional para hacer coerción de tipos cuando usa tipos de menos de 256 bits. Esto utiliza gas adicional.

El costo general principal será la verificación de los límites de la matriz para los my_array[i]cuales el compilador inserta, le guste o no. Actualmente, la única forma de evitarlo es usar ensamblado en línea .

¿Podrías echar un vistazo a la edición?
Es un poco difícil de depurar sin el código completo. Pero algunas observaciones: (1) El cálculo de la memoria mloaddebe ser en bytes, no en bits; (2) Dentro del ifbloque, su comentario dice add 512, pero en realidad agrega 544, y probablemente debería estar 96 = 0x60en bytes de todos modos; (3) no necesita usar ensamblador dentro del ifbloque, ya que se ejecuta solo una vez (a menos que haya otro ciclo externo que no nos esté mostrando).