区块链研究实验室-深入了解Solidity如何在以太坊VM上运行-第三节

两个存储变量

让我们添加一个相同类型的额外存储变量:

// 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

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180806A08EWE00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动