Разница между неоптимизированным и оптимизированным кодом солидности

Я пытаюсь найти источник того, в чем разница между оптимизированным и неоптимизированным кодом. Мой главный вопрос заключается в том, что делает неоптимизированный компилятор, особенно в смысле вызова SSTOREопкода.

Допустим, у меня есть это:

contract A{
    uint8 mem1;
    uint8 mem2;

    function store(uint8 store1, uint8 store2){
        mem1=store1;
        mem2=store2;
    }
}

Когда я скомпилировал это «тупым» способом, я SSTOREдважды вызывал, чтобы сохранить обе переменные. Однако, чтобы оптимизировать это, я бы выделил первые 8 битов uint256( SSTOREвсегда хранит uint256) для , mem1а вторые 8 бит - для mem2. Таким образом, мне нужно позвонить SSTOREтолько один раз за транзакцию. Однако это может привести к небольшим накладным расходам в другом коде, который может иметь контракт, поскольку нам нужно извлечь правильные биты. SSTOREпотребляет 20 тыс. газа при сохранении ненулевого значения, поэтому оптимизация этого кода экономит 20 тыс. газа.

Вызывает ли неоптимизированный компилятор при компиляции кода SSTOREдважды или один раз? Я знаю, что могу проверить это сам, скомпилировав и прочитав файл OPCODES, но я хотел бы найти источник того, что должны делать оба компилятора.

Самостоятельная проверка кажется самым простым вариантом, но вы также можете прочитать исходный код компилятора. (Ищите «оптимизатор».) Я не думаю, что оптимизация особенно хорошо документирована.
Хорошо, грустно слышать, что оптимизация плохо документирована, поскольку сейчас трудно понять, нужно ли вам создавать «хакерские» способы хранения для экономии газа или оптимизатор делает это за вас.
Это очень интересный вопрос. Неоптимизированный компилятор будет генерировать код с 1xSLOAD и 2xSSTORE. Однако(!), чего я не ожидал, стоимость газа по-прежнему составляет всего 21000 + 26442 (гет 1.7.2). Я ожидал увидеть что-то вроде 21000+200+40000+X. Чем это можно объяснить? Получается, если мы пишем на один и тот же адрес два раза, то второй стоит всего 5000?
Просто чтобы убедиться, что вы не сохраняете ноль во второй раз? 5k - это газ, используемый для хранения нуля.
Неа. Я использовал ваш код с параметрами 1,2.
Это не имеет смысла. В документации, которую я читал, SSTORE берет 20 тысяч газа за каждый вызов. Может быть, 21 КБ для каждой транзакции, устанавливающей баланс (20 КБ) и процесс (1 КБ?), Так что эти «потерянные» 20 КБ на самом деле находятся в этих «21 КБ»?

Ответы (1)

Вызывает ли неоптимизированный компилятор при компиляции приведенного выше кода SSTORE дважды или один раз?

Да, неоптимизированный код вызовет SSTORE дважды. Однако второй SSTORE в том же слоте хранилища будет стоить всего 5000 газа, поскольку он только сбрасывает значение в существующем слоте. (См. « Отличается ли стоимость обновления хранилища от стоимости добавления к хранилищу? »)

Оптимизированный код будет иметь только один SSTORE.

Насколько я знаю, нет документа, точно описывающего, что делает оптимизатор. Я думаю, для этого вам нужно просмотреть код и журналы изменений.

Я не знал, что обновление стоит меньше. Означает ли обновление «выделенное пространство» или обновление источников, находящихся в настоящее время в памяти? Я вижу много ссылок на Желтую книгу и прочитаю ее, спасибо.
Это означает: для «выделенного пространства». Set -> вы создаете новый узел в хранилище. Re-set -> вы меняете значение существующего узла trie. Обнуление -> вы удаляете узлы из хранилища, что вознаграждается возвратом 15 000 газа.