함수에서 스토리지 액세스 방지 - 2

이 게시물은 메모리에서 데이터를 참조하여 가스를 절약하는 마지막 게시물에서 계속됩니다. 이제 우리는 이것이 모순될 수 있는 경우를 보게 될 것입니다.

다음 계약을 고려하십시오.

contract varReferencing_1{
    uint[] public arr;
    uint public arrLength;

    function addItem(uint _item) external {
        arrLength = arrLength + 1; // updating state

        arr.push(_item); // adding element

        for (uint i; i < arrLength; i++) {
            arr[i] = arrLength + i; // updating state
        }
    }
}


contract varReferencing_2{
    uint[] public arr;
    uint public arrLength;

    function addItem(uint _item) external {
        uint _arrLength = arrLength + 1; // storing into memory

        arr.push(_item); // adding element
        uint[] memory _arr = arr; // storing into memory

        for (uint i; i < _arrLength; i++) {
            _arr[i] = _arrLength + i;
        }

        arr = _arr; // updating state
        arrLength = _arrLength; // updating state
    }
}


contract varReferencing_3{
    uint[] public arr;
    uint public arrLength;

    function addItem(uint _item) external {
        uint _arrLength = arrLength + 1; // storing into memory

        arr.push(_item); // adding element

        for (uint i; i < _arrLength; i++) {
            arr[i] = _arrLength + i;
        }

        arrLength = _arrLength; // updating state
    }
}


세 계약 모두 새 요소를 배열에 푸시하고 새 배열 길이로 모든 요소의 인덱스를 합산하고 배열에서 업데이트하는 기능이 완전히 동일합니다. (참고: 이 기능은 실제로 사용되지 않으며 단지 예일 뿐입니다.)

차이점과 각 계약에 사용된 가스를 살펴보겠습니다.

varReferencing_1addItem는 상태 변수arrLength를 1씩 증가시키고 새 요소_item를 상태 변수 배열arr로 푸시하며 각 배열 요소를 새 길이 + 인덱스로 업데이트합니다.



varReferencing_2addItem는 상태 변수_arrLength의 복사본을 1씩 늘리고 새 요소_item를 상태 변수 배열arr에 푸시하고 메모리에 복사본을 만듭니다. 그런 다음 이러한 복사본을 사용하여 추가 작업을 수행한 다음 원래 상태 변수에 할당합니다.



varReferencing_3addItemarrLength 상태 변수를 메모리에 복사하지만 arr는 복사하지 않습니다. 나머지 작업은 동일합니다.



결론



varReferencing_2는 두 상태 변수의 복사본을 만들기 때문에 가장 가스 효율적일 것으로 예상되었지만 가장 비쌌습니다. 이는 아마도 저장소에서 메모리로 복사arr한 다음 모든 작업 후 다시 저장소로 복사했기 때문일 것입니다.
varReferencing_3에서 우리는 방금 copy or arrLength를 만들었고 그것이 가장 가스 효율적인 방법으로 판명되었습니다.

좋은 웹페이지 즐겨찾기