Unterschied zwischen nicht optimiertem und optimiertem Solidity-Code

Ich versuche, eine Quelle für den Unterschied zwischen optimiertem und nicht optimiertem Code zu finden. Meine Hauptfrage ist, was der nicht optimierte Compiler tut, insbesondere im Sinne des Aufrufens des SSTOREOpcodes.

Nehmen wir an, ich habe dies:

contract A{
    uint8 mem1;
    uint8 mem2;

    function store(uint8 store1, uint8 store2){
        mem1=store1;
        mem2=store2;
    }
}

Wenn ich dies auf "dumme" Weise kompilieren würde, würde ich SSTOREzweimal aufrufen, um beide Variablen zu speichern. Um dies jedoch zu optimieren, würde ich die ersten 8 Bits von an uint256( SSTOREspeichert immer uint256) zu mem1und die zweiten 8 Bits zu zuweisen mem2. So muss ich nur SSTOREeinmal pro Transaktion anrufen. Dies kann jedoch zu einem leichten Overhead in anderem Code führen, den der Vertrag möglicherweise hat, da wir die richtigen Bits extrahieren müssen. SSTOREverbraucht 20.000 Gas, wenn ein Wert ungleich Null gespeichert wird, sodass die Optimierung dieses Codes 20.000 Gas spart.

Ruft der nicht optimierte Compiler beim Kompilieren des obigen Codes SSTOREzweimal oder einmal auf? Ich weiß, dass ich das selbst überprüfen kann, indem ich die kompiliere und lese OPCODES, aber ich würde gerne eine Quelle dafür finden, was beide Compiler tun sollten.

Es selbst zu überprüfen scheint die einfachste Option zu sein, aber Sie könnten auch den Compiler-Quellcode lesen. (Suchen Sie nach „Optimizer“.) Ich glaube nicht, dass die Optimierungen besonders gut dokumentiert sind.
In Ordnung, traurig zu hören, dass die Optimierung nicht gut dokumentiert ist, da es jetzt schwer zu lernen ist, ob Sie "hackige" Speichermöglichkeiten erstellen müssen, um Gas zu sparen, oder ob der Optimierer dies für Sie erledigt.
Das ist eine sehr interessante Frage. Der nicht optimierte Compiler generiert Code mit 1xSLOAD und 2xSSTORE. Allerdings(!), was ich nicht erwartet hatte, die Benzinkosten betragen immer noch nur 21000 + 26442 (geth 1.7.2). Ich hatte erwartet, etwas wie 21000 + 200 + 40000 + X zu sehen. Wie kann das erklärt werden? Es sieht so aus, wenn wir zweimal an dieselbe Adresse schreiben, kostet das zweite nur 5000?
Nur um sicherzugehen, speichern Sie beim zweiten Mal keine Null? 5k ist Gas, das verwendet wird, um eine Null zu speichern.
Nö. Ich habe Ihren Code mit 1,2 als Parameter verwendet.
Das macht keinen Sinn. In der Dokumentation, die ich gelesen habe, verbraucht SSTORE 20.000 Gas für jeden Aufruf. Sind vielleicht die 21k für jede Transaktionseinstellung Saldo (20k) und Prozess (1k?), so dass diese "verlorenen" 20k tatsächlich in diesen "21k" sind?

Antworten (1)

Ruft der nicht optimierte Compiler beim Kompilieren des obigen Codes SSTORE zweimal oder einmal auf?

Ja, der nicht optimierte Code ruft SSTORE zweimal auf. Der zweite SSTORE zum selben Speicherplatz kostet jedoch nur 5.000 Gas, da er nur den Wert in einem vorhandenen Platz zurücksetzt. (Siehe „ Unterscheiden sich die Kosten für das Aktualisieren von Speicher von den Kosten für das Hinzufügen von Speicher? “)

Optimierter Code hat nur einen SSTORE.

AFAIK gibt es kein Dokument, das genau beschreibt, was der Optimierer tut. Ich denke, Sie müssen dafür Code und ChangeLogs durchgehen.

Ich wusste nicht, dass die Aktualisierung weniger kostet. Bedeutet Aktualisierung „zugewiesener Speicherplatz“ oder Aktualisierungen von Quellen, die sich derzeit im Speicher befinden? Ich sehe viele Verweise auf das Yellow Paper und werde es lesen, danke.
Es bedeutet: für 'zugewiesenen Speicherplatz'. Set -> Sie erstellen einen neuen Knoten im Speicherversuch. Zurücksetzen -> Sie ändern den Wert eines vorhandenen Trie-Knotens. Zeroing -> Sie entfernen Knoten aus dem Speicherversuch, was mit der 15.000-Gas-Rückerstattung belohnt wird.