티스토리 뷰

 

가스비를 계산하는데 뭔가 계속 이상했다.

 

 

https://realapril.tistory.com/112

 

Storing Structs is costing you gas

Storing Structs is costing you gas 라는 글을 보고 가스를 측정해 보았다. 2018년 글 wow 여러 시나리오가 테스트되어있다. 가스비가 그냥 state 여러개 저장 >>>construct > construct 내 변수 최적화>>+알파 ..

realapril.tistory.com

에 따르면

 

    struct A{
        address sideWallet1;
        address sideWallet2;
        address sideWallet3;
    }

    struct B {
        string cid;
    }

struct 하나를 저장할때 struct A가스비가 struct B 보다 비싸야한다고 생각했다.

이유는 address 는 하나당 20 바이트이므로 저장할 때 slot 3개를 사용하기때문이다. (1 slot = 32 바이트)

 

반면 내 cid 는 46바이트인데, 저장하는데 slot 2개가 필요하기 때문이다.

그런데 로그를 찍어보면 저장할때 소모되는 가스비가 거의 비슷했다.

 

왜..? 왜???

 

열심히 검색해본결과 "정상"이다.

 

https://ethereum.stackexchange.com/questions/107282/storage-and-memory-layout-of-strings

 

Storage and memory layout of strings

How exactly are strings stored in storage? And, how does that differ from the way they're stored in memory when loaded from storage into a memory variable?

ethereum.stackexchange.com

bytes and string are encoded identically. In general, the encoding is similar to bytes1[], in the sense that there is a slot for the array itself and a data area that is computed using a keccak256 hash of that slot’s position. However, for short values (shorter than 32 bytes) the array elements are stored together with the length in the same slot.

In particular: if the data is at most 31 bytes long, the elements are stored in the higher-order bytes (left aligned) and the lowest-order byte stores the value length * 2. For byte arrays that store data which is 32 or more bytes long, the main slot p stores length * 2 + 1 and the data is stored as usual in keccak256(p). This means that you can distinguish a short array from a long array by checking if the lowest bit is set: short (not set) and long (set).

So for example a string "abcd" will use the short format and take up a single slot with the upper four bytes being characters a, b, c, d and remaining bytes being zeros.

On the other hand "0123456789012345678901234567890123456789", which has more than 32 characters will take 3 slots. A single slot placed at the normal location between other storage variables will only contain the length (40) shifted left by one bit and will have the last bit set to indicate that it's the long format. I.e. its value will be 81. The other two slots will store the characters of the string (with unused space being filled with zeros) and the compiler will place them at a location computed by hashing the address of the slot containing length with keccak256().

 

 

예를 들어 문자열 "abcd"는 짧은 형식을 사용하고 상위 4바이트는 문자 a, b, c, d이고 나머지 바이트는 0인 단일 슬롯을 차지합니다.

반면 32자 이상인 "0123456789012345678901234567890123456789"는 3슬롯을 차지한다. 다른 저장 변수 사이의 일반 위치에 있는 단일 슬롯은 왼쪽으로 1비트 이동한 길이(40)만 포함하고 마지막 비트가 긴 형식임을 나타내기 위해 설정됩니다. 즉. 값은 81이 됩니다. 다른 두 슬롯은 문자열의 문자를 저장하고(사용하지 않은 공간은 0으로 채워짐) 컴파일러는 keccak256()으로 길이를 포함하는 슬롯의 주소를 해싱하여 계산된 위치에 배치합니다.

 

= 첫 슬롯은 길이(40글자 짜리다)와 긴 스트링 양식이다 라는 정보값만 저장하고, 나머지 2 슬롯에 실제 데이터가 나누어져서 저장된다.

 

 

또 더나아가서, string 을 불러올때는 메모리를 자주 사용한다. 근데,, 내가 생각하는것과 용량이 다르다.

In memory "abcd" will occupy two consecutive 32-byte slots. The first will store the length and the other the characters.

"0123456789012345678901234567890123456789" will occupy 3 consecutive slots with the first containing the length (40) and the other two storing the characters. There's no short/long format in memory so the length is not shifted like it would be in storage.

 
 
 
놀라운걸
 
 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함