Grunderna i Web3- och DApp-utveckling · Lektion

Loop- och calldata-trick

Billigare operationer

Lektion 3 av 413 steg

Loop- och calldata-trick är en gratis lektion i Grunderna i Web3- och DApp-utveckling på CoddyKit. Detta är lektion 3 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Grunderna i Web3- och DApp-utveckling, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Grunderna i Web3- och DApp-utveckling innehåller totalt 4 lektioner.

Loopar multiplicerar kostnaden

Loopar är riskabla med avseende på gas, eftersom varje operation inuti körs en gång per iteration. Ett enda dyrt anrop i en loop kan överskrida Er gasbudget eller nå blockets gasgräns.

Målet är att flytta så mycket arbete som möjligt utanför loopen och göra varje iteration så billig som möjligt.

Cacha längden

Att läsa array.length i en lagringsarray kostar en SLOAD varje gång loopvillkoret kontrolleras. Cacha längden i en lokal variabel innan loopen.

// BAD: SLOAD on every iteration
for (uint256 i = 0; i < items.length; i++) { }

// GOOD: one SLOAD
uint256 len = items.length;
for (uint256 i = 0; i < len; i++) { }

Undvik lagring i loopar

Läs aldrig från eller skriv till samma lagringsslot upprepade gånger i en loop. Ackumulera i en lokal variabel och skriv resultatet en gång efter att loopen har avslutats.

// GOOD: single storage write after the loop
uint256 total = 0;
for (uint256 i = 0; i < len; i++) {
    total += amounts[i];
}
balance = total; // one SSTORE

Okontrollerad inkrementering

Sedan Solidity 0.8 har aritmetik inbyggda overflow-kontroller som kostar extra gas. En loopräknare som realistiskt sett aldrig kan orsaka overflow kan inkrementeras i ett unchecked-block.

for (uint256 i = 0; i < len;) {
    // loop body
    unchecked { ++i; }
}

Preinkrementering framför postinkrementering

++i är marginellt billigare än i++, eftersom postinkrementering måste skapa en tillfällig kopia av det gamla värdet. Besparingen per operation är liten, men den ackumuleras över många iterationer.

Föredra ++i för loopräknare när returvärdet inte används.

for (uint256 i = 0; i < len; ++i) {
    // ++i avoids a temporary copy
}

Calldata framför memory

För externa funktioner undviker ni att kopiera data till minnet genom att deklarera array- och struct-parametrar som calldata i stället för memory. Calldata är skrivskyddad och billigare att läsa.

// Cheaper: no memory copy
function process(uint256[] calldata data) external {
    for (uint256 i = 0; i < data.length; ++i) { }
}

Minska calldata

Varje calldata-byte som inte är noll kostar 16 gas. Mindre nyttolaster innebär billigare transaktioner. Tekniker omfattar:

  • Packa flera värden i en uint256
  • Använd mindre typer när ABI:t tillåter det
  • Skicka index i stället för fullständiga structs när datan redan finns on-chain

Kortslutande villkor

De logiska operatorerna && och || kortsluter: det andra operandet utvärderas bara vid behov. Ordna villkoren så att den billigaste eller mest sannolikt avgörande kontrollen kommer först.

// Check the cheap flag before the expensive storage read
if (isEnabled && expensiveStorageCheck()) {
    // ...
}

Undvik överflödiga läsningar

Om ni läser samma calldata- eller minneselement flera gånger i loopens kodblock bör ni cacha det i en lokal variabel. Även om åtkomst till calldata är billigare än åtkomst till lagring ackumuleras kostnaden vid upprepade läsningar.

for (uint256 i = 0; i < len; ++i) {
    uint256 v = data[i]; // read once
    total += v;
    if (v > max) max = v;
}

Begränsa looparna

Obegränsade loopar över användarkontrollerade arrayer kan överskrida blockets gasgräns och göra funktionen permanent oanropbar, vilket innebär en risk för denial of service.

Begränsa alltid antalet iterationer eller använd ett pull-baserat mönster där användarna behandlar sina egna poster, så att varje transaktion håller sig inom säkra gasgränser.

require(ids.length <= 100, "too many");
for (uint256 i = 0; i < ids.length; ++i) { }

Sätt ihop delarna

En optimerad loop brukar cacha längden, ackumulera i lokala variabler, använda indata i calldata, inkrementera med unchecked { ++i; } och vara begränsad.

Varje teknik ger en liten besparing var för sig, men tillsammans kan de minska loopens gasförbrukning avsevärt.

function batch(uint256[] calldata vals) external {
    uint256 len = vals.length;
    uint256 total;
    for (uint256 i = 0; i < len;) {
        total += vals[i];
        unchecked { ++i; }
    }
    sum = total;
}

Snabb kontroll

Varför är det billigare att använda calldata i stället för memory för en extern funktions arrayparameter?

Sammanfattning

Ni har lärt er gasoptimeringstekniker för loopar och calldata:

  • Cacha arrayens längd innan loopen
  • Ackumulera i lokala variabler och skriv till lagring en gång
  • Använd unchecked { ++i; } för säkra räknare
  • Föredra parametrar i calldata och minska nyttolaster
  • Begränsa alltid loopar för att undvika DoS på grund av gasgränsen

Därefter mäter vi dessa förbättringar med profileringsverktyg.

Gratis att börja

Lär dig Grunderna i Web3- och DApp-utveckling med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
29
Lektioner
105

Vanliga frågor

Är lektionen ”Loop- och calldata-trick” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Grunderna i Web3- och DApp-utveckling, inklusive ”Loop- och calldata-trick”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Grunderna i Web3- och DApp-utveckling innehåller totalt 4 lektioner.

Vad lär jag mig i ”Loop- och calldata-trick”?

Billigare operationer Ni övar på Grunderna i Web3- och DApp-utveckling med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Grunderna i Web3- och DApp-utveckling?

Du behöver inga förkunskaper. Utbildningen i Grunderna i Web3- och DApp-utveckling på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 4.

Hur lång tid tar lektionen ”Loop- och calldata-trick”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Grunderna i Web3- och DApp-utveckling-lektionen?

Ja. Varje Grunderna i Web3- och DApp-utveckling-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Modell för gaskostnader
  2. Lagringsoptimering
  3. Loop- och calldata-trick
  4. Mäta gas
← Tillbaka till Grunderna i Web3- och DApp-utveckling