0

I've read that:

It is more gas efficient to initialize a tightly packed struct with separate assignments instead of a single assignment. Separate assignments makes it easier for the optimizer to update all the variables at once.

So, they say:

this is better:

Point storage p = Point()
p.x = 0;
p.y = 0;

Than

Point storage p = Point(0, 0);

Any idea why ?

0

It has to do with addressing storage. Let's break it down.

Consider a bool and an address. The bool takes 1 byte (limitation of optimization) and the address takes 20 bytes. So we need 21 bytes of storage. The EVM uses 32-byte words which are the smallest chunk of storage that is addressable.

If you go

contract A {
  mapping(uint => bool) b;
  mapping(uint => address) a;
}

a and b values live in separate "slots" and you can be accessed them individually. For this to work, all of the storage in a "slot" needs to be allocated for one value, so there is leftover space and it is twice as expensive to store as:

contract A {

  struct Stuff {
    bool b;
    address a;
  }

  mapping(uint => Stuff) stuff;

Here, the compiler will look at the struct layout and work it out so one 32-byte word that holds 21-bytes of useful information. Of course, if you only want to update one member, then there is a read (to get the other) so the 32-byte write doesn't stomp on the other value.

Conceptually (not a technical explanation of the internals), something like this

Stuff storage s = Stuff[<uint>];
s.b = true;

makes the compiler

  1. compute the slot
  2. fetch the word
  3. replace the bool with true
  4. write the word

Tight packing is usually what you want because the total cost to write both a bool and an address is half of writing separate words. Words are the smallest unit of data for the expensive SSTORE opcode. So, yes, in a manner of speaking, structs help the compiler optimize the storage layout for gas cost.

Hope it helps.

1
  • Hi Rob, I might have missed your answer. I came across it today. I understand how things are stored in storage. What i don't understand is why initializing struct like this Point(0,0) is less optimized then Point() and then writing variables one by one ? can you show the compiler's look at those 2 difference examples ? Thank you – Nika Kurashvili Oct 3 '20 at 21:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.