Optimización de bucle comprobando coordenadas en una cuadrícula

Creé un contrato donde los usuarios pueden establecer una imagen en una coordenada específica, esa posición solo puede tener una imagen. El tamaño de la cuadrícula es de 400 de alto y ancho dinámico (crecerá con el tiempo) y hay 3 tamaños de imagen diferentes: 10x10, 20x20, 40x40 (píxeles).

Necesito optimizar el circuito para reducir el costo del gas, que es muy alto en este momento.

Aquí está mi implementación actual, donde las coordenadas y los tamaños se dividen por 10 para reducir el costo del combustible.

pragma solidity 0.4.19;


contract Test {

    mapping (uint => bool[40]) public grid;

    function check(uint x, uint y, uint size) public {

        for(uint i = 0; i < size; i++) {
            for(uint j = 0; j < size; j++) {

                if(grid[x + i][y + j]) {
                    // image exists in this slot
                    revert();
                }

                grid[x + i][y + j] = true;

            }
        }
    }

}

Tamaños posibles:

 - small: 1 (1 slot)
 - medium: 2 (4 slots)
 - big: 4 (16 slots)

Costo actual del gas :

- Small: 43223
- Medium: 76251
- Big: 163181
Puede ahorrar la mitad del combustible simplemente declarando que su mapeo está en uintlugar de boolen su código original. Creo que esto se debe a cómo Solidity empaqueta los valores booleanos cuando se escriben. Puede ser más fácil que el montaje :-)
@benjaminion acaba de intentarlo, en realidad aumenta mucho, Gas: 351253 para el panorama general, en lugar de 163181. Gracias de todos modos :), estoy intentando todo, incluso el montaje, que realmente no sé. Preferiría tener una respuesta sólida, pero cualquier cosa serviría. Estoy usando trufa y ganache para probar los costos de gasolina, en caso de que haya diferencias con la red principal.
Sí, hice algo mal :-) Disculpas. Creo que la principal forma en que el ensamblaje podría ayudarlo aquí es si lo usa para minimizar las cargas y las tiendas en la cuadrícula de paquetes de bits (es decir, verifique los sizebits a la vez con una carga en lugar de hacer sizecargas; lo mismo ocurre con el almacenamiento). Esto será bastante complicado y requiere un conocimiento profundo del almacenamiento de mapas de solidez. Una simple traducción ingenua a ensamblaje puede ayudar un poco al eliminar los controles de límites, pero no es el gran premio.
Entiendo, muchas gracias. Tal vez mi código ya esté optimizado, y tendré que aceptar que los usuarios tendrán que pagar esa cantidad de gasolina. Probablemente me quede con el código de solidez, pero solo para sacarlo de mi cabeza, ¿sabe cómo leer/escribir una matriz 2D o mapear en ensamblaje? No encontré nada en la web, y realmente quiero saber.

Respuestas (1)

Puede empaquetar todos los bools en una fila en una sola unidad y ahorrar en actualizaciones de almacenamiento:

pragma solidity 0.4.19;

contract Test {

    mapping (uint => uint) public grid;

    function check(uint x, uint y, uint size) public {

        for(uint i = 0; i < size; i++) {
            uint row = grid[x + i];
            for(uint j = 0; j < size; j++) {
                // if (y + j) bit is set in row
                if((row >> (y + j)) & uint(1) == uint(1)) {
                    // image exists in this slot
                    revert();
                }

                // set bit (y + j)
                row = row | (uint(1) << (y + j)); 
            }
            grid[x + i] = row;
        }
    }
}

Nuevos costos de gas :

- Small: 42632
- Medium: 63808
- Big: 107750

Cuanto mayor sea el tamaño, mayor será la mejora.

Tenga en cuenta también que las llamadas posteriores a checklas filas que se han tocado costarán aún más barato porque solo tendrá que pagar 5,000gasolina para actualizar las ranuras de almacenamiento en lugar de 20,000. Llamar check(0,0,4)seguido de check(0,4,4)costará solo 48214 gas.

Puede optimizarlo aún más empaquetando varias filas en un único uint. Si cada fila tiene 40 bits, puede empaquetar [256 / 40] = 6 filas. Sin embargo, el código será un poco más complejo.


Respuesta anterior:

Mire los bucles en el ensamblaje http://solidity.readthedocs.io/en/develop/assembly.html#loops . Permiten ahorrar gas en la comprobación de límites.

Puedes encontrar más ejemplos aquí

Gracias por responder, lo sabía, pero no conozco ningún ensamblaje, y creo que será un riesgo si codifico un contrato inteligente que no entiendo: P. Estoy buscando cómo acceder a una asignación en ensamblaje, pero aún no encuentro ningún ejemplo.
Intenté cambiar el código a ensamblaje, pero tengo problemas para recuperar/guardar la matriz de mapeo/2D. ¿Quieres echar un vistazo?
Claro, puedes incluir tu código en la pregunta.
De hecho, la idea de @MarcosCasagrande benjaminion fue buena. Actualicé mi respuesta.
Wow, muy buenas mejoras. ¡Estoy haciendo pruebas y todo parece funcionar perfectamente! ¡Permíteme un momento para entender completamente el código y te daré la recompensa!
Muchas gracias, muy inteligente empacando los bools en una unidad. You may award your bounty in 19 hours. En 19 horas es tuyo!