性能优化指南

性能优化指南

性能优化是Web3应用开发中的重要环节。本章将介绍智能合约和DApp的主要优化技术。

合约优化

1. Gas优化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// 1. 存储优化
contract StorageOptimization {
    // 不好的实践
    bool public flag1;
    bool public flag2;
    bool public flag3;

    // 好的实践:打包布尔值
    uint8 public flags;

    // 设置标志
    function setFlag(uint8 index, bool value) public {
        require(index < 8, "Invalid index");

        if (value) {
            flags |= (1 << index);
        } else {
            flags &= ~(1 << index);
        }
    }

    // 获取标志
    function getFlag(uint8 index) public view returns (bool) {
        require(index < 8, "Invalid index");
        return (flags & (1 << index)) != 0;
    }
}

// 2. 循环优化
contract LoopOptimization {
    // 不好的实践
    function badLoop(uint256[] memory array) public pure returns (uint256) {
        uint256 sum = 0;
        for (uint256 i = 0; i < array.length; i++) {
            sum += array[i];
        }
        return sum;
    }

    // 好的实践:缓存数组长度
    function goodLoop(uint256[] memory array) public pure returns (uint256) {
        uint256 sum = 0;
        uint256 length = array.length;
        for (uint256 i = 0; i < length; i++) {
            sum += array[i];
        }
        return sum;
    }

    // 更好的实践:使用unchecked
    function betterLoop(uint256[] memory array) public pure returns (uint256) {
        uint256 sum = 0;
        uint256 length = array.length;
        for (uint256 i = 0; i < length;) {
            sum += array[i];
            unchecked { i++; }
        }
        return sum;
    }
}

// 3. 函数优化
contract FunctionOptimization {
    // 不好的实践:重复计算
    function badCalculation(uint256 x, uint256 y) public pure returns (uint256) {
        return (x + y) * (x + y);
    }

    // 好的实践:缓存计算结果
    function goodCalculation(uint256 x, uint256 y) public pure returns (uint256) {
        uint256 sum = x + y;
        return sum * sum;
    }

    // 使用internal代替public
    function internalFunction(uint256 x) internal pure returns (uint256) {
        return x * x;
    }
}

2. 内存优化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// 1. 内存管理
contract MemoryManagement {
    // 不好的实践:过多的内存分配
    function badMemory(uint256[] memory array) public pure returns (uint256[] memory) {
        uint256[] memory temp1 = new uint256[](array.length);
        uint256[] memory temp2 = new uint256[](array.length);
        uint256[] memory result = new uint256[](array.length);

        for (uint256 i = 0; i < array.length; i++) {
            temp1[i] = array[i] * 2;
            temp2[i] = temp1[i] + 1;
            result[i] = temp2[i];
        }

        return result;
    }

    // 好的实践:重用内存
    function goodMemory(uint256[] memory array) public pure returns (uint256[] memory) {
        uint256[] memory result = new uint256[](array.length);

        for (uint256 i = 0; i < array.length; i++) {
            result[i] = (array[i] * 2) + 1;
        }

        return result;
    }
}

// 2. 字符串优化
contract StringOptimization {
    // 不好的实践:频繁的字符串连接
    function badString(string memory a, string memory b) public pure returns (string memory) {
        return string(abi.encodePacked(a, " ", b));
    }

    // 好的实践:使用bytes
    function goodString(bytes memory a, bytes memory b) public pure returns (bytes memory) {
        bytes memory result = new bytes(a.length + b.length + 1);
        uint256 i;

        for (i = 0; i < a.length; i++) {
            result[i] = a[i];
        }

        result[i] = 0x20; // 空格

        for (uint256 j = 0; j < b.length; j++) {
            result[i + 1 + j] = b[j];
        }

        return result;
    }
}

计算优化

1. 批量处理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// 1. 批量转账
contract BatchTransfer {
    IERC20 public token;

    constructor(address _token) {
        token = IERC20(_token);
    }

    // 不好的实践:单个转账
    function singleTransfer(
        address[] memory recipients,
        uint256[] memory amounts
    ) public {
        require(
            recipients.length == amounts.length,
            "Length mismatch"
        );

        for (uint256 i = 0; i < recipients.length; i++) {
            token.transfer(recipients[i], amounts[i]);
        }
    }

    // 好的实践:批量转账
    function batchTransfer(
        address[] memory recipients,
        uint256[] memory amounts
    ) public {
        require(
            recipients.length == amounts.length,
            "Length mismatch"
        );

        uint256 total = 0;
        for (uint256 i = 0; i < amounts.length; i++) {
            total += amounts[i];
        }

        token.transferFrom(msg.sender, address(this), total);

        for (uint256 i = 0; i < recipients.length; i++) {
            token.transfer(recipients[i], amounts[i]);
        }
    }
}

// 2. 批量操作
contract BatchOperation {
    struct Operation {
        address target;
        uint256 value;
        bytes data;
    }

    // 批量执行
    function batchExecute(Operation[] memory operations) public payable {
        for (uint256 i = 0; i < operations.length; i++) {
            Operation memory op = operations[i];
            (bool success, ) = op.target.call{value: op.value}(op.data);
            require(success, "Operation failed");
        }
    }
}

