analyze-gas-optimization
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSkill: analyze-gas-optimization
Skill: analyze-gas-optimization
Analyze and optimize Aptos Move contracts for gas efficiency, identifying expensive operations and suggesting
optimizations.
分析并优化Aptos Move合约的gas效率,识别高开销操作并给出优化建议。
When to Use This Skill
何时使用该技能
Trigger phrases:
- "optimize gas", "reduce gas costs", "gas analysis"
- "make contract cheaper", "gas efficiency"
- "analyze gas usage", "gas optimization"
- "reduce transaction costs"
Use cases:
- Before mainnet deployment
- When transaction costs are high
- When optimizing for high-frequency operations
- When building DeFi protocols with many transactions
触发短语:
- "optimize gas", "reduce gas costs", "gas analysis"
- "make contract cheaper", "gas efficiency"
- "analyze gas usage", "gas optimization"
- "reduce transaction costs"
使用场景:
- 主网部署前
- 交易成本过高时
- 针对高频操作做优化时
- 构建包含大量交易的DeFi协议时
Core Gas Optimization Principles
核心Gas优化原则
1. Storage Optimization
1. 存储优化
- Minimize stored data size
- Use efficient data structures
- Pack struct fields efficiently
- Remove unnecessary fields
- 最小化存储数据大小
- 使用高效的数据结构
- 高效打包结构体字段
- 移除不必要的字段
2. Computation Optimization
2. 计算优化
- Avoid loops over large collections
- Cache repeated calculations
- Use bitwise operations when possible
- Minimize vector operations
- 避免遍历大型集合的循环
- 缓存重复计算的结果
- 尽可能使用位运算
- 最小化向量操作
3. Reference Optimization
3. 引用优化
- Prefer borrowing over moving when possible
- Use and
&efficiently&mut - Avoid unnecessary copies
- 尽可能优先使用借用而非转移
- 高效使用和
&&mut - 避免不必要的拷贝
Gas Cost Analysis
Gas成本分析
Expensive Operations
高开销操作
1. Global Storage Operations
1. 全局存储操作
move
// EXPENSIVE: Writing to global storage
move_to(account, large_struct);
// EXPENSIVE: Reading and writing
let data = borrow_global_mut<LargeData>(addr);
// EXPENSIVE: Checking existence
if (exists<Resource>(addr)) { ... }move
// EXPENSIVE: Writing to global storage
move_to(account, large_struct);
// EXPENSIVE: Reading and writing
let data = borrow_global_mut<LargeData>(addr);
// EXPENSIVE: Checking existence
if (exists<Resource>(addr)) { ... }2. Vector Operations
2. 向量操作
move
// EXPENSIVE: Growing vectors dynamically
vector::push_back(&mut vec, item); // O(n) worst case
// EXPENSIVE: Searching vectors
vector::contains(&vec, &item); // O(n)
// EXPENSIVE: Removing from middle
vector::remove(&mut vec, index); // O(n)move
// EXPENSIVE: Growing vectors dynamically
vector::push_back(&mut vec, item); // O(n) worst case
// EXPENSIVE: Searching vectors
vector::contains(&vec, &item); // O(n)
// EXPENSIVE: Removing from middle
vector::remove(&mut vec, index); // O(n)3. String Operations
3. 字符串操作
move
// EXPENSIVE: String concatenation
string::append(&mut s1, s2);
// EXPENSIVE: UTF8 validation
string::utf8(bytes);move
// EXPENSIVE: String concatenation
string::append(&mut s1, s2);
// EXPENSIVE: UTF8 validation
string::utf8(bytes);Optimization Patterns
优化模式
1. Batch Operations
1. 批量操作
move
// BAD: Multiple storage accesses
public fun update_values(account: &signer, updates: vector<Update>) {
let i = 0;
while (i < vector::length(&updates)) {
let update = vector::borrow(&updates, i);
let data = borrow_global_mut<Data>(update.address);
data.value = update.value;
i = i + 1;
}
}
// GOOD: Single storage access with batch update
public fun batch_update(account: &signer, updates: vector<Update>) {
let data = borrow_global_mut<Data>(signer::address_of(account));
let i = 0;
while (i < vector::length(&updates)) {
let update = vector::borrow(&updates, i);
// Update in memory
update_memory_data(data, update);
i = i + 1;
}
}move
// BAD: Multiple storage accesses
public fun update_values(account: &signer, updates: vector<Update>) {
let i = 0;
while (i < vector::length(&updates)) {
let update = vector::borrow(&updates, i);
let data = borrow_global_mut<Data>(update.address);
data.value = update.value;
i = i + 1;
}
}
// GOOD: Single storage access with batch update
public fun batch_update(account: &signer, updates: vector<Update>) {
let data = borrow_global_mut<Data>(signer::address_of(account));
let i = 0;
while (i < vector::length(&updates)) {
let update = vector::borrow(&updates, i);
// Update in memory
update_memory_data(data, update);
i = i + 1;
}
}2. Storage Packing
2. 存储打包
move
// BAD: Wasteful storage
struct UserData has key {
active: bool, // 1 byte used, 7 wasted
level: u8, // 1 byte used, 7 wasted
score: u64, // 8 bytes
timestamp: u64, // 8 bytes
// Total: 32 bytes (50% wasted)
}
// GOOD: Packed storage
struct UserData has key {
// Pack small fields together
flags: u8, // Bits: [active, reserved...]
level: u8,
reserved: u16, // Future use
score: u64,
timestamp: u64,
// Total: 20 bytes (37.5% saved)
}move
// BAD: Wasteful storage
struct UserData has key {
active: bool, // 1 byte used, 7 wasted
level: u8, // 1 byte used, 7 wasted
score: u64, // 8 bytes
timestamp: u64, // 8 bytes
// Total: 32 bytes (50% wasted)
}
// GOOD: Packed storage
struct UserData has key {
// Pack small fields together
flags: u8, // Bits: [active, reserved...]
level: u8,
reserved: u16, // Future use
score: u64,
timestamp: u64,
// Total: 20 bytes (37.5% saved)
}3. Lazy Evaluation
3. 懒加载计算
move
// BAD: Always compute expensive value
struct Pool has key {
total_shares: u64,
total_assets: u64,
// Computed on every update
share_price: u64,
}
// GOOD: Compute only when needed
struct Pool has key {
total_shares: u64,
total_assets: u64,
// Don't store computed values
}
public fun get_share_price(pool_addr: address): u64 {
let pool = borrow_global<Pool>(pool_addr);
if (pool.total_shares == 0) {
INITIAL_SHARE_PRICE
} else {
pool.total_assets * PRECISION / pool.total_shares
}
}move
// BAD: Always compute expensive value
struct Pool has key {
total_shares: u64,
total_assets: u64,
// Computed on every update
share_price: u64,
}
// GOOD: Compute only when needed
struct Pool has key {
total_shares: u64,
total_assets: u64,
// Don't store computed values
}
public fun get_share_price(pool_addr: address): u64 {
let pool = borrow_global<Pool>(pool_addr);
if (pool.total_shares == 0) {
INITIAL_SHARE_PRICE
} else {
pool.total_assets * PRECISION / pool.total_shares
}
}4. Event Optimization
4. 事件优化
move
// BAD: Large event data
struct TradeEvent has drop, store {
pool: Object<Pool>,
trader: address,
token_in: Object<Token>,
token_out: Object<Token>,
amount_in: u64,
amount_out: u64,
fees: u64,
timestamp: u64,
metadata: vector<u8>, // Large metadata
}
// GOOD: Minimal event data
struct TradeEvent has drop, store {
pool_id: u64, // Use ID instead of Object
trader: address,
amounts: u128, // Pack amount_in and amount_out
fees: u64,
// Compute other data from state
}move
// BAD: Large event data
struct TradeEvent has drop, store {
pool: Object<Pool>,
trader: address,
token_in: Object<Token>,
token_out: Object<Token>,
amount_in: u64,
amount_out: u64,
fees: u64,
timestamp: u64,
metadata: vector<u8>, // Large metadata
}
// GOOD: Minimal event data
struct TradeEvent has drop, store {
pool_id: u64, // Use ID instead of Object
trader: address,
amounts: u128, // Pack amount_in and amount_out
fees: u64,
// Compute other data from state
}5. Collection Optimization
5. 集合优化
move
// BAD: Linear search
public fun find_item(items: &vector<Item>, id: u64): Option<Item> {
let i = 0;
while (i < vector::length(items)) {
let item = vector::borrow(items, i);
if (item.id == id) {
return option::some(*item)
};
i = i + 1;
}
option::none()
}
// GOOD: Use Table for O(1) lookup
struct Storage has key {
items: Table<u64, Item>,
}
public fun find_item(storage: &Storage, id: u64): Option<Item> {
if (table::contains(&storage.items, id)) {
option::some(*table::borrow(&storage.items, id))
} else {
option::none()
}
}move
// BAD: Linear search
public fun find_item(items: &vector<Item>, id: u64): Option<Item> {
let i = 0;
while (i < vector::length(items)) {
let item = vector::borrow(items, i);
if (item.id == id) {
return option::some(*item)
};
i = i + 1;
}
option::none()
}
// GOOD: Use Table for O(1) lookup
struct Storage has key {
items: Table<u64, Item>,
}
public fun find_item(storage: &Storage, id: u64): Option<Item> {
if (table::contains(&storage.items, id)) {
option::some(*table::borrow(&storage.items, id))
} else {
option::none()
}
}Gas Measurement
Gas测算
1. Transaction Simulation
1. 交易模拟
bash
undefinedbash
undefinedSimulate to get gas estimate
Simulate to get gas estimate
aptos move run-function
--function-id 0x1::module::function
--args ...
--simulate
--function-id 0x1::module::function
--args ...
--simulate
aptos move run-function
--function-id 0x1::module::function
--args ...
--simulate
--function-id 0x1::module::function
--args ...
--simulate
Output includes:
Output includes:
- gas_unit_price
- gas_unit_price
- max_gas_amount
- max_gas_amount
- gas_used
- gas_used
undefinedundefined2. Gas Profiling
2. Gas性能分析
move
#[test]
public fun test_gas_usage() {
// Measure gas for operation
let gas_before = gas::remaining_gas();
expensive_operation();
let gas_used = gas_before - gas::remaining_gas();
// Assert reasonable gas usage
assert!(gas_used < MAX_ACCEPTABLE_GAS, E_TOO_EXPENSIVE);
}move
#[test]
public fun test_gas_usage() {
// Measure gas for operation
let gas_before = gas::remaining_gas();
expensive_operation();
let gas_used = gas_before - gas::remaining_gas();
// Assert reasonable gas usage
assert!(gas_used < MAX_ACCEPTABLE_GAS, E_TOO_EXPENSIVE);
}Optimization Checklist
优化检查清单
Storage Checklist
存储检查项
- Pack struct fields to minimize size
- Use appropriate integer sizes (u8, u16, u32, u64)
- Remove unnecessary fields
- Consider off-chain storage for large data
- Use events instead of storage for logs
- 打包结构体字段以最小化体积
- 使用合适的整数类型(u8、u16、u32、u64)
- 移除不必要的字段
- 大型数据考虑使用链下存储
- 日志使用事件而非存储
Computation Checklist
计算检查项
- Cache repeated calculations
- Minimize loops over collections
- Use early returns to skip unnecessary work
- Batch similar operations
- Avoid redundant checks
- 缓存重复计算的结果
- 最小化遍历集合的循环
- 使用提前返回跳过不必要的工作
- 批量处理相似操作
- 避免冗余检查
Collection Checklist
集合检查项
- Use Table/TableWithLength for key-value lookups
- Use SmartTable for large collections
- Limit vector sizes
- Consider pagination for large results
- Use appropriate data structures
- 使用Table/TableWithLength实现键值查找
- 大型集合使用SmartTable
- 限制向量大小
- 大型结果考虑分页
- 使用合适的数据结构
Best Practices
最佳实践
- Profile before and after optimization
- Test gas usage in unit tests
- Document gas costs for public functions
- Consider gas costs in contract design
- Monitor mainnet gas usage
- 优化前后都进行性能分析
- 在单元测试中测试gas使用情况
- 为公开函数标注gas成本
- 合约设计阶段就考虑gas成本
- 监控主网gas使用情况
Common Gas Optimizations
常见Gas优化方案
1. Replace Vectors with Tables
1. 用Table替换Vector
move
// Before: O(n) search
struct Registry has key {
users: vector<User>,
}
// After: O(1) lookup
struct Registry has key {
users: Table<address, User>,
user_list: vector<address>, // If iteration needed
}move
// Before: O(n) search
struct Registry has key {
users: vector<User>,
}
// After: O(1) lookup
struct Registry has key {
users: Table<address, User>,
user_list: vector<address>, // If iteration needed
}2. Minimize Storage Reads
2. 最小化存储读取次数
move
// Before: Multiple reads
public fun transfer(from: &signer, to: address, amount: u64) {
assert!(get_balance(signer::address_of(from)) >= amount, E_INSUFFICIENT);
let from_balance = borrow_global_mut<Balance>(signer::address_of(from));
let to_balance = borrow_global_mut<Balance>(to);
// ...
}
// After: Single read with validation
public fun transfer(from: &signer, to: address, amount: u64) {
let from_addr = signer::address_of(from);
let from_balance = borrow_global_mut<Balance>(from_addr);
assert!(from_balance.value >= amount, E_INSUFFICIENT);
// ... rest of logic
}move
// Before: Multiple reads
public fun transfer(from: &signer, to: address, amount: u64) {
assert!(get_balance(signer::address_of(from)) >= amount, E_INSUFFICIENT);
let from_balance = borrow_global_mut<Balance>(signer::address_of(from));
let to_balance = borrow_global_mut<Balance>(to);
// ...
}
// After: Single read with validation
public fun transfer(from: &signer, to: address, amount: u64) {
let from_addr = signer::address_of(from);
let from_balance = borrow_global_mut<Balance>(from_addr);
assert!(from_balance.value >= amount, E_INSUFFICIENT);
// ... rest of logic
}3. Use Bitwise Flags
3. 使用位标志
move
// Before: Multiple bool fields (8 bytes each)
struct Settings has copy, drop, store {
is_active: bool,
is_paused: bool,
is_initialized: bool,
allows_deposits: bool,
}
// After: Single u8 (1 byte)
struct Settings has copy, drop, store {
flags: u8, // Bit 0: active, 1: paused, 2: initialized, 3: deposits
}
const FLAG_ACTIVE: u8 = 1; // 0b00000001
const FLAG_PAUSED: u8 = 2; // 0b00000010
const FLAG_INITIALIZED: u8 = 4; // 0b00000100
const FLAG_DEPOSITS: u8 = 8; // 0b00001000
public fun is_active(settings: &Settings): bool {
(settings.flags & FLAG_ACTIVE) != 0
}move
// Before: Multiple bool fields (8 bytes each)
struct Settings has copy, drop, store {
is_active: bool,
is_paused: bool,
is_initialized: bool,
allows_deposits: bool,
}
// After: Single u8 (1 byte)
struct Settings has copy, drop, store {
flags: u8, // Bit 0: active, 1: paused, 2: initialized, 3: deposits
}
const FLAG_ACTIVE: u8 = 1; // 0b00000001
const FLAG_PAUSED: u8 = 2; // 0b00000010
const FLAG_INITIALIZED: u8 = 4; // 0b00000100
const FLAG_DEPOSITS: u8 = 8; // 0b00001000
public fun is_active(settings: &Settings): bool {
(settings.flags & FLAG_ACTIVE) != 0
}Gas Optimization Report Template
Gas优化报告模板
markdown
undefinedmarkdown
undefinedGas Optimization Report
Gas Optimization Report
Summary
Summary
- Current average gas: X units
- Optimized average gas: Y units
- Savings: Z% reduction
- Current average gas: X units
- Optimized average gas: Y units
- Savings: Z% reduction
Optimizations Applied
Optimizations Applied
1. Storage Optimization
1. Storage Optimization
- Packed struct fields (saved X bytes)
- Replaced vectors with tables (O(n) → O(1))
- Removed redundant fields
- Packed struct fields (saved X bytes)
- Replaced vectors with tables (O(n) → O(1))
- Removed redundant fields
2. Computation Optimization
2. Computation Optimization
- Cached price calculations (saved X operations)
- Batched updates (N calls → 1 call)
- Early returns in validation
- Cached price calculations (saved X operations)
- Batched updates (N calls → 1 call)
- Early returns in validation
3. Event Optimization
3. Event Optimization
- Reduced event size from X to Y bytes
- Removed redundant event fields
- Reduced event size from X to Y bytes
- Removed redundant event fields
Measurements
Measurements
| Function | Before | After | Savings |
|---|---|---|---|
| mint | 50,000 | 35,000 | 30% |
| transfer | 30,000 | 25,000 | 17% |
| swap | 80,000 | 60,000 | 25% |
| Function | Before | After | Savings |
|---|---|---|---|
| mint | 50,000 | 35,000 | 30% |
| transfer | 30,000 | 25,000 | 17% |
| swap | 80,000 | 60,000 | 25% |
Recommendations
Recommendations
- Consider further optimizations for high-frequency functions
- Monitor mainnet usage patterns
- Set up gas usage alerts
undefined- Consider further optimizations for high-frequency functions
- Monitor mainnet usage patterns
- Set up gas usage alerts
undefinedIntegration Notes
集成说明
- Works with to ensure optimizations don't compromise security
security-audit - Use with to verify optimizations maintain correctness
generate-tests - Apply before for mainnet deployments
deploy-contracts - Reference for detailed patterns
STORAGE_OPTIMIZATION.md
- 可与搭配使用,确保优化不会损害安全性
security-audit - 可配合使用,验证优化后逻辑正确性
generate-tests - 在主网部署的步骤前应用
deploy-contracts - 参考获取详细模式说明
STORAGE_OPTIMIZATION.md
NEVER Rules
禁止规则
- ❌ NEVER optimize away security checks (access control, input validation)
- ❌ NEVER deploy optimized code without re-testing
- ❌ NEVER read or
.envduring gas analysis (contain private keys)~/.aptos/config.yaml
- ❌ 绝对不要移除安全检查(访问控制、输入校验)来优化gas
- ❌ 绝对不要未重新测试就部署优化后的代码
- ❌ gas分析期间绝对不要读取或
.env(包含私钥)~/.aptos/config.yaml
References
参考资料
- Aptos Gas Schedule: https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/aptos-gas-schedule
- Move VM Gas Metering: https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/aptos-vm
- Gas Optimization Patterns: Check daily-move repository for real examples
- Aptos Gas Schedule: https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/aptos-gas-schedule
- Move VM Gas Metering: https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/aptos-vm
- Gas Optimization Patterns: Check daily-move repository for real examples