This is a bit tricky.
The exercise that you did comparing the gas that each approach consumes is the way to go.
Usually, there's no need to make a copy of a
mapping value in memory. Reading and writing directly to it might be enough.
But sometimes, it may be useful to make a copy of the value in memory if we know that we will read/write to a
mapping multiple times, and maybe we just need to copy the value, do many operations on it and then write it just once to the mapping. Especially if we are using a loop.
Keep in mind that making a copy of a value in memory also costs gas, starting from 3 gas units. The total cost of the copy will depend on the size of the data you are copying. So, sometimes we may not get any benefit from making a copy of the data in
If you take a look at the opcodes and the gas they consume here, you will notice that
MSTORE (storing a value in memory) uses
3* gas to store data in memory. The
* means that it will depend on the size of the data being copied.
MLOAD (reading a value from memory) consumes the same
SLOAD uses 800 gas to read a word (32 bytes) from storage.
Also notice that
20000* to store values in storage, depending on the values to be saved, starting at 20000 units of gas.
If you need to inevitably read from a
mapping or storage x times and you have to inevitably write to a
mapping x more times, then think if you really need make a copy in memory on top of that, which you probably won't.
Don't make a copy of the data in
memory unless you need to and see that is beneficial. Because if making the copy in
memory is unnecessary, then you would be wasting resources because you would be reading/writing from and to storage and on top of that making an extra copy of the data in memory. Sometimes it will be useful, sometimes it won't.
Compare both approaches and you can select the one that uses less gas.
When using loops, check if you are modifying the same state variable multiple times and decide if you should better create a copy in
memory, modify the copy and then update the storage just once with the result.
Check all the EVM opcodes and the gas they consume here: https://github.com/crytic/evm-opcodes