Wie skalieren die Kosten für EVM-Speicher?
Ich frage mich, wie die Kosten für EVM-Speicher (nicht Speicher) steigen?
Tatsächlich sind die Speicherkosten nach dem Lesen anderer QAs keine lineare Funktion, sondern sollten schnell steigen, wenn mehr davon zugewiesen wird?
Nachdem ich den Floyd-Warshall-Algorithmus in Solidity geschrieben habe, der eine (nxn) Matrix von uints zuweist, sehe ich, dass der Gasverbrauch extrem schnell ansteigt. Dies ist sogar für n = 24 der Fall, wo der Gasverbrauch etwa 19085414 beträgt.
pragma solidity ^0.4.11;
contract APSPBenchmark is usingOraclize {
event OraclizeEvent0(string desc);
event OraclizeEvent1(string desc, int[] apsp);
int constant INF = -1;
function APSPBenchmark() public payable {}
/*
* Local all-pairs shortest path
*/
function localAPSP(int[] w) public {
int[] memory apsp = allPairsShortestPath(w);
OraclizeEvent0("local");
//OraclizeEvent1("local", apsp); // Infinity encoded as -1
}
/*
* All-pairs shortest path
*/
function allPairsShortestPath(int[] w) private constant returns(int[]) {
uint i; uint j; uint k;
uint n = babylonian(w.length);
int[] memory d = new int[](n * n);
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
d[i * n +j] = (w[i * n + j] >= 100 ? INF : w[i * n + j]);
}
d[i * n + i] = 0;
}
for (k = 0; k < n; ++k) {
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
if (d[i * n + k] == INF || d[k * n + j] == INF) continue;
else if (d[i * n + j] == INF) d[i * n + j] = d[i * n + k] + d[k * n + j];
else d[i * n + j] = min(d[i * n +j], d[i * n + k] + d[k * n + j]);
}
}
}
return d;
}
/*
* Minimum of two values
*/
function min(int a, int b) private constant returns(int) {
return a < b ? a : b;
}
/*
* Babylonian sqrt
*/
function babylonian(uint n) private constant returns(uint) {
uint x = n;
uint y = 1;
while (x > y) {
x = (x + y) / 2;
y = n / x;
}
return x;
}
}
Die Gaskosten der Speichererweiterung sind im Yellow Paper Anhang H wie folgt definiert:
G_memory ist 3 und a
ist die Anzahl der zugewiesenen 256-Bit-Worte ( int
s).
Für a=24^2 ergibt das 3 * 576 + 648 = 2.376. Es sieht also so aus, als ob die Speicherkosten nicht Ihr Hauptproblem sind.
Die Formel in dieser Antwort sind eigentlich nicht die Erweiterungskosten , sondern die Speicherkosten.
Die Erweiterungskosten sind die zusätzlichen Speicherkosten für die zuvor unberührten Speicherwörter. Siehe Solidity-Dokumentation und Zitat unten aus Anhang H im gelben Papier .
Beachten Sie auch, dass Cmem die Speicherkostenfunktion ist (die Erweiterungsfunktion ist die Differenz zwischen den Kosten davor und danach). Es handelt sich um ein Polynom, bei dem der Koeffizient höherer Ordnung geteilt und geglättet wird, und daher linear bis zu 724 B des verwendeten Speichers, danach kostet es wesentlich mehr.
(Nicht genug Repräsentant zum Kommentieren)
Benjaminion
INF
mit einer Konstante zu definieren:int constant INF = -1;
Ein Problem ist, dass der obige Code gespeichert wirdINF
. Jedes Mal, wenn Sie es im Körper verwenden, kostet das Auslesen aus dem Speicher 200 Gas. Durch die Deklaration wird diesconstant
vermieden.Shuzheng
Benjaminion
INF
, sparen Sie bis zu 600 Gas in Ihrem inneren Kreislauf (3 Ablesungen vonINF
). Ihre innere Schleife ist n ^ 3, also sparen Sie bei n = 24 bis zu 600 * 24 ^ 3 = 8,3 Millionen Gas. Das sollte helfen.Shuzheng
Shuzheng
Benjaminion
Shuzheng
Shuzheng
Benjaminion