¿Cómo se escala el costo de la memoria EVM?
Me pregunto cómo se escala el costo de la memoria EVM (no el almacenamiento).
De hecho, después de haber leído otros controles de calidad, el costo de la memoria no es una función lineal, pero ¿debería aumentar rápidamente a medida que se asigna más?
Habiendo escrito el algoritmo de Floyd-Warshall en Solidity, que asigna una matriz (nxn) de uint, veo que el consumo de gas aumenta extremadamente rápido. Este es el caso incluso para n = 24, donde el uso de gas es de aproximadamente 19085414.
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;
}
}
El costo de gas de la expansión de la memoria se define en el Apéndice H del Libro Amarillo , de la siguiente manera,
G_memory es 3 y a
es el número de palabras de 256 bits int
asignadas.
Para a=24^2 esto llega a 3 * 576 + 648 = 2,376. Entonces parece que el costo de la memoria no es su principal problema.
La fórmula en esta respuesta en realidad no es el costo de expansión , es el costo de la memoria.
El costo de expansión es el costo de memoria adicional para las palabras de memoria previamente intactas. Consulte los documentos de Solidity y la cita a continuación del Apéndice H en el documento amarillo .
Tenga en cuenta también que Cmem es la función de costo de memoria (siendo la función de expansión la diferencia entre el costo antes y después). Es un polinomio, con el coeficiente de orden superior dividido y piso, y por lo tanto lineal hasta 724B de memoria utilizada, después de lo cual cuesta sustancialmente más.
(No hay suficiente representante para comentar)
benjaminion
INF
con constante:int constant INF = -1;
un problema es que el código anterior se estáINF
almacenando. Cada vez que lo usa en el cuerpo, leerlo desde el almacenamiento cuesta 200 de gas. Declararloconstant
evita esto.Shuzheng
benjaminion
INF
a constante le ahorrará hasta 600 de gas en su circuito interno (3 lecturas deINF
). Su bucle interno es n^3, por lo que para n=24 esto le ahorra hasta 600 * 24^3 = 8,3 millones de gasolina. Eso debería ayudar.Shuzheng
Shuzheng
benjaminion
Shuzheng
Shuzheng
benjaminion