gas သက်သာစေရန် သင့်ကုဒ်ရေးသားမှုစွမ်းရည်ကို မြှင့်တင်ပေးမည့် Solidity အကြံပြုချက်အချို့ကို သင်တွေ့ဖူးလောက်ပါသည်။ သို့သော် ယနေ့တွင် Ethereum Virtual Machine အလုပ်လုပ်ပုံကို နားလည်ထားခြင်းက သင့် smart contract များအတွက် gas ကုန်ကျစရိတ်ကို မည်သို့ အမှန်တကယ် သက်သာစေနိုင်ကြောင်းကို ပိုမိုအာရုံစိုက်လိုပါသည်။
Ethereum ကို နက်နက်ရှိုင်းရှိုင်း လေ့လာသွားတော့မည်ဖြစ်သောကြောင့် opcode များ၏ gas ကုန်ကျစရိတ်များကို သတ်မှတ်ထားသည့် ၎င်း၏ Yellow Paper မှ အပိုင်းတစ်ခုကို ဤနေရာတွင် ထည့်ပေးထားပါသည်။ ဆောင်းပါးတစ်လျှောက်လုံး ၎င်းတို့ကို ကိုးကားသွားပါမည်။
အကြံပြုချက် #1: Cold access နှင့် warm access
Gcoldsload: 2100 gas
Gwarmaccess: 100 gas
ဤနေရာတွင် ကျွန်ုပ်တို့၏ ပထမဆုံး OPCODE များကို တွေ့ရသည်။ ပထမတစ်ခုသည် variable တစ်ခုကို ပထမဆုံးအကြိမ် ဖတ်ရှုရန် (သို့မဟုတ် cold access) ကုန်ကျစရိတ်ကို သတ်မှတ်ပြီး၊ ဒုတိယတစ်ခုသည် ထို variable ကို ဒုတိယအကြိမ်နှင့် နောက်ပိုင်းတွင် ဖတ်ရှုရန် (warm access) ကုန်ကျစရိတ်ကို သတ်မှတ်သည်။ ဈေးနှုန်းကွာခြားချက်မှာ များစွာကြီးမားသည်ကို တွေ့ရနိုင်သကဲ့သို့၊ ဤအချက်ကို နားလည်ခြင်းဖြင့် သင့် smart contract ၏ transaction ကုန်ကျစရိတ်များကို များစွာ လျှော့ချနိုင်သည်။ ဥပမာတစ်ခုကို ကြည့်ကြရအောင်။
Solidity တွင် function တစ်ခုအတွင်း ဒေတာကို cache လုပ်ထားခြင်းသည် code လိုင်းများ ပိုများလာသော်လည်း gas အသုံးပြုမှုကို လျှော့ချနိုင်သည်။ ဤဥပမာတွင် array ၏ တည်နေရာကို ပြောင်းလဲထားသည်။ loop တစ်ပတ်စီတိုင်း storage မှ ဖတ်ရှုကာ cold access လုပ်မည့်အစား array ကို memory ထဲတွင် သိမ်းဆည်းထားပြီး ၎င်းကို ဖတ်ရှုရန် ကုန်ကျစရိတ် ပိုနည်းသည်။
အကြံပြုချက် #2: သုညတန်ဖိုးနှင့် သုညမဟုတ်သောတန်ဖိုးများ၊ gas ပြန်အမ်းငွေ
Gsset = 20,000 gas
Rsclear = {လုပ်ဆောင်မှုကုန်ကျစရိတ်အပေါ် လျှော့စျေး}
Ethereum blockchain တွင် တန်ဖိုးတစ်ခုကို 0 မှ သုညမဟုတ်သောတန်ဖိုးသို့ ပြောင်းလဲခြင်းသည် Gsset ၏ ကုန်ကျစရိတ်ကို ကြည့်လျှင် ဈေးကြီးသည်။ သို့သော် သုညမဟုတ်သောတန်ဖိုးမှ 0 သို့ ပြောင်းလဲခြင်းသည် Rsclear opcode အရ gas တန်ဖိုးကို ပြန်အမ်းပေးနိုင်သည်။ ပြန်အမ်းငွေကို အလွန်အကျွံ အသုံးချခြင်းမရှိစေရန်၊ transaction ကုန်ကျစရိတ် စုစုပေါင်း၏ အများဆုံး 20% အထိသာ ပြန်အမ်းငွေ ရနိုင်သည်ဟု သတ်မှတ်ထားသည်။
blockchain တွင် အလွန်တွေ့ရလေ့ရှိသော အခြေအနေတစ်ခုဖြစ်သည့် smart contract များရှိ address များ၏ လက်ကျန်ငွေကို အပ်ဒိတ်လုပ်သည့်အခါတွင် ဤကဲ့သို့သော အခြေအနေမျိုးကို တွေ့နိုင်သည်။ တစ်ခုစီအတွက် ဥပမာကို ကြည့်ကြရအောင်။
ပထမဥပမာဖြစ်သော ZeroToNonZero contract တွင်၊ သုညမဟုတ်ရာမှ သုညမဟုတ်ရာသို့ (5,000 gas*) + သုညမှ သုညမဟုတ်ရာသို့ (20,000 gas) = 25,000 gas
ဒုတိယဥပမာဖြစ်သော NonZeroToZero contract တွင်၊ သုညမဟုတ်ရာမှ သုညသို့ (5,000 gas*) + သုညမှ သုညမဟုတ်ရာသို့ (20,000 gas) — ပြန်အမ်းငွေ (4,800 gas) = 21,200 gas
*2,100 (Gcolssload) + 2,900 (Gsreset) = 5,000 gas
အကြံပြုချက် #3: state variable များ၏ အစီအစဉ်သည် အရေးကြီးသည်
Storage သည် Solidity smart contract တစ်ခု၏ state variable တန်ဖိုးများကို သိမ်းဆည်းထားသည့် key-value data structure တစ်ခုနှင့် တူသည်။
Storage ကို မြင်သာစေရန် array တစ်ခုအဖြစ် စဉ်းစားနိုင်သည်။ ဤ Storage “array” ထဲရှိ နေရာတစ်ခုစီကို slot ဟုခေါ်ပြီး ဒေတာ 32 bytes (256 bits) ကို သိမ်းဆည်းနိုင်သည်။ smart contract တွင် ကြေညာထားသော state variable တစ်ခုစီသည် ၎င်း၏ ကြေညာထားသည့် အစီအစဉ်နေရာနှင့် type ပေါ်မူတည်၍ slot တစ်ခုကို အသုံးပြုမည်ဖြစ်သည်။
data type အားလုံးသည် slot တစ်ခုစီရှိ 32 bytes အားလုံးကို အသုံးပြုကြသည်မဟုတ်ပါ။ အချို့ data type များ (bool, uint8, address…) သည် ထိုပမာဏထက် နည်းသော bytes ကိုသာ အသုံးပြုသည်။
ဤနေရာတွင် အသုံးပြုသည့် နည်းလမ်းမှာ variable နှစ်ခု၊ သုံးခု သို့မဟုတ် ထို့ထက်ပိုသော variable များ၏ စုစုပေါင်းအရွယ်အစားသည် 32 bytes သို့မဟုတ် ထိုထက်နည်းပါက Solidity compiler သည် ၎င်းတို့ကို slot တစ်ခုတည်းထဲတွင် စုစည်းထည့်သွင်းရန် ကြိုးစားခြင်းဖြစ်သည်။ သို့သော် ထို variable များကို တစ်ခုနှင့်တစ်ခု ကပ်လျက် သတ်မှတ်ထားရမည်။
ဤနေရာတွင် bool (1 byte), address (20 bytes) နှင့် uint256 (32 bytes) data type များကို အသုံးပြုထားသည်။ ဤ variable များ၏ အရွယ်အစားကို သိထားပါက TwoSlots contract ရှိ ပထမဥပမာတွင် bool နှင့် address ကို အတူတကွ ထည့်ထားသောကြောင့် (1 + 20 = 21 bytes၊ 32 bytes ထက်နည်းသည်) ၎င်းတို့သည် slot တစ်ခုကို အသုံးပြုမည်ဖြစ်ကြောင်း အလွယ်တကူ နားလည်နိုင်သည်။ ThreeSlots contract တွင် bool နှင့် uint256 ကို slot တစ်ခုတည်းတွင် ထည့်၍မရသောကြောင့် (1 + 32 = 33 bytes၊ slot ၏ အများဆုံးပမာဏထက် ပိုသည်) စုစုပေါင်း slot သုံးခုကို အသုံးပြုရမည်ဖြစ်သည်။
ဒါဆို ဒါက ဘာကြောင့် အလွန်အရေးကြီးတာလဲ။
SLOAD opcode သည် 2100 gas ကုန်ကျပြီး Storage slot များမှ ဖတ်ရန် အသုံးပြုသည်။ ထို့ကြောင့် variable များကို slot အနည်းငယ်အတွင်း သိမ်းဆည်းနိုင်ပါက gas အချို့ကို ချွေတာနိုင်မည်ဖြစ်သည်။
အကြံပြုချက် #4: uint256 သည် uint8 ထက် ကုန်ကျစရိတ် ပိုနည်းသည်
အကြံပြုချက် #3 တွင် uint256 (256 bits = 32 bytes) သည် slot တစ်ခုကို တစ်ခုတည်း အသုံးပြုကြောင်းနှင့် uint8 သည် 32 bytes ထက်ငယ်ကြောင်း သင်ယူခဲ့ရသည်။ 8 bits သည် 256 bits ထက်ငယ်သည်မှာ ရှင်းနေသော်လည်း uint256 က ဘာကြောင့် ကုန်ကျစရိတ် ပိုနည်းရတာလဲ။
variable တစ်ခုသည် slot တစ်ခုလုံးကို မဖြည့်ဘဲ၊ ထို slot ကို အခြား variable များကလည်း မဖြည့်ထားပါက EVM သည် ၎င်းကို ကိုင်တွယ်နိုင်ရန် ကျန်ရှိသော bit များကို “0” များဖြင့် ဖြည့်ပေးမည်ဖြစ်ကြောင်း သိထားရန် အရေးကြီးသည်။
EVM က ထည့်ပေးသည့် ဤ “0” များသည် gas ကုန်ကျစေသည်။ ထို့ကြောင့် transaction gas ကို ချွေတာရန် uint8 အစား uint256 ကို အသုံးပြုခြင်းက ပိုကောင်းသည်။
__________________
သင့် smart contract များတွင် gas ကုန်ကျစရိတ်ကို လျှော့ချရန် ဤအကြံပြုချက်များကို လေ့လာရင်း EVM အလုပ်လုပ်ပုံအကြောင်းကိုလည်း အနည်းငယ် သင်ယူနိုင်ခဲ့မည်ဟု မျှော်လင့်ပါသည်။
__________________
Smart Contract များ၊ Web3 Security၊ Solidity၊ smart contract များကို စစ်ဆေးခြင်းနှင့် အခြားအကြောင်းအရာများအတွက် နေ့စဉ်အပ်ဒိတ်များ ပိုမိုရယူရန် Twitter @TheBlockChainer ကို ကြည့်ပါ။
__________________