Kodingizni yaxshilash va gas sarfini kamaytirish bo‘yicha Solidity maslahatlariga duch kelgan bo‘lishingiz mumkin. Ammo bugun Ethereum Virtual Mashinasi qanday ishlashini tushunish smart-kontraktlaringizdagi gas xarajatlarini qanday samarali kamaytirishiga ko‘proq e’tibor qaratmoqchiman.
Ethereum’ga chuqurroq kirishmoqchi ekanmiz, bu yerda opkodlarning gas xarajatlarini belgilovchi Yellow Paper’dan parchani keltiraman. Maqola davomida ularga murojaat qilamiz.
1-maslahat: Sovuq murojaat va iliq murojaat
Gcoldsload: 2100 gas
Gwarmaccess: 100 gas
Bu yerda dastlabki OPCODElarimiz keltirilgan: birinchisi o‘zgaruvchiga birinchi marta (yoki sovuq kirishda) murojaat qilish narxini, ikkinchisi esa o‘zgaruvchiga ikkinchi va undan keyingi murojaatlarning (iliq kirish) narxini ko‘rsatadi. Ko‘rib turganingizdek, narxlar orasidagi farq ancha katta, shuning uchun buni tushunish aqlli kontraktingiz tranzaksiyalari xarajatlariga sezilarli ta’sir qilishi mumkin. Keling, bir misol ko‘rib chiqamiz.
Solidity’da funksiya ichidagi ma’lumotlarni keshlash kod satrlari sonini oshirsa ham, gas sarfini kamaytirishi mumkin. Bu misolda massiv joylashuvini o‘zgartirish orqali amalga oshirilgan: sikl davomida har safar storage’dan foydalanib, sovuq kirish o‘rniga massiv memory’da saqlanadi, u yerdan murojaat qilish esa arzonroq.
2-maslahat: Nol va noldan farqli qiymatlar hamda gas qaytarimlari
Gsset = 20,000 gas
Rsclear = {ijro narxidagi chegirma}
Ethereum blokcheynida qiymatni 0 dan noldan farqli qiymatga o‘zgartirish Gsset narxidan ko‘rinib turganidek qimmatga tushadi. Ammo qiymatni noldan farqli qiymatdan 0 ga o‘zgartirsangiz, Rsclear opkodiga muvofiq gas qaytarimi olishingiz mumkin. Bu qaytarimdan ortiqcha foydalanishning oldini olish uchun, tranzaksiyaning umumiy xarajatining ko‘pi bilan 20 foizigacha qaytarim olish mumkinligi belgilangan.
Blokcheynda juda keng tarqalgan holatlardan birida, ya’ni aqlli kontraktlarda manzillar balansini yangilashda, shunday vaziyatga duch kelishingiz mumkin. Keling, har biriga bittadan misol ko‘rib chiqamiz:
Birinchi misoldagi ZeroToNonZero kontraktida: noldan farqli qiymatdan noldan farqli qiymatga (5,000 gas*) + noldan noldan farqli qiymatga (20,000 gas) = 25,000 gas
Ikkinchi misoldagi NonZeroToZero kontraktida: noldan farqli qiymatdan nolga (5,000 gas*) + noldan noldan farqli qiymatga (20,000 gas) — gas qaytarimi (4,800 gas) = 21,200 gas
*2,100 (Gcolssload) + 2,900 (Gsreset) = 5,000 gas
3-maslahat: Holat o‘zgaruvchilarining tartibi muhim
Storage — Solidity aqlli kontraktining holat o‘zgaruvchilari qiymatlarini saqlaydigan kalit-qiymat ma’lumotlar tuzilmasidir.
Buni tasavvur qilish uchun storage’ni massiv deb o‘ylashingiz mumkin. Ushbu storage “massivi”dagi har bir joy slot deb ataladi va 32 bayt (256 bit) ma’lumotni saqlaydi. Aqlli kontraktda e’lon qilingan har bir holat o‘zgaruvchisi e’lon qilingan o‘rni va turiga qarab slotni egallaydi.
Barcha ma’lumot turlari har bir slotdagi 32 baytning barchasini egallamaydi, chunki ayrim ma’lumot turlari (bool, uint8, address…) bundan kam joy egallaydi.
Bu yerda qo‘llanadigan usul shuki: agar ikki, uch yoki undan ortiq o‘zgaruvchining umumiy hajmi 32 bayt yoki undan kam bo‘lsa, Solidity kompilyatori ularni bitta slotga joylashtirishga harakat qiladi, ammo bu o‘zgaruvchilar yonma-yon e’lon qilinishi kerak.
Bu yerda bool (1 bayt), address (20 bayt) va uint256 (32 bayt) ma’lumot turlaridan foydalanmoqdamiz. Bu o‘zgaruvchilarning hajmini bilgan holda, TwoSlots kontraktidagi birinchi misolda bool va address birga (1 + 20 = 21 bayt, ya’ni 32 baytdan kam) bo‘lgani uchun ular bitta slotni egallashini osongina tushunishingiz mumkin. ThreeSlots kontraktida esa bool va uint256 bitta slotga sig‘maydi (1 + 32 = 33 bayt, ya’ni slot sig‘imidan ko‘p), shu sababli jami uchta slotdan foydalanamiz.
Xo‘sh, bu nega shunchalik muhim?
SLOAD opkodining narxi 2100 gas bo‘lib, u Storage slotlaridan o‘qish uchun ishlatiladi. Shuning uchun o‘zgaruvchilarni kamroq slotlarda saqlay olsangiz, gasni tejaysiz.
4-maslahat: uint256 uint8’dan arzonroq
3-maslahatda uint256 (256 bit = 32 bayt) o‘zi alohida slotni egallashini, uint8 esa 32 baytdan kam joy egallashini bilib oldik. 8 bit 256 bitdan kichikligi o‘z-o‘zidan tushunarli bo‘lsa-da, uint256 qanday qilib arzonroq bo‘lishi mumkin?
Buni tushunish uchun shuni bilish muhimki, agar o‘zgaruvchi slotni to‘liq egallamasa va bu slot boshqa hech qanday o‘zgaruvchi bilan to‘ldirilmasa, EVM qolgan bitlarni boshqarish mumkin bo‘lishi uchun “0”lar bilan to‘ldiradi.
EVM bajargan bu “0” qo‘shish amali gas talab qiladi. Demak, tranzaksiya gasini tejash uchun uint8 o‘rniga uint256 ishlatgan ma’qul.
__________________
Umid qilamizki, aqlli kontraktlaringizdagi gas xarajatlarini kamaytirishga yordam beradigan bu maslahatlarni o‘rganish davomida EVM qanday ishlashi haqida ham biroz bilib oldingiz.
__________________
Aqlli kontraktlar, Web3 xavfsizligi, Solidity, aqlli kontraktlar auditi va boshqa mavzulardagi kundalik yangiliklar uchun Twitter’da @TheBlockChainer sahifasini kuzating.
__________________