## 26.基准
基准是一种度量。 你可以测量代码运行所需的时间。 所以,为什么这么重要? 随着你成为更认真的编码人员,完成一件工作就不再重要了。 重要的是你编写代码的程度以及代码在实时环境中的性能。 你必须知道编写快速运行的代码。 要检查你的代码片段是否比其他代码片段更快,可以使用基准测试。
以下面的示例为例,输入并运行
```rb
# benchmark.rb
require 'benchmark'
Benchmark.bm do|b|
b.report("+= ") do
a = ""
1_000_000.times { a += "." }
end
b.report("<< ") do
a = ""
1_000_000.times { a << "." }
end
end
```
输出量
```rb
user system total real
+= 55.030000 7.320000 62.350000 ( 62.303848)
<< 0.160000 0.000000 0.160000 ( 0.168452)
```
因此,让我遍历代码,在`require 'benchmark'`行中,基准测试库作为 Ruby 标准发行版的一部分包含在内,因此你可以要求此代码在文件中不必大惊小怪。
现在让我们看一下这个块
```rb
Benchmark.bm do|b|
………….
end
```
它有什么作用? 首先,我们在`Benchmark`类中调用名为`bm`的函数,并在`do`和`end`之间传递一个块。 现在,让我们看看该块中的内容
```rb
Benchmark.bm do|b|
b.report("+= ") do
a = ""
1_000_000.times { a += "." }
end
b.report("<< ") do
a = ""
1_000_000.times { a << "." }
end
end
```
参见上面的代码。 我们正在使用`b.report("+= ")`准备报告,可以将将在输出中打印的任何字符串传递给报告函数。 如果查看输出的第二行`+= 55.030000 7.320000 62.350000 ( 62.303848)`,则会打印`+=`,因为`“+=”`已传递到`b.report()`。
`b.report()``打开一个代码块,你可以将任何需要基准标记的内容传递给该代码块。 在这里,我们传递了如下所示的代码片段
```rb
b.report("+= ") do
a = ""
1_000_000.times { a += "." }
end
```
因此,我们为 a 分配了一个空字符串,并使用`+=`运算符对其添加了一百万次。 我们得到这个
```rb
user system total real
+= 55.030000 7.320000 62.350000 ( 62.303848)
```
输出显示总共花费 62.35 秒,这是非常安静的。 现在让我们来看看第二个块
```rb
b.report("<< ") do
a = ""
1_000_000.times { a << "." }
end
```
在这里,我们执行的操作与第一个相同,但是我们使用`<<`运算符而不是`+=`,这将产生以下输出,如下所示
```rb
user system total real
+= 55.030000 7.320000 62.350000 ( 62.303848)
<< 0.160000 0.000000 0.160000 ( 0.168452)
```
因此,使用`<<`仅需 0.1685 秒,因此在字符串连接方面,`<<`远优于`+=`。
现在,让我们看看其他内容。 你们都知道计算机有内存。 当程序运行时,它需要记住事情并消耗一些内存,有时当可用内存变少时,Ruby 解释器将清理内存。 这称为垃圾收集 <sup class="footnote">[ [62](#_footnotedef_62 "View footnote.") ]</sup> 。 就像你的城市或市政当局收集垃圾一样,城市运行正常。 现在想想,如果不收集垃圾,而你遇到的垃圾会流到街道上,整个城市步履蹒跚,事情真的会变慢,那将会发生什么。 同样,如果程序运行足够长的时间可以更好地收集垃圾,否则,运行的新代码可能会变慢,并且如果对它进行基准测试,则可能会显示错误的结果。
现在,在文本编辑器中键入以下程序并运行它。
```rb
# benchmark_2.rb
require 'benchmark'
puts "Testing without cleaning up"
Benchmark.bm do|b|
b.report("+=") do
a = ""
100_000.times { a += "." }
end
b.report("<<") do
a = ""
1_000_000.times { a << "." }
end
end
GC.start
puts
puts "Testing with cleaning up"
Benchmark.bmbm do|b|
b.report("+=") do
a = ""
100_000.times { a += "." }
end
b.report("<<") do
a = ""
100_000.times { a << "." }
end
end
```
Output
```rb
Testing without cleaning up
user system total real
+= 0.550000 0.220000 0.770000 ( 0.773730)
<< 0.150000 0.010000 0.160000 ( 0.159381)
Testing with cleaning up
Rehearsal --------------------------------------
+= 0.520000 0.180000 0.700000 ( 0.687914)
<< 0.010000 0.010000 0.020000 ( 0.018958)
----------------------------- total: 0.720000sec
user system total real
+= 0.530000 0.120000 0.650000 ( 0.650013)
<< 0.010000 0.000000 0.010000 ( 0.015668)
```
如果你看到此代码产生的第一个基准测试
```rb
puts "Testing without cleaning up"
Benchmark.bm do|b|
b.report("+=") do
a = ""
100_000.times { a += "." }
end
b.report("<<") do
a = ""
1_000_000.times { a << "." }
end
end
```
在此,我们使用`Benchmark.bm`并像往常一样运行它,它将生成以下输出:
```rb
Testing without cleaning up
user system total real
+= 0.550000 0.220000 0.770000 ( 0.773730)
<< 0.150000 0.010000 0.160000 ( 0.159381)
```
基准总计分别为 0.77 和 0.16 秒。 在此块之后,我们有这些行
```rb
GC.start
puts
```
在这些行中,我们正在收集垃圾或释放该程序已使用的内存。 现在我们运行另一个由该代码块定义的基准
```rb
puts "Testing with cleaning up"
Benchmark.bmbm do|b|
b.report("+=") do
a = ""
100_000.times { a += "." }
end
b.report("<<") do
a = ""
100_000.times { a << "." }
end
end
```
那么`Benchmark.bmbm`的作用是什么? 直到这次我们使用`Benchmark.bm`! 在上述代码中,我们有两个基准正在运行。 `bmbm`确保在完成第一个基准测试之后,进行垃圾回收并释放内存,以便下一个工作在垃圾回收环境中运行,从而获得更好的准确结果。 这是第二个此代码生成的输出
```rb
Testing with cleaning up
Rehearsal --------------------------------------
+= 0.520000 0.180000 0.700000 ( 0.687914)
<< 0.010000 0.010000 0.020000 ( 0.018958)
----------------------------- total: 0.720000sec
```
如果你可以比较不带 GC 的`100_000.times { a << "." }`的输出和带 GC 的`100_000.times { a << "." }`的输出,分别为 0.16 秒和 0.02 秒。 现在,我想你会意识到垃圾收集的需要,无论是在城市中还是在编程中。
- 前言
- 红宝石
- 先决条件
- 1.安装 Ruby
- 2.在线资源
- 3.入门
- 4.比较与逻辑
- 5.循环
- 6.数组
- 7.哈希和符号
- 8.范围
- 9.功能
- 10.可变范围
- 11.类&对象
- 12.安全导航
- 13.打破大型程序
- 14.结构和 OpenStruct
- 15. Rdoc
- 16. Ruby 样式指南
- 17.模块和混入
- 18.日期和时间
- 19.文件
- 20. Proc,Lambda 和块
- 21.多线程
- 22.异常处理
- 23.正则表达式
- 24.宝石
- 25.元编程
- 26.基准
- 27.测试驱动开发
- 28.观察者模式
- 29.模板模式
- 30.工厂模式
- 31.装饰图案
- 32.适配器模式
- 33.单例模式
- 34.复合模式
- 35.建造者模式
- 36.策略模式
- 赞助商
- 捐
- 人们怎么说
- 版权
- 取得这本书