http://www.7klian.com

Gas 优化 如何优化存储

    strength = uint256(uint16(character>>208));
uint16 class;
    owner = address(character);
    _character.dna = dnaRecords[_id];
[4]Cell Network: https://www.cellnetwork.io/?utm_souce=learnblockchain
[2]Tiny熊: https://learnblockchain.cn/people/15
function setCharacter(uint256 _id, address owner, uint256 creationTime, uint256 strength, uint256 race, uint256 class, uint256 dna) 
    _character.creationTime = uint256(uint40(character>>160));
    uint256 character = characters[_id];
这是按位或赋值运算符。用来组合两个二进制值(我们在计较机上,所以一切都是二进制的),要领是“假如个中任一位为1,则功效中的该位为1”。我们可以在这里利用它,因为我们以uint256(address)开头,这意味着我们知道在位160之上的所有位均为0。
    uint256 character = uint256(owner);
mapping(uint256 => uint256) dnaRecords;
  uint256 dna;
变量归并
}
{
    character |= creationTime<<160;
  uint256 race;
    dna = dnaRecords[_id];
}
    character |= race<<224;
此刻你已经有了数据存储,你大概需要在函数之间通报数据。除非你的应用措施像这里描写的那样简朴,不然你将碰着16个局部变量的仓库限制。因此,你需要将数据作为布局体通报到内存中。此布局体看起来与之前显示的布局略有差异:
利用数据
我们确实在1980年月早期编写了一个兔子洞编程-对数据举办编码,需要存眷我们可以从代码中抽出的每一个小优化。编写Solidity差异于编写现代语言,这是一种差异的”物种” – 以太坊区块链的限制意味着你正在有效地为成果不如1973 Apple 1 。
    race = uint256(uint16(character>>224));
struct GameCharacter {
uint16 strength;
returns(address owner, uint256 creationTime, uint256 strength, uint256 race, uint256 class, uint256 dna) {
    external view
    _character.race = uint256(uint16(character>>224));
mapping(uint256 => GameCharacter) characters;
address owner;
    creationTime = uint256(uint40(character>>160));
这是左移位运算符。它取一个数字的位,然后将它们向左移动。因此,creationTime<<160 并将creationTime移至功效代码中的插槽160–207中。将移位和按位或赋值运算相团结,就可以构建编码。
  uint16 strength;
mapping(uint256 => address) owners;
新代码的耗费:60,000 gas!我们在此处举办了两项变动:首先,将dna移至末端。它是一个uint256,已经是32个字节,因此不能包括任何其他的内容。然后,我们将 creationTime 的范例从uint64 变动为uint48。这使前五个字段全部打包成32个字节。时间戳记不必高出uint48 类,并且Solidity(与其他大大都语言差异)答允uint为8的任意倍数,而不只仅是8/16/32/64等(假如你急切地需要空间,, 你可以将时间戳利用uint32,在2106年它大概导致问题之前,你大概已经死了 :) 。
将数据存储为 uint256 只会耗费40,000多gas — 仅举办两次存储操纵,再加上一些移位和按位或运算。思量到我们最初为120,000gas,这是一个很大的进步!利用此要领检索数据也要自制一些。请留意,这两个函数不会执行任何错误查抄-你需要本身执行此操纵,以确保所有输入的最终值都不会高出其最大值(但你必需在所有这些实现中举办沟通的查抄)。
  uint256 strength;
}
mapping(uint256 => uint16) class;
大大都dApp和游戏都需要将数据存储在上,因此必需与存储举办交互。优化智能合约的gas本钱是一项重要的事情。
|=
    _character.owner = address(character);
这是右移位运算符。它的事情方法与<<雷同,但偏向相反。我们可以利用此要领从编码数据转换返来。可是,我们还需要:
此刻,当我们存储此布局体时,我们付出的用度更少:75000 gas 。编译器会将 owner 和creationTime 巧妙地打包到同一插槽中,因此耗费25,000,而不是40,000 (译者注,因为第2个写值被当做更新)。同样结果却更少的耗费,不外,我们可以做得更好:
每一点细微的优化城市辅佐你实现更有效的存储要领, 来为你和你的用户节减一些gas。
    _character.class = uint256(uint16(character>>240));
    external view
function getCharacter(uint256 _id) 
这是一个简朴的区块链游戏大概存储的数据:
uint64 creationTime;
假如我们只是直接存储这些值,则大概需要执行以下操纵:
[1]登链翻译打算: https://github.com/lbc-team/Pioneer
    characters[_id] = character;
  uint256 class;
>>
  uint256 creationTime;
编码与解码
function getCharacterStruct(uint256 _id) 
uint256 dna;
<<
    character |= strength<<208;
    character |= class<<240;
在Solidity[3](用于智能合约的编程语言)中,你拥有“内存(memory)”(想像计较机上的RAM)和“存储(storage)”(想像硬盘驱动器)。两者均以32字节的块为操纵单元(一个字节省莫是一个字母)。在Solidity 中,内存价值自制(存储或更新值仅需要 3 gas)。存储很昂贵(存储新的值需要20,000 gas,更新值需要 5000 gas)。
  uint64 creationTime;
mapping(uint256 => GameCharacter) characters;
所有字段均为uint256。这是 solidity 中最有效的数据范例。内存中的变量(甚至是布局体)基础没有打包,因此在内存中利用uint16不会得到任何长处,并且由于solidity必需执行特另外操纵才气将uint16转换为uint256举办计较,所以你也许会迷失偏向。
struct GameCharacter {
  uint256 dna;
参考资料
    class = uint256(uint16(character>>240));
  uint16 race;
[5]Nova Blitz: https://medium.com/@novablitz

}
总结
uint16 race;
mapping(uint256 => uint64) creationTime;
[3]Solidity: https://learnblockchain.cn/docs/solidity/
  address owner;

我们会很快进入一些很是技能性的Solidity观念。
    external 
存储这些数据需要耗费120,000 gas(12万),这确实很是昂贵!当我们结构一个布局体并将其存储时,我们会获得更好的功效:
利用这些技能,我们可以明显提高智能合约的机能。
这操作了solidity编译器的成果。假如将uint256转换为uint48,则会扬弃所有高于位 48 的位。这对付我们的目标而言是完美的,因为我们知道 creationTime 的长度为48位,因此仅提取所需的数据。
  uint16 strength;
  uint16 race;
mapping(uint256 => uint16) strength;
  uint256 dna;
    dnaRecords[_id] = dna;
uint256(uint48())
  uint16 class;
mapping(uint256 => uint256) characters;
我们将用度减半了 — 很好,对吧?好吧,不 — 我们但愿所有成果的 gas 耗损都尽大概小,而且仍可以通过将前5个数据字段编码为单个 uint256 来低落本钱:
  address owner;
  address owner;
returns(GameCharacter memory _character) {
mapping(uint256 => uint16) race;
上面的代码中大概有一些字符让你感受生疏。让我们来一探毕竟:
    uint256 character = characters[_id];
    _character.strength = uint256(uint16(character>>208));
  uint48 creationTime;
}
  uint16 class;
mapping(uint256 => uint256) dna;
struct GameCharacter {
}

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

相关文章阅读