零点课堂 | 如何编写智能合约,优化以太坊gas的消耗(2)

循环中昂贵的操作(Expensive operations in a loop)

由于昂贵的SLOAD和SSTORE操作码,管理存储中的变量比管理内存中的变量要昂贵得多。因此,不应在循环中使用存储变量。

uint num = 0;

function expensiveLoop(uint x) public {
for(uint i = 0; i < x; i++) {
num += 1;
}
}

该模式的解决方法是创建一个代表全局变量的临时变量,并在循环完成后,将临时变量的值重新分配给全局变量。

uint num = 0;

function lessExpensiveLoop(uint x) public {
uint temp = num;
for(uint i = 0; i < x; i++) {
temp += 1;
}
num = temp;
}

循环的持续结果(Constant ouTCOme of a loop)

如果循环的结果是可以在编译期间推断的常数,则不应使用它。

function constantOutcome() public pure returns(uint) {
uint num = 0;
for(uint i = 0; i < 100; i++) {
num += 1;
}
return num;
}

循环融合(Loop fusion)

有时在智能合约中,您可能会发现有两个具有相同参数的循环。 在循环参数相同的情况下,没有理由使用单独的循环。

function loopFusion(uint x, uint y) public pure returns(uint) {
for(uint i = 0; i < 100; i++) {
x += 1;
}
for(uint i = 0; i < 100; i++) {
y += 1;
}
return x + y;
}

循环重复计算

如果循环中的表达式在每次迭代中产生相同的结果,则可以将其移出循环。当表达式中使用的变量存储在存储器中时,这一点尤其重要。

uint a = 4;
uint b = 5;
function repeatedComputations(uint x) public returns(uint) {
uint sum = 0;
for(uint i = 0; i <= x; i++) {
sum = sum + a * b;
}
}

与单侧循环结果的比较

如果在循环的每个迭代中执行比较但每次的结果都相同,则应将其从循环中删除。

function unilateralOutcome(uint x) public returns(uint) {
uint sum = 0;
for(uint i = 0; i <= 100; i++) {
if(x > 1) {
sum += 1;
}
}
return sum;
}

本文由 零点财经 作者:tao 发表,其版权均为 零点财经 所有,文章内容系作者个人观点,不代表 零点财经 对观点赞同或支持。如需转载,请注明文章来源。
分享生成图片
56

发表回复

零点课堂 | 如何编写智能合约,优化以太坊gas的消耗(2)

2021-06-03 11:15:39

循环中昂贵的操作(Expensive operations in a loop)

由于昂贵的SLOAD和SSTORE操作码,管理存储中的变量比管理内存中的变量要昂贵得多。因此,不应在循环中使用存储变量。

uint num = 0;

function expensiveLoop(uint x) public {
for(uint i = 0; i < x; i++) {
num += 1;
}
}

该模式的解决方法是创建一个代表全局变量的临时变量,并在循环完成后,将临时变量的值重新分配给全局变量。

uint num = 0;

function lessExpensiveLoop(uint x) public {
uint temp = num;
for(uint i = 0; i < x; i++) {
temp += 1;
}
num = temp;
}

循环的持续结果(Constant ouTCOme of a loop)

如果循环的结果是可以在编译期间推断的常数,则不应使用它。

function constantOutcome() public pure returns(uint) {
uint num = 0;
for(uint i = 0; i < 100; i++) {
num += 1;
}
return num;
}

循环融合(Loop fusion)

有时在智能合约中,您可能会发现有两个具有相同参数的循环。 在循环参数相同的情况下,没有理由使用单独的循环。

function loopFusion(uint x, uint y) public pure returns(uint) {
for(uint i = 0; i < 100; i++) {
x += 1;
}
for(uint i = 0; i < 100; i++) {
y += 1;
}
return x + y;
}

循环重复计算

如果循环中的表达式在每次迭代中产生相同的结果,则可以将其移出循环。当表达式中使用的变量存储在存储器中时,这一点尤其重要。

uint a = 4;
uint b = 5;
function repeatedComputations(uint x) public returns(uint) {
uint sum = 0;
for(uint i = 0; i <= x; i++) {
sum = sum + a * b;
}
}

与单侧循环结果的比较

如果在循环的每个迭代中执行比较但每次的结果都相同,则应将其从循环中删除。

function unilateralOutcome(uint x) public returns(uint) {
uint sum = 0;
for(uint i = 0; i <= 100; i++) {
if(x > 1) {
sum += 1;
}
}
return sum;
}