7a6163/rubyfast
GitHub: 7a6163/rubyfast
用 Rust 重写的 Ruby 性能静态分析工具,检测 19 种常见性能反模式并支持自动修复,比原版 fasterer 快 40 倍以上。
Stars: 0 | Forks: 0
# rubyfast
[](https://github.com/7a6163/rubyfast/actions/workflows/ci.yml)
[](https://codecov.io/gh/7a6163/rubyfast)
[](https://crates.io/crates/rubyfast)
[](LICENSE)
一个用 Rust 重写的 Ruby 性能检查工具。可检测 Ruby 代码中的 19 种常见性能反模式。
[fasterer](https://github.com/DamirSvrtan/fasterer) 的 Rust 重写版 —— 检测规则相同,但执行速度更快,支持并行文件扫描,且无需 Ruby 运行时依赖。
## 安装
```
cargo install --path .
```
## 使用
```
# 扫描当前目录
rubyfast
# 扫描特定文件
rubyfast path/to/file.rb
# 扫描特定目录
rubyfast path/to/ruby/project
# Auto-fix safe offenses in-place
rubyfast --fix path/to/ruby/project
# 选择输出格式
rubyfast --format file path/to/project # group by file (default)
rubyfast --format rule path/to/project # group by rule
rubyfast --format plain path/to/project # one per line (for CI/grep/reviewdog)
```
如果没有违规项,退出码为 `0`;如果发现任何违规项,退出码为 `1`。
## 输出格式
### `--format file`(默认)
按文件路径对违规项进行分组 —— 紧凑且易于浏览:
```
app/controllers/concerns/lottery_common.rb
L13 Hash#fetch with second argument is slower than Hash#fetch with block
L94 Hash#fetch with second argument is slower than Hash#fetch with block
app/controllers/api/v1/health_articles_controller.rb
L11 Hash#fetch with second argument is slower than Hash#fetch with block
```
支持 `--fix` 的违规项会标记为 `(fixable)`,摘要行会显示有多少项可以自动修复:
```
tests/fixtures/19_for_loop.rb
L1 For loop is slower than using each (fixable)
22 files inspected, 41 offenses detected, 21 offenses autocorrectable (run rubyfast --fix)
```
### `--format rule`
按规则对违规项进行分组 —— 适用于了解哪些模式最常见:
```
Hash#fetch with second argument is slower than Hash#fetch with block. (3 offenses)
app/controllers/api/v1/health_articles_controller.rb:11
app/controllers/concerns/lottery_common.rb:13
app/controllers/concerns/lottery_common.rb:94
```
### `--format plain`
每行显示一个违规项 —— 适用于 grep、reviewdog 和 CI 流水线:
```
app/controllers/api/v1/health_articles_controller.rb:11 Hash#fetch with second argument is slower than Hash#fetch with block.
```
## 自动修复
`rubyfast --fix` 会就地自动修正 8 个安全的违规项:
| # | 模式 | 修复 |
|---|---------|-----|
| 1 | `.shuffle.first` | `.sample` |
| 2 | `.select{}.first` | `.detect{}` |
| 4 | `.reverse.each` | `.reverse_each` |
| 5 | `.keys.each` | `.each_key` |
| 6 | `.map{}.flatten(1)` | `.flat_map{}` |
| 7 | `.gsub("x","y")` | `.tr("x","y")` |
| 13 | `(1..10).include?` | `.cover?` |
| 19 | `for x in arr` | `arr.each do \|x\|` |
修复会按倒序字节位置应用并进行语法验证 —— 如果修复会导致无效的 Ruby 代码,文件将保持不变。
## 检测到的违规项
| # | 模式 | 建议 | 自动修复 |
|---|---------|------------|----------|
| 1 | `.shuffle.first` | `.sample` | 是 |
| 2 | `.select{}.first` | `.detect{}` | 是 |
| 3 | `.select{}.last` | `.reverse.detect{}` | 否 |
| 4 | `.reverse.each` | `.reverse_each` | 是 |
| 5 | `.keys.each` | `.each_key` | 是 |
| 6 | `.map{}.flatten(1)` | `.flat_map{}` | 是 |
| 7 | `.gsub("x","y")` (单字符) | `.tr("x","y")` | 是 |
| 8 | `.sort { \|a,b\| ... }` | `.sort_by` | 否 |
| 9 | `.fetch(k, v)` | `.fetch(k) { v }` | 否 |
| 10 | `.merge!({k: v})` | `h[k] = v` | 否 |
| 11 | `.map { \|x\| x.foo }` | `.map(&:foo)` | 否 |
| 12 | `.each_with_index` | `while` 循环 | 否 |
| 13 | `(1..10).include?` | `.cover?` | 是 |
| 14 | `.module_eval("def ...")` | `define_method` | 否 |
| 15 | `rescue NoMethodError` | `respond_to?` | 否 |
| 16 | `def foo(&block); block.call; end` | `yield` | 否 |
| 17 | `def x; @x; end` | `attr_reader` | 否 |
| 18 | `def x=(v); @x=v; end` | `attr_writer` | 否 |
| 19 | `for x in arr` | `arr.each` | 是 |
## 行内禁用
使用行内注释禁止特定违规项(类似于 RuboCop):
```
# 在同一行禁用
x = [].shuffle.first # rubyfast:disable shuffle_first_vs_sample
# 禁用下一行
# rubyfast:disable-next-line shuffle_first_vs_sample
x = [].shuffle.first
# 块禁用/启用
# rubyfast:disable for_loop_vs_each
for i in arr
puts i
end
# rubyfast:enable for_loop_vs_each
# 禁用所有规则
code # rubyfast:disable all
# 多个规则
code # rubyfast:disable shuffle_first_vs_sample, for_loop_vs_each
# 与 fasterer 向后兼容
code # fasterer:disable shuffle_first_vs_sample
```
## 配置
在项目根目录下创建 `.rubyfast.yml`(或为了向后兼容使用 `.fasterer.yml`)以禁用特定检查或排除文件:
```
speedups:
shuffle_first_vs_sample: true
for_loop_vs_each: false # disable this check
exclude_paths:
- vendor/**/*.rb
- tmp/**/*.rb
```
配置文件通过从扫描目录向上遍历自动发现。如果两者同时存在,`.rubyfast.yml` 优先。
## CI/CD 集成
### GitHub Action
```
- uses: 7a6163/rubyfast-action@v1
```
配合 [reviewdog](https://github.com/reviewdog/reviewdog) 进行行内 PR 评论(内部使用 `--format plain`):
```
rubyfast:
runs-on: ubuntu-latest
permissions:
contents: read
checks: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: 7a6163/rubyfast-action@v1
with:
reviewdog: "true"
github-token: ${{ secrets.GITHUB_TOKEN }}
reviewdog-reporter: github-pr-review
```
查看 [rubyfast-action](https://github.com/7a6163/rubyfast-action) 了解所有选项。
### GitLab CI
```
rubyfast:
image:
name: ghcr.io/7a6163/rubyfast:latest
entrypoint: [""]
script:
- rubyfast .
```
### Docker
```
docker run --rm -v $(pwd):/workspace ghcr.io/7a6163/rubyfast:latest .
```
## 基准测试
使用 [hyperfine](https://github.com/sharkdp/hyperfine) 与原始 [fasterer](https://github.com/DamirSvrtan/fasterer) Ruby gem (v0.11.0) 进行对比。在 Apple Silicon、macOS 上测量。
### 大型项目(17,091 个 Ruby 文件)
| 命令 | 平均值 | 最小值 | 最大值 | 相对值 |
|:---|---:|---:|---:|---:|
| `rubyfast` | 3,445 ms | 3,421 ms | 3,464 ms | **1.00** |
| `fasterer` | 150,122 ms | 148,309 ms | 151,609 ms | 慢 43.57 倍 |
### 小型项目:22 个测试固件
| 命令 | 平均值 | 最小值 | 最大值 | 相对值 |
|:---|---:|---:|---:|---:|
| `rubyfast` | 4.6 ms | 3.3 ms | 15.1 ms | **1.00** |
| `fasterer` | 488.7 ms | 483.1 ms | 510.7 ms | 慢 105.57 倍 |
在真实代码库上**快约 44–106 倍**。Rust 实现可在 3.4 秒内处理 17,000 多个 Ruby 文件,而 Ruby gem 需要超过 2.5 分钟。
## 开发
```
cargo build
cargo test
cargo clippy -- -D warnings
```
## 许可证
MIT
标签:Cargo, CI/CD 集成, Fasterer 替代品, Java RMI, Linter, pptx, Ruby, Rust, 代码检查工具, 可视化界面, 威胁情报, 并行处理, 开发者工具, 性能优化, 性能反模式检测, 检测绕过, 知识库, 网络流量审计, 自动修复, 请求拦截, 跨语言重写, 通知系统, 错误基检测, 静态代码分析