7a6163/rubyfast

GitHub: 7a6163/rubyfast

用 Rust 重写的 Ruby 性能静态分析工具,检测 19 种常见性能反模式并支持自动修复,比原版 fasterer 快 40 倍以上。

Stars: 0 | Forks: 0

# rubyfast [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/31fda4dbf0155537.svg)](https://github.com/7a6163/rubyfast/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/7a6163/rubyfast/graph/badge.svg)](https://codecov.io/gh/7a6163/rubyfast) [![Crates.io](https://img.shields.io/crates/v/rubyfast)](https://crates.io/crates/rubyfast) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](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, 代码检查工具, 可视化界面, 威胁情报, 并行处理, 开发者工具, 性能优化, 性能反模式检测, 检测绕过, 知识库, 网络流量审计, 自动修复, 请求拦截, 跨语言重写, 通知系统, 错误基检测, 静态代码分析