Some benchmarks are measured with wrong approach
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 38/100
- Issue 类型
- 缺陷
- 描述清晰度
- 基本清楚
- 活跃度
- 停滞
- 技术栈
- ruby
- 领域
- performance
调研方向
从 code/array/length-vs-size-vs-count.rb 开始,这是 issue 中明确链接的 benchmark,并检查其 Benchmark.ips 报告块。将当前基于块的方法与这里描述的 benchmark-ips 字符串报告形式进行比较。当受影响的小操作 benchmark 使用开销更低的方法并且其结果已更新时,即视为完成;issue 没有列出所有受影响的文件。
由索引模型根据 Issue 内容生成。
描述
tl;dr When we measure small things we have to remove all overheads which have impact. Wrapping with a method and block call is quite big overhead for most of benchmarks in this repository.
Suppose you want compare performance of "2 + 3" vs "2 * 3" calls. If you do it with a approach used in this repository you will get this results:
require "benchmark/ips"
def slow
2 * 2
end
def fast
2 + 2
end
Benchmark.ips do |x|
x.report("2 * 2") { slow }
x.report("2 + 2") { fast }
x.compare!
end
(simplified output)
Comparison:
2 + 2: 8304760.0 i/s
2 * 2: 7535516.6 i/s - 1.10x slower
But there is one problem. Calling a method + surrounding block ({ slow }) has bigger overhead than calling Fixnum#+ or Fixnum#* itself. Thea easiest way to observe it is to repeat benchmarked operations in one call. Like this:
require "benchmark/ips"
def slow
2*2; 2*2; 2*2; 2*2; 2*2; 2*2; 2*2; 2*2; 2*2; 2*2;
end
def fast
2+2; 2+2; 2+2; 2+2; 2+2; 2+2; 2+2; 2+2; 2+2; 2+2;
end
Benchmark.ips do |x|
x.report("2 * 2") { slow }
x.report("2 + 2") { fast }
x.compare!
end
Comparison:
2 + 2: 4680545.3 i/s
2 * 2: 3468681.3 i/s - 1.35x slower
See how results changed? Writing our benchmarks in this way would be quite problematic. Fortunately benchmark-ips gem has answer for that. Benchmark::IPS::Job#report method allows to pass string which will be compiled before benchmark is run. Passing right string allows to measure it properly:
require "benchmark/ips"
Benchmark.ips do |x|
x.report("2 * 2", "2 * 2;" * 1_000)
x.report("2 + 2", "2 + 2;" * 1_000)
x.compare!
end
Comparison:
2 + 2: 91567.5 i/s
2 * 2: 57994.4 i/s - 1.58x slower
This is greatly explained here: https://docs.omniref.com/ruby/2.2.1/symbols/Benchmark/bm#annotation=4095926&line=182
How does this affect fast-ruby benchmarks? All benchmarks that call small things are flawed. One of them is Array#length vs Array#size vs Array#count benchmark. Here is the original code and result obtained on my computer:
require 'benchmark/ips'
ARRAY = [*1..100]
Benchmark.ips do |x|
x.report("Array#length") { ARRAY.length }
x.report("Array#size") { ARRAY.size }
x.report("Array#count") { ARRAY.count }
x.compare!
end
Comparison:
Array#size: 8679483.2 i/s
Array#length: 8664450.7 i/s - 1.00x slower
Array#count: 7237299.5 i/s - 1.20x slower
The same benchmark measure with described approach gives different numbers:
require 'benchmark/ips'
ARRAY = [*1..100]
Benchmark.ips do |x|
x.report("Array#length", "ARRAY.length;" * 1_000)
x.report("Array#size", "ARRAY.size;" * 1_000)
x.report("Array#count", "ARRAY.count;" * 1_000)
x.compare!
end
Comparison:
Array#size: 113902.4 i/s
Array#length: 113655.9 i/s - 1.00x slower
Array#count: 28753.4 i/s - 3.96x slower
Difference: 1.20x slower vs 3.96x slower.
My guess is that it affects most of benchmarks.
- 主要语言
- Ruby
- 星标
- 5.7k
- 派生
- 370
- PR 合并指标
- 30 天内没有已合并 PR
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
fastruby/fast-ruby 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 52/100
-
难度 4/5 3-5 天 新手友好度 32/100
-
难度 3/5 1-2 天 新手友好度 35/100
-
难度 2/5 1-3 小时 新手友好度 45/100
-
难度 4/5 3-5 天 新手友好度 42/100
查看 fastruby/fast-ruby 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 75/100
palladius/rails8-app-on-gcp#145 ·
-
难度 2/5 1-3 小时 新手友好度 75/100
-
难度 2/5 1-3 小时 新手友好度 75/100
rubocop/rubocop-rspec#2236 ·
-
bug
难度 2/5 1-3 小时 新手友好度 70/100
riscv/riscv-unified-db#2624 · 1 个 reaction ·
-
难度 1/5 1 小时以内 新手友好度 88/100