最近做一個(gè)項(xiàng)目谁撼,發(fā)現(xiàn)solidity的代碼對(duì)性能影響非常大柿究,這里把每個(gè)版本的代碼做了比較
1. 第一個(gè)版本摊鸡,使用string操作
function KVStoragePut(string key, string value) public whenNotPaused onlyUser returns(uint256[1] p) {
bytes32[] memory keyBytes = StrToBytes32Array(key);
uint256 keyLen = keyBytes.length;
bytes32[] memory valueBytes = StrToBytes32Array(value);
uint256 valueLen = valueBytes.length;
uint256[] memory input = new uint256[](1 + keyLen + 1 + valueLen + 1);
input[0] = keyLen;
for(uint256 i=0;i<keyLen;i++) {
input[i+1] = (uint256)(keyBytes[i]);
}
input[1 + keyLen] = valueLen;
for(i=0;i<valueLen;i++) {
input[i+2+keyLen] = (uint256)(valueBytes[i]);
}
uint256 len = (1 + keyLen + 1 + valueLen + 1) * 32;
assembly {
// call KVStoragePut precompile
if iszero(call(not(0), 0x0a, 0, input, len, p, 0x20)) {
revert(0, 0)
}
}
}
function StrToBytes32Array(string p_str) internal pure returns(bytes32[]){
bytes memory lbts_para; //the result of convert p_str to bytes
uint li_paralength; //lbts_para's length
string memory ls_new; //the result of convert ont bytes32 to string
bytes32 lbt_row; // the new bytes32 data
bytes32[] memory lbt_result32; //the return bytes32 array
uint li_rowcount; // bytes32 array's length
uint li_temp;
uint li_sum; //the total byte32 array's bytes amount
uint li_colidx; //the new column's index
uint li_resultlength ; // the result bytes32 array's length
lbts_para = bytes(p_str); //ex:'1234' = 0x31323334
li_paralength = lbts_para.length; //ex: 4
bytes memory lbts_new = new bytes(32); //for store to arrays32 array
// lbt_result32.length=0; //ininial the array32 array
if (li_paralength <= 32 ){ //if actul data length is less equal than 32,use assemble method
assembly {
lbt_row := mload(add(p_str, 32))
}
// lbt_result32.length = 1;
lbt_result32 = new bytes32[](1);
lbt_result32[0] = lbt_row;
} else {
//li_rowcount :calculate the bytes32 array's length
li_rowcount = li_paralength/32;
li_temp = li_paralength%32;
if (li_temp > 0 )
li_rowcount = li_rowcount +1;
//li_sum :the total bytes amount of bytes32 array
lbt_result32 = new bytes32[](li_rowcount);
li_sum = li_rowcount *32;
li_colidx = 0;
for (uint p = 1;p<= li_sum;p++){
//decide whether to add a new row
li_temp = p%32; //if equal 0,add a new row
if (li_temp == 0 ){
if (p > li_paralength)
lbts_new[li_colidx] = 0x0;
else
lbts_new[li_colidx] = lbts_para[p - 1];
li_colidx = 0;
ls_new = string(lbts_new);
assembly {
lbt_row := mload(add(ls_new, 32))
}
// li_resultlength = lbt_result32.length ;
li_resultlength = li_resultlength +1;
// lbt_result32.length = li_resultlength;
lbt_result32[li_resultlength - 1] = lbt_row;
}else {
if (p > li_paralength)
lbts_new[li_colidx] = 0x0;
else
lbts_new[li_colidx] = lbts_para[p - 1];
li_colidx = li_colidx +1;
}
}
}
return lbt_result32;
}
2. 第二個(gè)版本渗饮,使用bytes操作
function KVStoragePut(bytes key, bytes value) public whenNotPaused onlyUser returns(uint256[1] p) {
bytes32[] memory keyBytes = StrToBytes32Array(key);
uint256 keyLen = keyBytes.length;
bytes32[] memory valueBytes = StrToBytes32Array(value);
uint256 valueLen = valueBytes.length;
uint256[] memory input = new uint256[](1 + keyLen + 1 + valueLen + 1);
input[0] = newKey.length;
for(uint256 i=0;i<keyLen;i++) {
input[i+1] = (uint256)(keyBytes[i]);
}
input[1 + keyLen] = value.length;
for(i=0;i<valueLen;i++) {
input[i+2+keyLen] = (uint256)(valueBytes[i]);
}
uint256 len = (1 + keyLen + 1 + valueLen + 1) * 32;
assembly {
// call KVStoragePut precompile
if iszero(call(not(0), 0x0a, 0, input, len, p, 0x20)) {
revert(0, 0)
}
}
}
function StrToBytes32Array(bytes lbts_para) internal pure returns(bytes32[]){
// bytes memory lbts_para; //the result of convert p_str to bytes
uint li_paralength; //lbts_para's length
string memory ls_new; //the result of convert ont bytes32 to string
bytes32 lbt_row; // the new bytes32 data
bytes32[] memory lbt_result32; //the return bytes32 array
uint li_rowcount; // bytes32 array's length
uint li_temp;
uint li_sum; //the total byte32 array's bytes amount
uint li_colidx; //the new column's index
uint li_resultlength ; // the result bytes32 array's length
// lbts_para = bytes(p_str); //ex:'1234' = 0x31323334
li_paralength = lbts_para.length; //ex: 4
bytes memory lbts_new = new bytes(32); //for store to arrays32 array
// lbt_result32.length=0; //ininial the array32 array
if (li_paralength <= 32 ){ //if actul data length is less equal than 32,use assemble method
assembly {
lbt_row := mload(add(lbts_para, 32))
}
// lbt_result32.length = 1;
lbt_result32 = new bytes32[](1);
lbt_result32[0] = lbt_row;
} else {
//li_rowcount :calculate the bytes32 array's length
li_rowcount = li_paralength/32;
li_temp = li_paralength%32;
if (li_temp > 0 )
li_rowcount = li_rowcount +1;
//li_sum :the total bytes amount of bytes32 array
lbt_result32 = new bytes32[](li_rowcount);
li_sum = li_rowcount *32;
li_colidx = 0;
for (uint p = 1;p<= li_sum;p++){
//decide whether to add a new row
li_temp = p%32; //if equal 0,add a new row
if (li_temp == 0 ){
if (p > li_paralength)
lbts_new[li_colidx] = 0x0;
else
lbts_new[li_colidx] = lbts_para[p - 1];
li_colidx = 0;
ls_new = string(lbts_new);
assembly {
lbt_row := mload(add(ls_new, 32))
}
// li_resultlength = lbt_result32.length ;
li_resultlength = li_resultlength +1;
// lbt_result32.length = li_resultlength;
lbt_result32[li_resultlength - 1] = lbt_row;
}else {
if (p > li_paralength)
lbts_new[li_colidx] = 0x0;
else
lbts_new[li_colidx] = lbts_para[p - 1];
li_colidx = li_colidx +1;
}
}
}
return lbt_result32;
}
3. 第三個(gè)版本,使用abi.encodePacked 處理bytes
function KVStoragePut(bytes key, bytes value) public whenNotPaused onlyUser returns(uint256[1] p) {
bytes memory input = abi.encodePacked((int8)(key.length),key,(int8)(value.length),value);
uint256 len = input.length + 32;
assembly {
// call KVStoragePut precompile
if iszero(call(not(0), 0x0a, 0, input, len, p, 0x20)) {
revert(0, 0)
}
}
}
性能對(duì)比呆抑,執(zhí)行1000次耗時(shí):
版本 | 方法 | 耗時(shí)(ms) |
---|---|---|
1 | string | 3650 |
2 | bytes | 2478 |
3 | abi | 232 |