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 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 check
las filas que se han tocado costarán aún más barato porque solo tendrá que pagar 5,000
gasolina 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í
You may award your bounty in 19 hours
. En 19 horas es tuyo!
benjaminion
uint
lugar debool
en 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 :-)marcos casagrande
benjaminion
size
bits a la vez con una carga en lugar de hacersize
cargas; 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.marcos casagrande