2. 并行计算

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
// 1. 任务分片
contract TaskSharding {
    struct Task {
        uint256 id;
        uint256 startIndex;
        uint256 endIndex;
        bool completed;
        bytes result;
    }

    mapping(uint256 => Task) public tasks;
    uint256 public taskCount;

    // 创建任务
    function createTask(
        uint256 startIndex,
        uint256 endIndex
    ) public returns (uint256) {
        taskCount++;

        tasks[taskCount] = Task({
            id: taskCount,
            startIndex: startIndex,
            endIndex: endIndex,
            completed: false,
            result: new bytes(0)
        });

        return taskCount;
    }

    // 执行任务
    function executeTask(uint256 taskId) public {
        Task storage task = tasks[taskId];
        require(!task.completed, "Task already completed");

        // 执行计算
        bytes memory result = performComputation(
            task.startIndex,
            task.endIndex
        );

        task.result = result;
        task.completed = true;
    }

    // 执行计算
    function performComputation(
        uint256 startIndex,
        uint256 endIndex
    ) internal pure returns (bytes memory) {
        // 实现具体的计算逻辑
        return new bytes(0);
    }
}

// 2. 工作池
contract WorkerPool {
    struct Worker {
        address account;
        uint256 capacity;
        bool active;
    }

    mapping(address => Worker) public workers;
    address[] public workerList;

    // 注册工作者
    function registerWorker(uint256 capacity) public {
        require(!workers[msg.sender].active, "Already registered");

        workers[msg.sender] = Worker({
            account: msg.sender,
            capacity: capacity,
            active: true
        });

        workerList.push(msg.sender);
    }

    // 分配任务
    function assignTask(
        bytes memory data
    ) public view returns (address) {
        uint256 bestCapacity = 0;
        address bestWorker = address(0);

        for (uint256 i = 0; i < workerList.length; i++) {
            address worker = workerList[i];
            if (
                workers[worker].active &&
                workers[worker].capacity > bestCapacity
            ) {
                bestCapacity = workers[worker].capacity;
                bestWorker = worker;
            }
        }

        return bestWorker;
    }
}

网络优化

1. 事件优化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 1. 事件索引
contract EventOptimization {
    // 不好的实践:过多的索引
    event BadEvent(
        address indexed user,
        address indexed token,
        address indexed recipient,
        uint256 amount,
        uint256 timestamp
    );

    // 好的实践:合理的索引
    event GoodEvent(
        address indexed user,
        address indexed token,
        uint256 amount,
        uint256 timestamp
    );

    // 批量事件
    event BatchEvent(
        address indexed user,
        address[] tokens,
        uint256[] amounts
    );
}

// 2. 事件批处理
contract EventBatching {
    struct Operation {
        address user;
        uint256 amount;
        uint256 timestamp;
    }

    event BatchOperations(Operation[] operations);

    // 批量记录
    function logOperations(Operation[] memory operations) public {
        emit BatchOperations(operations);
    }
}

2. RPC优化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// 1. 调用优化
contract RPCOptimization {
    // 不好的实践:多次调用
    function badCall(address[] memory targets) public view returns (uint256[] memory) {
        uint256[] memory results = new uint256[](targets.length);

        for (uint256 i = 0; i < targets.length; i++) {
            (bool success, bytes memory data) = targets[i].staticcall(
                abi.encodeWithSignature("getValue()")
            );
            require(success, "Call failed");
            results[i] = abi.decode(data, (uint256));
        }

        return results;
    }

    // 好的实践:批量调用
    function goodCall(
        address[] memory targets,
        bytes[] memory data
    ) public view returns (bytes[] memory) {
        bytes[] memory results = new bytes[](targets.length);

        for (uint256 i = 0; i < targets.length; i++) {
            (bool success, bytes memory result) = targets[i].staticcall(data[i]);
            require(success, "Call failed");
            results[i] = result;
        }

        return results;
    }
}

// 2. 缓存优化
contract CacheOptimization {
    struct Cache {
        uint256 value;
        uint256 timestamp;
        uint256 ttl;
    }

    mapping(bytes32 => Cache) public cache;

    // 获取或更新缓存
    function getOrUpdate(
        bytes32 key,
        uint256 ttl
    ) public returns (uint256) {
        Cache storage entry = cache[key];

        if (
            entry.timestamp + entry.ttl > block.timestamp &&
            entry.ttl > 0
        ) {
            return entry.value;
        }

        // 获取新值
        uint256 newValue = fetchValue();

        entry.value = newValue;
        entry.timestamp = block.timestamp;
        entry.ttl = ttl;

        return newValue;
    }

    // 获取值
    function fetchValue() internal pure returns (uint256) {
        // 实现获取值的逻辑
        return 0;
    }
}

练习题

  1. 实现一个Gas优化的合约:
1
2
3
4
// 练习:实现Gas优化
contract GasOptimization {
    // 你的代码
}
  1. 创建内存优化的数组操作:
1
2
3
4
// 练习:实现内存优化
contract MemoryOptimization {
    // 你的代码
}
  1. 实现批量转账:
1
2
3
4
// 练习:实现批量转账
contract BatchTransfer {
    // 你的代码
}
  1. 创建工作池:
1
2
3
4
// 练习:实现工作池
contract WorkerPool {
    // 你的代码
}
  1. 实现事件优化:
1
2
3
4
// 练习:实现事件优化
contract EventOptimization {
    // 你的代码
}

参考资源

  1. Solidity Gas优化
  2. 以太坊Gas优化
  3. Web3性能优化
  4. DApp优化指南
  5. 智能合约最佳实践