Solidity
EVM 記憶體的成本如何擴展?
EVM 記憶體的成本如何擴展?
我想知道 EVM 記憶體(不是儲存)的成本如何擴展?
確實,在閱讀了其他 QA 之後,記憶體成本不是線性函式,而是應該隨著分配的更多而迅速增加?
在 Solidity 中編寫了 Floyd-Warshall 算法,該算法分配了一個 (nxn) 的 uint 矩陣,我發現氣體消耗增加得非常快。即使 n = 24 也是如此,其中氣體使用量約為 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; } }
記憶體擴展的gas成本在黃皮書 附錄H中定義如下,
G_memory 為 3,
a
是分配的 256 位字 (int
s) 的數量。對於 a=24^2,等於 3 * 576 + 648 = 2,376。所以看起來記憶體成本不是你的主要問題。
這個答案中的公式實際上不是擴展成本,而是記憶體成本。
擴展成本是先前未觸及的記憶體字的額外記憶體成本。請參閱Solidity 文件並在下面從黃皮書的附錄 H中引用。
另請注意,Cmem 是記憶體成本函式(擴展函式是之前和之後成本之間的差異)。它是一個多項式,對高階係數進行除法和取底,因此線性使用高達 724B 的記憶體,之後它的成本要高得多。
(沒有足夠的代表發表評論)