Grunnleggende om Web3- og DApp-utvikling · leksjon

Optimalisering av lagring

Pakking og slots

Leksjon 2 av 413 trinn

Optimalisering av lagring er en gratis leksjon i Grunnleggende om Web3- og DApp-utvikling på CoddyKit. Dette er leksjon 2 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Grunnleggende om Web3- og DApp-utvikling, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Grunnleggende om Web3- og DApp-utvikling inneholder totalt 4 leksjoner.

Grunnleggende om lagringsslots

Kontraktlagring er en enorm matrise med 32-bytes slots, indeksert fra slot 0. Tilstandsvariabler tildeles slots i deklarasjonsrekkefølgen.

Hver slot du skriver til, koster gas. Jo færre slots dataene dine opptar, desto billigere er kontrakten å bruke. Å forstå slot-oppsettet er grunnlaget for å optimalisere lagring.

contract Layout {
    uint256 a; // slot 0
    uint256 b; // slot 1
    uint256 c; // slot 2
}

Pakking av variabler

Solidity-kompilatoren pakker flere små variabler inn i én enkelt 32-bytes slot når de passer sammen fortløpende.

En uint128 bruker 16 byte, så to slike deler én slot. En bool bruker 1 byte, og en uint8 bruker 1 byte. Pakking reduserer både lagringskostnadene ved utrulling og under kjøring.

contract Packed {
    uint128 a; // slot 0 (bytes 0-15)
    uint128 b; // slot 0 (bytes 16-31)
    uint256 c; // slot 1
}

Deklarasjonsrekkefølgen er viktig

Pakking fungerer bare for variabler som står ved siden av hverandre i deklarasjonen. Et dårlig ordnet oppsett sløser med slots.

I eksempelet nedenfor tvinger uint256 de to uint128-variablene inn i separate slots. Hvis du endrer rekkefølgen slik at de små typene står sammen, kan de pakkes.

// BAD: 3 slots
uint128 a; // slot 0
uint256 b; // slot 1
uint128 c; // slot 2

// GOOD: 2 slots
uint128 a; // slot 0
uint128 c; // slot 0
uint256 b; // slot 1

Velge heltallsstørrelser

Mindre heltall sparer bare gas når de pakkes. En frittstående uint8 i sin egen slot er ikke billigere enn en uint256, og kan til og med koste mer på grunn av maskeringsoperasjoner.

Tommelfingerregel: Bruk uint256 som standard, og reduser størrelsen bare når du kan få flere små verdier inn i én slot.

Pakking av strukturer

Strukturer følger de samme pakker reglene. Ordne strukturmedlemmene slik at små typer grupperes sammen. En godt pakket struktur kan redusere antallet SSTORE-operasjoner betydelig.

struct Order {
    uint128 amount;  // slot 0
    uint64 timestamp;// slot 0
    uint64 id;       // slot 0
    address maker;   // slot 1
}

Konstanter og uforanderlige verdier

Verdier som aldri endres, bør ikke ligge i lagring i det hele tatt.

  • constant — bygges direkte inn i bytekoden ved kompilering, uten lagring
  • immutable — settes én gang i konstruktøren og lagres i bytekoden, ikke i lagringen

Begge unngår kostbare SLOAD-operasjoner fullstendig.

uint256 public constant MAX_SUPPLY = 10000;
address public immutable owner;

constructor() {
    owner = msg.sender;
}

Mappinger og dynamiske matriser

Mappinger og dynamiske matriser pakkes ikke. Hver oppføring opptar sin egen slot, beregnet ved å hashe nøkkelen sammen med basissloten.

Du kan ikke pakke på tvers av mapping-oppføringer, men du kan pakke strukturen som lagres som mapping-verdi. Hvis du utformer verdistrukturen slik at den får plass i færre slots, sparer du gas ved hver skriving.

mapping(address => Order) public orders;
// each Order packs into 2 slots regardless of mapping

Mellomlagring av lagringslesinger

Hvis du leser en lagringsvariabel gjentatte ganger i en funksjon, betaler du for hver tilgang. Kopier den én gang til en lokal minnevariabel, og bruk deretter den lokale variabelen.

Dette er særlig nyttig i løkker, der hver iterasjon ellers ville lest lagringen på nytt.

uint256 len = items.length; // cache length once
for (uint256 i = 0; i < len; i++) {
    // process items[i]
}

Skriving i grupper

Når du oppdaterer flere felt i en pakket struktur, laster du strukturen inn i minnet, endrer den og skriver den deretter tilbake én gang. Kompilatoren kan slå sammen tilstøtende felt til én enkelt SSTORE.

Hvis du skriver feltene ett om gangen, kan det utløse flere les–endre–skriv-sykluser på den samme sloten.

Order memory o = orders[id];
o.amount = newAmount;
o.timestamp = uint64(block.timestamp);
orders[id] = o; // single packed write of slot 0

Straff ved null til ikke-null

Det koster 20000 gas å initialisere en slot fra null til en verdi som ikke er null, mens det bare koster 5000 gas å oppdatere en slot som allerede har en verdi som ikke er null.

Derfor forhåndsvarmer noen kontrakter slots eller bruker en vaktverdi (for eksempel 1 i stedet for 0) for å holde slots på en verdi som ikke er null. Slik byttes en engangskostnad mot billigere gjentatte oppdateringer.

// Using 1 as 'false' and 2 as 'true' keeps the slot non-zero
uint256 private locked = 1; // never goes back to 0

Sjekkliste for gjennomgang av oppsett

Ved gjennomgang av lagring med tanke på gas:

  • Gruppér små typer slik at de pakkes i delte slots
  • Bruk constant / immutable for faste verdier
  • Mellomlagre gjentatte lagringslesinger i minnet
  • Utfør struktur-skrivinger i grupper
  • Unngå unødvendige overganger fra null til ikke-null

Kontroller alltid endringene med en gasrapport.

Kort test

Du deklarerer en uint128, deretter en uint256 og så enda en uint128. Hvor mange lagringsslots bruker de?

Oppsummering

Du har lært å optimalisere lagringsoppsettet:

  • Lagring består av 32-bytes slots; tilstøtende små typer pakkes sammen
  • Deklarasjonsrekkefølgen avgjør pakkingen
  • constant og immutable unngår lagring fullstendig
  • Mellomlagre lesinger og utfør struktur-skrivinger i grupper
  • Ta hensyn til kostnaden ved skriving fra null til ikke-null

Deretter ser vi på optimalisering av løkker og håndtering av calldata.

Gratis å komme i gang

Lær deg Grunnleggende om Web3- og DApp-utvikling med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
29
Leksjoner
105

Ofte stilte spørsmål

Er leksjonen «Optimalisering av lagring» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Grunnleggende om Web3- og DApp-utvikling, inkludert «Optimalisering av lagring», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Grunnleggende om Web3- og DApp-utvikling inneholder totalt 4 leksjoner.

Hva lærer jeg i «Optimalisering av lagring»?

Pakking og slots Du øver på Grunnleggende om Web3- og DApp-utvikling med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Grunnleggende om Web3- og DApp-utvikling?

Ingen tidligere erfaring er nødvendig. Grunnleggende om Web3- og DApp-utvikling på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.

Hvor lang tid tar leksjonen «Optimalisering av lagring»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Grunnleggende om Web3- og DApp-utvikling-leksjonen?

Ja. Alle Grunnleggende om Web3- og DApp-utvikling-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Gas-kostnadsmodell
  2. Optimalisering av lagring
  3. Triks for løkker og calldata
  4. Måle gas
← Tilbake til Grunnleggende om Web3- og DApp-utvikling