0Pricing
Ruby Academy · 课时

测量性能

Benchmark 模块

测量性能 是 CoddyKit 上的免费 Ruby Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Ruby Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Ruby Academy 课程共包含 4 节课。

为什么要测量?

不进行测量就优化,等同于猜测。Ruby 标准库中的 Benchmark 模块可以精确地为代码计时。

  • 在修改之前找出速度较慢的部分
  • 客观地比较不同实现
  • 避免过早优化
require 'benchmark'

time = Benchmark.realtime do
  1_000_000.times { |i| i * 2 }
end
puts "Took #{time.round(4)}s"

Benchmark.measure

Benchmark.measure 返回包含用户时间、系统时间和实际时间的 report。

  • 用户时间是代码消耗的 CPU 时间
  • 实际时间是挂钟经过的时间
require 'benchmark'

result = Benchmark.measure do
  500_000.times { |i| i.to_s }
end
puts result

Benchmark.bm

Benchmark.bm 在表格中运行多个代码块并为其添加标签。

  • 传入标签宽度以便对齐
  • 每个 x.report 都是一行
require 'benchmark'

Benchmark.bm(10) do |x|
  x.report('to_s:') { 100_000.times { |i| i.to_s } }
  x.report('inspect:') { 100_000.times { |i| i.inspect } }
end

Benchmark.bmbm

Benchmark.bmbm 会先运行一次预演,以预热缓存和垃圾回收器,从而得到更公平的数值。

  • 第一次运行的结果会被丢弃
  • 第二次运行才是真正的测量
require 'benchmark'

Benchmark.bmbm do |x|
  x.report('sum:') { (1..100_000).sum }
  x.report('reduce:') { (1..100_000).reduce(:+) }
end

用于快速计时的 realtime

Benchmark.realtime 只返回以浮点数表示的挂钟秒数。

  • 为一个代码块计时的最简单方式
  • 适合临时检查
require 'benchmark'

elapsed = Benchmark.realtime do
  arr = Array.new(100_000) { rand }
  arr.sort
end
puts "Sorted in #{elapsed.round(4)}s"

单调时钟

如果需要不受系统时钟变化影响的精确计时,请将 Process.clock_gettime 与单调时钟结合使用。

  • 不受 NTP 调整影响
  • 最准确的内置选项
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
200_000.times { |i| i * i }
finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
puts "Elapsed: #{(finish - start).round(4)}s"

比较两种方法

比较不同方案时,基准测试最能发挥作用。请在相同的负载下运行两种方案。

  • 保持足够大的输入规模,以便测量
  • 重复运行以减少噪声
require 'benchmark'

arr = (1..100_000).to_a
Benchmark.bm(8) do |x|
  x.report('map:') { arr.map { |n| n * 2 } }
  x.report('each:') { r = []; arr.each { |n| r << n * 2 } }
end

警惕微型基准测试

微型基准测试可能会误导您。

  • 即时编译和缓存可能无法反映真实工作负载
  • 垃圾回收器可能在测量过程中运行
  • 请测量符合实际的数据规模
require 'benchmark'

# Too small to be meaningful
t = Benchmark.realtime { 10.times { |i| i + 1 } }
puts "Misleadingly tiny: #{t}s"

每秒迭代次数

您通常会关注吞吐量,也就是每秒可以执行多少次操作。benchmark-ips gem 会报告这一指标,但您也可以手动进行近似计算。

  • 在固定的时间窗口内统计迭代次数
  • 每秒迭代次数越高,速度越快
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + 0.2
count = 0
while Process.clock_gettime(Process::CLOCK_MONOTONIC) < deadline
  count += 1
  'hello'.upcase
end
puts "Iterations in 0.2s: #{count}"

控制垃圾回收器

垃圾回收器可能会使结果产生偏差。您可以暂时禁用它,以获得更稳定的数值。

  • 之前使用 GC.disable,之后使用 GC.enable
  • 请谨慎使用,以免内存持续增长
require 'benchmark'

GC.disable
t = Benchmark.realtime { 100_000.times { |i| i.to_s } }
GC.enable
puts "Without GC: #{t.round(4)}s"

对多次运行取平均值

多次运行基准测试并取平均值,可以平滑差异。

  • 如有需要,丢弃最慢的离群值
  • 报告中位数以提高稳定性
require 'benchmark'

times = 3.times.map do
  Benchmark.realtime { (1..50_000).map { |n| n * n } }
end
avg = times.sum / times.size
puts "Average: #{avg.round(4)}s"

快速检查

测试您对基准测试的了解。

回顾

您学会了测量性能:

  • Benchmark 模块可以准确地为代码计时
  • realtime、measure、bm 和 bmbm 适用于不同需求
  • 使用单调时钟进行精确计时
  • 避免会产生误导的微型基准测试,并考虑垃圾回收器的影响
  • 对多次运行取平均值,以减少噪声

接下来您将使用专门的性能分析工具。

常见问题解答

「测量性能」课时是免费的吗?

是的 — 「测量性能」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Ruby Academy 课程的其余内容,请升级到 CoddyKit PRO。 Ruby Academy 课程共包含 4 节课。

「测量性能」这节课中我会学到什么?

Benchmark 模块 你通过在浏览器中直接运行的动手代码来练习 Ruby Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Ruby Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Ruby Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「测量性能」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Ruby Academy 课中编写并运行代码吗?

能。每节 Ruby Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 测量性能
  2. 性能分析工具
  3. 内存优化
  4. 常见瓶颈
← 返回 Ruby Academy