Warum kostet uint8 mehr Gas als uint256?

contract A {
  uint8 a = 0;
}

kostet 20150 + 2000 Gas während der Erstellung.

verglichen mit

contract A {
  uint a = 0;   // or uint256
}

kostet 5050 + 2000 Gas während der Erstellung

Es ist seltsam, dass eine Variable, die weniger Speicherplatz benötigt, mehr Benzin kostet. Warum ist das so?

Antworten (4)

Das EVM arbeitet mit 256-Bit/32-Byte-Wörtern (umstrittene Designentscheidung). Jede Operation basiert auf diesen Basiseinheiten. Wenn Ihre Daten kleiner sind, sind weitere Operationen erforderlich, um von 256 Bit auf 8 Bit herunterzuskalieren, weshalb Sie erhöhte Kosten sehen.

Übrigens, wenn Sie die "Details" im Online-Solidity-Compiler umschalten, erhalten Sie den genauen Assembly-Dump, aus dem die zusätzlichen Opcodes stammen. Ich hatte jetzt keine Zeit, sie zu interpretieren, aber wenn Sie dies tun und feststellen, dass es etwas Zusätzliches gibt, bin ich sicher, dass das Solidity-Team gerne Optimierungen hinzufügen würde, um sie zu umgehen.

Ja, ich habe die Aufbauanleitung gesehen. Ich würde es weiter untersuchen, wenn ich hier keine Antworten bekommen könnte. Danke für deine Antwort. Es ist eine seltsame Entscheidung, damit anzufangen uint256. Nächste Frage Ich frage mich, ob es dann immer sinnvoll ist, sich einfach an uint256 zu halten und niemals kleiner zu werden.
@uzyn Die Verwendung kleinerer Werte für den Speicher ist sinnvoll, da das Schreiben in den Speicher teuer ist und der Compiler mehrere kleinere Argumente packt. Bei Funktionsparametern und Speichervariablen macht es nur Sinn, wenn man den Wertebereich einschränken will: Packen gibt es nicht, also weder mehr noch weniger Aufwand.
Wenn wir eine Variable wie uint32in a structstatt erstellen uint256und sie in ein Array schieben, kostet es viel weniger Gas.

Es sollte jedoch beachtet werden, dass uint8 in einer Struktur aufgrund der engen Packungsfunktion weniger kostet als ein herkömmliches uint. Stellen Sie außerdem sicher, dass Ihre Uints neben Ihren anderen Uints und Bytes neben Bytes usw. liegen. Dies erhöht die dicht gepackten Funktionen weiter.

Was meinen Sie mit "stellen Sie sicher, dass Ihre Uints neben Ihren anderen Uints und Bytes neben Bytes usw. liegen". Also structsollte in a uintsnacheinander auch auf andere Typen definiert werden und warum? @ VoR0220
Er empfiehlt dies, da die Reihenfolge, in der Sie Ihre Zustandsvariablen deklarieren, die Gesamtzahl der von Ihrem Vertrag verwendeten Speicherplätze beeinflussen kann. Wenn Sie 2 uint128 und dann einen uin256 deklarieren, werden 2 256-Bit-Speicherplätze verwendet. 1 Steckplatz für die 2 uint128 und 1 Steckplatz für den uint256. Wenn Sie 1 uint128 deklarieren, dann ein uint256, dann ein uint128, verwendet Ihr Vertrag 3 Speicherplätze, da die mittlere uint256-Zustandsvariable nicht in einen Speicherplatz mit einem der uint128 passen kann, also muss jede Variable haben einen eigenen Speicherplatz.

SOLC 0.4.18: Jetzt ist der Unterschied gering

https://ethfiddle.com/6lt852gx7K

Vertrag A mit uint8Kosten von 75414 für die Bereitstellung

Vertrag B mit uint256Kosten von 73867 für die Bereitstellung

Ein Unterschied von 1547 Gas.

gilt immer noch in den neuesten Solidity-Versionen (gleiche genaue Kosten für 0.6.11 und 0.7.1)
Auf solidity 0.8.10 ist es etwa 100 Gas teurer unit8 einzusetzen als uint256.

Update im Dezember 2021:

Wenn Sie so etwas testen: 5 Variablen statt nur 1, was eher einem realen Szenario mit mehreren Variablen ähneln könnte, nicht nur einer.

contract A {
  uint8 a = 0;
  uint8 b = 0;
  uint8 c = 0;
  uint8 d = 0;
  uint8 e = 0;
}

Dann ist es billiger als seine uint256-Version.

Aus dem Remix:

uint8: 69484gas uint256: 78420gas

Update Juni 2022 (0.8.15)

uint8: 83524gas uint256: 90183gas

Sie sparen also Gas, wenn Sie Uint mit geringerer Größe verwenden, wie andere Kommentare sagen, wenn es sich um Arrays handelt, sparen Sie mehr.