Ich habe einen Vertrag erstellt, bei dem Benutzer ein Bild in einer bestimmten Koordinate festlegen können, diese Position kann nur ein Bild haben. Die Rastergröße ist 400 hoch und dynamisch breit (wird mit der Zeit wachsen) und es gibt 3 verschiedene Bildgrößen: 10 x 10, 20 x 20, 40 x 40 (Pixel).
Ich muss den Kreislauf optimieren, um die derzeit sehr hohen Gaskosten zu senken.
Hier ist meine aktuelle Implementierung, bei der Koordinaten und Größen durch 10 geteilt werden, um die Gaskosten zu senken.
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;
}
}
}
}
Mögliche Größen:
- small: 1 (1 slot)
- medium: 2 (4 slots)
- big: 4 (16 slots)
Aktuelle Gaskosten :
- Small: 43223
- Medium: 76251
- Big: 163181
Sie können alle bools hintereinander in eine einzige uint packen und Speicheraktualisierungen sparen:
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;
}
}
}
Gaskosten neu :
- Small: 42632
- Medium: 63808
- Big: 107750
Je größer die Größe, desto größer die Verbesserung.
Beachten Sie auch, dass nachfolgende Aufrufe check
in den berührten Reihen sogar noch billiger werden, da Sie nur 5,000
Gas für die Aktualisierung von Speicherplätzen bezahlen müssen, anstatt 20,000
. Ein Anruf check(0,0,4)
mit anschließendem Anruf check(0,4,4)
kostet nur 48214 Gas.
Sie können es noch weiter optimieren, indem Sie mehrere Zeilen in einzelne Einheiten packen. Wenn jede Zeile 40 Bit hat, können Sie [256 / 40] = 6 Zeilen packen. Der Code wird jedoch etwas komplexer.
Vorherige Antwort:
Sehen Sie sich Schleifen in Assembly an http://solidity.readthedocs.io/en/develop/assembly.html#loops . Sie ermöglichen das Einsparen von Gas bei der Grenzkontrolle.
Weitere Beispiele finden Sie hier
You may award your bounty in 19 hours
. In 19 Stunden gehört es Ihnen!
Benjaminion
uint
alsbool
Ihren ursprünglichen Code deklarieren. Dies liegt daran, wie Solidity Booleans packt, wenn sie geschrieben werden, denke ich. Vielleicht einfacher als der Zusammenbau :-)Marco Casagrande
Benjaminion
size
Bits gleichzeitig mit einer Ladung zu prüfen, anstattsize
Ladungen auszuführen; dito Speichern). Dies wird ziemlich kompliziert sein und erfordert tiefgreifende Kenntnisse über Solidity-Mapping-Speicherung. Eine einfache naive Übersetzung in Assembler kann ein wenig helfen, indem sie Grenzenüberprüfungen eliminiert, aber es ist nicht der große Preis.Marco Casagrande