两个存储变量
让我们添加一个相同类型的额外存储变量:
// c2.sol
pragma solidity ^0.4.11;
contract C {
uint256 a;
uint256 b;
function C() {
a =1;
b =2;
}
}
编译,专注于tag_2:
$ solc --bin --asm c2.sol
// ... more stuff omitted
tag_2:
/* "c2.sol":99:100 1 */
0x1
/* "c2.sol":95:96 a */
0x0
/* "c2.sol":95:100 a = 1 */
dup2
swap1
sstore
pop
/* "c2.sol":112:113 2 */
0x2
/* "c2.sol":108:109 b */
0x1
/* "c2.sol":108:113 b = 2 */
dup2
swap1
sstore
pop
代码组装:
// a = 1
sstore(0x0,0x1)
// b = 2
sstore(0x1,0x2)
我们在这里学到的是两个存储变量一个接一个地定位,其中位置为0x0,b位于位置0x1。
存储打包
每个插槽存储可以存储32个字节。 如果变量只需要16个字节,那么使用全部32个字节会很浪费。 如果可能,通过将两个较小的数据类型打包到一个存储槽中,Solidity可以优化存储效率。
让我们改变a和b,使它们每个只有16个字节:
pragma solidity ^0.4.11;
contract C {
uint128 a;
uint128 b;
function C() {
a =1;
b =2;
}
}
编译合同:
$ solc --bin --asm c3.sol
生成的复杂程序集:
tag_2:
// a = 1
0x1
0x0
dup1
0x100
exp
dup2
sload
dup2
0xffffffffffffffffffffffffffffffff
mul
not
and
swap1
dup4
0xffffffffffffffffffffffffffffffff
and
mul
or
swap1
sstore
pop
// b = 2
0x2
0x0
0x10
0x100
exp
dup2
sload
dup2
0xffffffffffffffffffffffffffffffff
mul
not
and
swap1
dup4
0xffffffffffffffffffffffffffffffff
and
mul
or
swap1
sstore
pop
上面的汇编代码将这两个变量一起打包在一个存储位置(0x0),如下所示:
[ b ][ a ]
[16bytes /128bits][16bytes /128bits]
打包的原因是因为到目前为止最昂贵的操作是存储使用:
sstore首先写入新职位需要20000gas。
sstore为后续写入现有位置花费5000gas。
sload需要500gas。
大多数指令需要3到10种gas。
通过使用相同的存储位置,Solidity为第二个存储变量支付5000而不是20000,为我们节省了15000个gas。
1
领取专属 10元无门槛券
私享最新 技术干货