首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何压缩数据以获得最便宜的存储读取?

如何压缩数据以获得最便宜的存储读取?
EN

Ethereum用户
提问于 2020-10-07 12:35:31
回答 1查看 209关注 0票数 1

Eth中气体成本的增加和存储操作成本的增加(参见eip 2929)引发了另一项研究,即寻找更廉价的方法将数据压缩到单个存储槽(32字节)中,同时优化更便宜的负载。

我将在下面的答案中分享我自己的实验,但仍在寻找更好的解决方案。所以这是我的一个悬而未决的问题。

EN

回答 1

Ethereum用户

发布于 2020-10-07 12:35:31

参见下面的代码实验,将4个数字压缩到一个槽(int16、int112、int16、int112)。这些功能所使用的技术和气体产生的结果是:

  1. solc编译器直接从存储区读取结构数据: 1306 gas。
  2. 汇编改为: 1346气体。
  3. 数据压缩/解压缩使用按位运算符(x,&):1296 gas。
  4. 与换档操作器(>>)相同,而不是div: 1258气体。

正如你所看到的,对于单个负载+数据转移,气体成本仍然远远不是单一负荷成本(目前EVM为800 gas )。

代码语言:javascript
运行
复制
contract CompressedData {

uint256 constant pow2_16 = 2 ** 16;
uint256 constant pow2_112 = 2 ** 112;
uint256 constant full112 = 2 ** 112 - 1;
uint256 constant full16 = 2 ** 16 - 1;

struct CompData {
    int16 x1;
    int112 y1;
    int16 x2;
    int112 y2;
}

mapping(uint => CompData) data;
mapping(uint => bytes32) decData;

constructor() public {
    data[0].x1 = 1;
    data[0].y1 = -1000;
    data[0].x2 = 2;
    data[0].y2 = -2000;

    decData[0] = encodeData(11, -10, 21, -20);

    decData[1] = encodeStepFunctionData(13, -13, 15, -15);
}


   
function getData (uint256 x) external view returns (int256, int256, int256, int256) {
    // gas result according to remix: 1306
        CompData storage pData = data[x];
        return(pData.x1, pData.y1, pData.x2, pData.y2);   
    }
 


function getDataMem (uint256 x) external view returns (int256, int256, int256, int256) {
    // gas result according to remix: 1681
    CompData memory _data = data[x];
    return(_data.x1, _data.y1, _data.x2, _data.y2);   
}
    
function encodeData(int256 x1, int256 x2, int256 x3, int256 x4) public pure returns(bytes32 result) {
    uint256 val;
    val = uint256(x1) & full16;
    val |= (uint256(x2) & full112) * pow2_16;
    val |= (uint256(x3) & full16) * pow2_16 * pow2_112;
    val |= (uint256(x4) & full112) * pow2_16 * pow2_112 * pow2_16;
    
    return(bytes32(val));
}

function getDecData(uint256 x) external view returns (int256 x1, int256 y1, int256 x2, int256 y2) {
// gas result according to remix: 1298
    uint256 val = uint256(decData[x]);
    x1 = int256(int16(val));
    y1 = int256(int112((val / pow2_16)));
    x2 = int256(int16(val / (pow2_16 * pow2_112)));
    y2 = int256(int112((val / (pow2_16 * pow2_112 * pow2_16))));
}

function getShiftDecData(uint256 x) external view returns (int256 x1, int256 y1, int256 x2, int256 y2) {
// gas result according to remix: 1258
    
    uint256 val = uint256(decData[x]);
    x1 = int256(int16(val));
    y1 = int256(int112((val >> 16)));
    x2 = int256(int16(val >> (16 + 112)));
    y2 = int256(int112((val >> (16 + 112 + 16))));
}

function getDecodedAsm() external view returns (uint112 x1, int16 y1, uint112 x2, int16 y2){
// gas result according to remix: 1346
    bytes memory tmp = abi.encodePacked(decData[1]); //assembly decoded data in slot 1
    assembly {
        x1 := mload(add(tmp, 14))
        y1 := mload(add(tmp, 16))
        x2 := mload(add(tmp, 30))
        y2 := mload(add(tmp, 32))
    }
}

function encodeStepFunctionData(uint112 x1, int16 y1, uint112 x2, int16 y2) public pure returns(bytes32 out) {
    bytes memory _data = abi.encodePacked(x1, y1, x2, y2);
    assembly {
        // skip 1 slot for data.length
        out := mload(add(_data, 32))
    }
}

}

票数 1
EN
页面原文内容由Ethereum提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://ethereum.stackexchange.com/questions/88131

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档