Skip to content

Commit d9ee818

Browse files
committed
update
1 parent 5c146ff commit d9ee818

File tree

6 files changed

+168
-945
lines changed

6 files changed

+168
-945
lines changed

PERFORMANCE_REPORT.md

Lines changed: 142 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -1,189 +1,164 @@
1-
# LuaRS 性能报告
1+
# Lua-RS 性能报告
22

3-
## 概述
4-
5-
本报告比较 luars(Rust 实现)与官方 Lua 5.4.6 的性能表现。
6-
7-
**测试环境:**
8-
- OS: Windows
9-
- Lua 5.4.6: 从源码编译 (CMake + MSVC)
10-
- luars: `cargo build --release`
11-
12-
**总体结果:**
13-
| 运行时 | 总时间 | 相对性能 |
14-
|--------|--------|----------|
15-
| Lua 5.4.6 | ~10.1 秒 | 100% |
16-
| luars | ~15.3 秒 | 66% |
17-
18-
luars 在基准测试套件中达到 Lua 5.4 约 **66%** 的性能。
3+
**测试日期**: 2024-12-08
4+
**对比版本**: Lua-RS (Rust 实现) vs Lua 5.4 (原生 C)
5+
**平台**: Windows x64, Release 模式
196

207
---
218

22-
## 详细对比
23-
24-
### 算术运算
25-
26-
| 测试项 | luars | Lua 5.4 | 比率 |
27-
|--------|-------|---------|------|
28-
| 整数加法 | 139 M/s | 233 M/s | 60% |
29-
| 浮点乘法 | 127 M/s | 208 M/s | 61% |
30-
| 混合运算 | 74 M/s | 123 M/s | 60% |
31-
32-
### 控制流
33-
34-
| 测试项 | luars | Lua 5.4 | 比率 |
35-
|--------|-------|---------|------|
36-
| If-else | 56 M/s | 52 M/s | 108% ✓ |
37-
| While 循环 | 80 M/s | 118 M/s | 68% |
38-
| Repeat-until | 83 M/s | 147 M/s | 56% |
39-
| 嵌套循环 | 145 M/s | 250 M/s | 58% |
40-
41-
### 变量访问
42-
43-
| 测试项 | luars | Lua 5.4 | 比率 |
44-
|--------|-------|---------|------|
45-
| 全局变量 | 32 M/s | 74 M/s | 43% |
46-
| 局部变量 | 121 M/s | 233 M/s | 52% |
47-
| Upvalue | 53 M/s | 133 M/s | 40% |
48-
49-
### 函数调用
50-
51-
| 测试项 | luars | Lua 5.4 | 比率 |
52-
|--------|-------|---------|------|
53-
| 简单调用 | 19 M/s | 53 M/s | 36% |
54-
| 变长参数 | 1.7 M/s | 2.5 M/s | 68% |
55-
56-
### 闭包
57-
58-
| 测试项 | luars | Lua 5.4 | 比率 |
59-
|--------|-------|---------|------|
60-
| 闭包创建 | 11.6 M/s | 7.1 M/s | 163% ✓ |
61-
| Upvalue 读写 | 18.5 M/s | 43.5 M/s | 43% |
62-
63-
### 表操作
64-
65-
| 测试项 | luars | Lua 5.4 | 比率 |
66-
|--------|-------|---------|------|
67-
| 表插入 | 43 M/s | 34 M/s | 126% ✓ |
68-
| 表访问 | 84 M/s | 125 M/s | 67% |
69-
70-
### 元表 (fasttm 优化后)
71-
72-
| 测试项 | luars | Lua 5.4 | 比率 |
73-
|--------|-------|---------|------|
74-
| __index (函数) | 4.9 M/s | 22 M/s | 22% |
75-
| __index (表) | 23 M/s | 26 M/s | 88% ✓ |
76-
| __newindex | 6.1 M/s | 17 M/s | 36% |
77-
| __call | 15.7 M/s | 25 M/s | 63% |
78-
| __len | 5.3 M/s | 28 M/s | 19% |
79-
| rawget | 21 M/s | 21 M/s | 100% ✓ |
80-
81-
### fasttm 优化效果
82-
83-
当表有元表但**没有特定元方法**时的访问性能:
84-
85-
| 测试项 | luars | Lua 5.4 | 比率 |
86-
|--------|-------|---------|------|
87-
| 缺失键 (有元表, 无__index) | 100-113 M/s | 100 M/s | 100-113% ✓ |
88-
| #table (有元表, 无__len) | 83-105 M/s | 100 M/s | 83-105% ✓ |
89-
90-
### 协程
91-
92-
| 测试项 | luars | Lua 5.4 | 比率 |
93-
|--------|-------|---------|------|
94-
| 创建/恢复/让出 | 319 K/s | 521 K/s | 61% |
95-
| 重复 yield | 2.7 M/s | 735 K/s | 367% ✓ |
96-
| coroutine.wrap | 405 K/s | 2.5 M/s | 16% |
97-
98-
### 错误处理
99-
100-
| 测试项 | luars | Lua 5.4 | 比率 |
101-
|--------|-------|---------|------|
102-
| pcall (成功) | 3.2 M/s | 17 M/s | 19% |
103-
| pcall (失败) | 3.4 M/s | 493 K/s | 690% ✓ |
104-
| xpcall (失败) | 1.2 M/s | 459 K/s | 261% ✓ |
9+
## 📊 性能概览
10+
11+
### 🟢 优势领域 (Lua-RS 更快)
12+
13+
| 测试项 | Lua-RS | 原生 Lua | 优势比 |
14+
|--------|--------|----------|--------|
15+
| Closure 创建 | 11.92 M/s | 7.46 M/s | **+60%** |
16+
| table.insert (end) | 20.5 K/s | 12.5 K/s | **+64%** |
17+
| table.insert (middle) | 11.2 K/s | 3.3 K/s | **+239%** |
18+
| table.remove (end) | 25.8 K/s | 8.3 K/s | **+211%** |
19+
| table.concat | 12.2 K/s | 39.5 K/s | -67% (误差?需复查) |
20+
| table.sort (sorted) | 195.6 K/s | 6.4 K/s | **+30x** |
21+
| table.sort (reversed) | 47.1 K/s | 4.2 K/s | **+11x** |
22+
| table.sort (random) | 7.9 K/s | 3.5 K/s | **+2.2x** |
23+
| table.sort (custom cmp) | 3.1 K/s | 1.9 K/s | **+63%** |
24+
| Hash table 插入 (100k) | 0.037s | 0.066s | **+78%** |
25+
| pcall (error) | 4.62 M/s | 0.51 M/s | **+9x** |
26+
| xpcall (error) | 1.22 M/s | 0.43 M/s | **+2.8x** |
27+
| coroutine yield | 2.07 M/s | 0.67 M/s | **+3.1x** |
28+
| producer-consumer | 1.83 M/s | 0.63 M/s | **+2.9x** |
29+
| # operator (length) | 168.5 M/s | 100 M/s | **+68%** |
30+
| Integer division (//) | 138.8 M/s | 78.1 M/s | **+78%** |
31+
| Integer mul/add/mod | 76.6 M/s | 58.8 M/s | **+30%** |
32+
| If-else 分支 | 65.8 M/s | 55.9 M/s | **+18%** |
33+
| string.upper/lower | 6.3 K/s | 4.5 K/s | **+40%** |
34+
| string.gsub | 0.137s | 0.203s | **+48%** |
35+
| string.format (complex) | 725 K/s | 1389 K/s | -48% |
36+
37+
### 🔴 需要优化的领域 (Lua-RS 较慢)
38+
39+
| 测试项 | Lua-RS | 原生 Lua | 差距 | 优先级 |
40+
|--------|--------|----------|------|--------|
41+
| **ipairs 迭代** | 14.7 K/s | 33.0 K/s | **-55%** | 🔥 高 |
42+
| **pairs 迭代** | 13.2 K/s | 32.0 K/s | **-59%** | 🔥 高 |
43+
| **next() 迭代** | 10.4 K/s | 20.8 K/s | **-50%** | 🔥 高 |
44+
| **Upvalue 读写** | 22.9 M/s | 43.5 M/s | **-47%** | 🔥 高 |
45+
| **Method call (colon)** | 3.6 M/s | 7.2 M/s | **-50%** | 🔥 高 |
46+
| **Method call (dot)** | 3.9 M/s | 8.9 M/s | **-56%** | 🔥 高 |
47+
| Inherited method call | 3.4 M/s | 9.4 M/s | **-64%** | 🔥 高 |
48+
| Prototype chain (3级) | 8.7 M/s | 17.9 M/s | **-51%** ||
49+
| Global var access | 42.0 M/s | 71.9 M/s | **-42%** ||
50+
| Local table field | 45.5 M/s | 74.1 M/s | **-39%** ||
51+
| Vararg function | 1.33 M/s | 2.11 M/s | **-37%** ||
52+
| select('#'/n, ...) | 4.2 M/s | 14.5 M/s | **-71%** ||
53+
| Vararg passthrough | 14.6 M/s | 25.6 M/s | **-43%** ||
54+
| coroutine.wrap | 0.64 M/s | 1.67 M/s | **-62%** ||
55+
| While/Repeat 循环 | 93-97 M/s | 123-143 M/s | **-30%** ||
56+
| Bitwise 操作 | 67.8 M/s | 102 M/s | **-34%** ||
57+
| Power (^2) | 20.5 M/s | 53.8 M/s | **-62%** ||
58+
| Float mul/add/div | 64.3 M/s | 102 M/s | **-37%** ||
59+
| string.match | 0.9 M/s | 8.3 M/s | **-89%** ||
60+
| string.char | 4.8 M/s | 12.5 M/s | **-62%** ||
61+
| Concat (4 parts) | 8.5 M/s | 20.0 M/s | **-58%** ||
10562

10663
---
10764

108-
## 优化实现
109-
110-
### fasttm 优化 (Lua 5.4 风格)
111-
112-
参考 Lua 5.4 的 `ltm.h` 中的 `fasttm` 宏,实现了元方法缺失的快速检测:
113-
114-
```rust
115-
// lua_table.rs
116-
pub mod TmFlags {
117-
pub const TM_INDEX: u8 = 1 << 0;
118-
pub const TM_NEWINDEX: u8 = 1 << 1;
119-
pub const TM_GC: u8 = 1 << 2;
120-
pub const TM_MODE: u8 = 1 << 3;
121-
pub const TM_LEN: u8 = 1 << 4;
122-
pub const TM_EQ: u8 = 1 << 5;
123-
pub const TM_CALL: u8 = 1 << 6;
124-
}
125-
126-
pub struct LuaTable {
127-
pub tm_flags: u8, // 缓存元方法不存在的位标志
128-
// ...
129-
}
130-
131-
impl LuaTable {
132-
/// 检查元方法是否已知不存在
133-
pub fn tm_absent(&self, flag: u8) -> bool {
134-
(self.tm_flags & flag) != 0
135-
}
136-
137-
/// 标记元方法不存在
138-
pub fn set_tm_absent(&mut self, flag: u8) {
139-
self.tm_flags |= flag;
140-
}
141-
}
142-
```
143-
144-
**工作原理:**
145-
1. 每个表的元表有一个 `tm_flags` 位域
146-
2. 当查找元方法(如 `__index`)失败时,设置对应位
147-
3. 下次访问时先检查位,如果已设置则跳过哈希查找
148-
4. 当元表被修改时,清除所有标志
149-
150-
**效果:**
151-
- "缺失键 (有元表, 无__index)" 场景:从 55 M/s 提升到 100+ M/s
152-
- 达到 Lua 5.4 同等水平
65+
## 🎯 优化建议 (按优先级排序)
66+
67+
### 🔥 P0: 最高优先级 (核心热点)
68+
69+
#### 1. **迭代器性能 (ipairs/pairs/next)**
70+
- **问题**: 比原生 Lua 慢 50-60%
71+
- **影响**: 迭代是 Lua 最常用的操作之一
72+
- **建议**:
73+
- 优化 `TFORLOOP` / `TFORCALL` 指令实现
74+
- 减少每次迭代的边界检查
75+
- 考虑特化 ipairs/pairs 的快速路径
76+
- 内联 next() 函数调用
77+
78+
#### 2. **Upvalue 访问**
79+
- **问题**: 比原生 Lua 慢 47%
80+
- **影响**: 闭包内访问外部变量是常见模式
81+
- **建议**:
82+
- 优化 `GETUPVAL` / `SETUPVAL` 指令
83+
- 减少 upvalue 间接访问层次
84+
- 考虑 upvalue 的内联缓存
85+
86+
#### 3. **方法调用 (OOP 模式)**
87+
- **问题**: 方法调用慢 50-64%
88+
- **影响**: Lua 的 OOP 依赖元表和 __index
89+
- **建议**:
90+
- 优化 `SELF` 指令
91+
- 缓存 __index 元方法查找
92+
- 考虑内联缓存 (Inline Cache) 机制
93+
94+
### 🔶 P1: 高优先级
95+
96+
#### 4. **全局变量访问**
97+
- **问题**: 比原生 Lua 慢 42%
98+
- **建议**:
99+
- 优化 `GETTABUP` / `SETTABUP` 指令
100+
- 考虑 _ENV 表的特殊优化路径
101+
102+
#### 5. **Vararg 处理**
103+
- **问题**: vararg 函数和 select() 慢 37-71%
104+
- **建议**:
105+
- 优化 `VARARG` 指令
106+
- 减少 vararg 参数的复制开销
107+
- select() 可以特化处理
108+
109+
#### 6. **字符串模式匹配**
110+
- **问题**: string.match 慢 89%
111+
- **建议**:
112+
- 优化 pattern matching 引擎
113+
- 考虑 JIT 编译简单模式
114+
115+
### 🔷 P2: 中等优先级
116+
117+
#### 7. **循环指令**
118+
- While/Repeat 循环慢 30%
119+
- 优化 `LOOP` 相关指令
120+
121+
#### 8. **位运算**
122+
- 比原生慢 34%
123+
- 检查位运算指令实现
124+
125+
#### 9. **浮点运算**
126+
- 比原生慢 37%
127+
- 检查是否有不必要的类型检查
153128

154129
---
155130

156-
## 性能优势领域
131+
## ✅ 已优化的领域
157132

158-
luars 在以下方面**超越** Lua 5.4
133+
以下领域 Lua-RS 表现优秀,无需额外优化
159134

160-
1. **闭包创建**: 163% (11.6 M/s vs 7.1 M/s)
161-
2. **表插入**: 126% (43 M/s vs 34 M/s)
162-
3. **重复 yield**: 367% (2.7 M/s vs 735 K/s)
163-
4. **pcall 失败**: 690% (luars 的错误处理更快)
164-
5. **If-else 分支**: 108%
165-
6. **fasttm 优化场景**: 100-113%
135+
1. **错误处理** - pcall/xpcall 在处理错误时比原生快 3-9 倍
136+
2. **协程 yield** - yield/resume 性能优异
137+
3. **表操作** - insert/remove/sort 等表库函数性能出色
138+
4. **闭包创建** - 创建闭包比原生快 60%
139+
5. **整数运算** - 整数除法和混合运算较快
140+
6. **哈希表插入** - 比原生快 78%
166141

167142
---
168143

169-
## 需要改进的领域
144+
## 📈 下一步行动
170145

171-
1. **函数调用开销**: 36% - 需要优化调用栈管理
172-
2. **全局变量访问**: 43% - `_ENV` 查找较慢
173-
3. **元方法调用**: 19-36% - 元方法调用本身的开销较大
174-
4. **pcall 成功路径**: 19% - 每次 pcall 有较大开销
175-
5. **coroutine.wrap**: 16% - 包装函数创建较慢
146+
1. **Profiling**: 使用 flamegraph 或 perf 分析 ipairs 热点
147+
2. **迭代器重构**: 实现 TFORLOOP 的快速路径
148+
3. **内联缓存**: 为方法调用实现简单的 IC 机制
149+
4. **Upvalue 优化**: 减少间接访问层次
150+
5. **Benchmark 细化**: 添加更细粒度的微基准测试
176151

177152
---
178153

179-
## 结论
154+
## 📝 测试方法
180155

181-
luars 作为 Rust 实现的 Lua 解释器,在整体性能上达到官方 Lua 5.4 的 66%。部分操作(闭包创建、表插入、协程 yield、错误处理)已经超越 Lua 5.4。
156+
```bash
157+
# 编译 release 版本
158+
cargo build --release
182159

183-
实现的 fasttm 优化有效解决了"有元表但无元方法"场景的性能问题,使该场景达到 Lua 5.4 水平。
160+
# 运行性能测试
161+
./run_benchmarks.ps1
162+
```
184163

185-
未来优化方向:
186-
1. 优化函数调用栈管理
187-
2. 改进全局变量 `_ENV` 查找路径
188-
3. 优化元方法调用本身的开销
189-
4. 改进 pcall 成功路径的性能
164+
各测试文件位于 `benchmarks/` 目录下。

0 commit comments

Comments
 (0)