class Minitest::Benchmark
继承 Benchmark
以创建您自己的基准测试运行。以“bench_”开头的方法将在每个类上执行。
公共类方法
返回一组范围,这些范围从 min
到 max
以 base
的幂指数方式递增。例如
bench_exp(2, 16, 2) # => [2, 4, 8, 16]
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 35 def self.bench_exp min, max, base = 10 min = (Math.log10(min) / Math.log10(base)).to_i max = (Math.log10(max) / Math.log10(base)).to_i (min..max).map { |m| base ** m }.to_a end
返回一组范围,这些范围从 min
到 max
以 step
线性递增。例如
bench_linear(20, 40, 10) # => [20, 30, 40]
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 48 def self.bench_linear min, max, step = 10 (min..max).step(step).to_a end
指定用于该类的基准测试的范围。默认为从 1 到 10k 以 10 的幂指数增长。如果您需要不同的基准测试范围,请覆盖此方法。
另请参阅:::bench_exp
和 ::bench_linear
。
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 59 def self.bench_range bench_exp 1, 10_000 end
公共实例方法
运行给定的 work
,收集每次运行的时间。然后将范围和时间传递给给定的 validation
proc。输出基准测试名称和时间,以制表符分隔的格式,使其易于粘贴到电子表格中进行绘图或进一步分析。
范围由 ::bench_range
指定。
例如
def bench_algorithm validation = proc { |x, y| ... } assert_performance validation do |n| @obj.algorithm(n) end end
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 81 def assert_performance validation, &work range = self.class.bench_range io.print self.name times = [] range.each do |x| GC.start t0 = Minitest.clock_time instance_exec(x, &work) t = Minitest.clock_time - t0 io.print "\t%9.6f" % t times << t end io.puts validation[range, times] end
运行给定的 work
并断言收集的时间符合给定的 threshold
内的常数速率(例如,线性斜率 == 0)。注意:因为我们正在测试斜率为 0,所以 R^2 不是拟合的良好决定因素,因此阈值会应用于斜率本身。因此,您可能需要从默认值收紧它。
有关更多详细信息,请参阅 www.graphpad.com/guides/prism/8/curve-fitting/reg_intepretingnonlinr2.htm。
拟合由 fit_linear
计算。
范围由 ::bench_range
指定。
例如
def bench_algorithm assert_performance_constant 0.9999 do |n| @obj.algorithm(n) end end
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 125 def assert_performance_constant threshold = 0.99, &work validation = proc do |range, times| a, b, rr = fit_linear range, times assert_in_delta 0, b, 1 - threshold [a, b, rr] end assert_performance validation, &work end
运行给定的 work
并断言收集的时间符合给定的误差 threshold
内的指数曲线。
拟合由 fit_exponential
计算。
范围由 ::bench_range
指定。
例如
def bench_algorithm assert_performance_exponential 0.9999 do |n| @obj.algorithm(n) end end
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 151 def assert_performance_exponential threshold = 0.99, &work assert_performance validation_for_fit(:exponential, threshold), &work end
运行给定的 work
并断言收集的时间符合给定的误差 threshold
内的直线。
拟合由 fit_linear
计算。
范围由 ::bench_range
指定。
例如
def bench_algorithm assert_performance_linear 0.9999 do |n| @obj.algorithm(n) end end
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 191 def assert_performance_linear threshold = 0.99, &work assert_performance validation_for_fit(:linear, threshold), &work end
运行给定的 work
并断言收集的时间符合给定的误差 threshold
内的对数曲线。
拟合由 fit_logarithmic
计算。
范围由 ::bench_range
指定。
例如
def bench_algorithm assert_performance_logarithmic 0.9999 do |n| @obj.algorithm(n) end end
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 171 def assert_performance_logarithmic threshold = 0.99, &work assert_performance validation_for_fit(:logarithmic, threshold), &work end
运行给定的 work
并断言收集的时间曲线拟合符合给定的误差 threshold
内的幂曲线。
拟合由 fit_power
计算。
范围由 ::bench_range
指定。
例如
def bench_algorithm assert_performance_power 0.9999 do |x| @obj.algorithm end end
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 211 def assert_performance_power threshold = 0.99, &work assert_performance validation_for_fit(:power, threshold), &work end
获取 x/y 对的数组并计算一般的 R^2 值。
请参阅:en.wikipedia.org/wiki/Coefficient_of_determination
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 220 def fit_error xys y_bar = sigma(xys) { |_, y| y } / xys.size.to_f ss_tot = sigma(xys) { |_, y| (y - y_bar) ** 2 } ss_err = sigma(xys) { |x, y| (yield(x) - y) ** 2 } 1 - (ss_err / ss_tot) end
要拟合函数形式:y = ae^(bx)。
获取 x 和 y 值并返回 [a, b, r^2]。
请参阅:mathworld.wolfram.com/LeastSquaresFittingExponential.html
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 235 def fit_exponential xs, ys n = xs.size xys = xs.zip ys sxlny = sigma(xys) { |x, y| x * Math.log(y) } slny = sigma(xys) { |_, y| Math.log(y) } sx2 = sigma(xys) { |x, _| x * x } sx = sigma xs c = n * sx2 - sx ** 2 a = (slny * sx2 - sx * sxlny) / c b = ( n * sxlny - sx * slny ) / c return Math.exp(a), b, fit_error(xys) { |x| Math.exp(a + b * x) } end
拟合函数形式:a + bx。
获取 x 和 y 值并返回 [a, b, r^2]。
请参阅:mathworld.wolfram.com/LeastSquaresFitting.html
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 279 def fit_linear xs, ys n = xs.size xys = xs.zip ys sx = sigma xs sy = sigma ys sx2 = sigma(xs) { |x| x ** 2 } sxy = sigma(xys) { |x, y| x * y } c = n * sx2 - sx**2 a = (sy * sx2 - sx * sxy) / c b = ( n * sxy - sx * sy ) / c return a, b, fit_error(xys) { |x| a + b * x } end
要拟合函数形式:y = a + b*ln(x)。
获取 x 和 y 值并返回 [a, b, r^2]。
请参阅:mathworld.wolfram.com/LeastSquaresFittingLogarithmic.html
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 257 def fit_logarithmic xs, ys n = xs.size xys = xs.zip ys slnx2 = sigma(xys) { |x, _| Math.log(x) ** 2 } slnx = sigma(xys) { |x, _| Math.log(x) } sylnx = sigma(xys) { |x, y| y * Math.log(x) } sy = sigma(xys) { |_, y| y } c = n * slnx2 - slnx ** 2 b = ( n * sylnx - sy * slnx ) / c a = (sy - b * slnx) / n return a, b, fit_error(xys) { |x| a + b * Math.log(x) } end
要拟合函数形式:y = ax^b。
获取 x 和 y 值并返回 [a, b, r^2]。
请参阅:mathworld.wolfram.com/LeastSquaresFittingPowerLaw.html
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 301 def fit_power xs, ys n = xs.size xys = xs.zip ys slnxlny = sigma(xys) { |x, y| Math.log(x) * Math.log(y) } slnx = sigma(xs) { |x | Math.log(x) } slny = sigma(ys) { | y| Math.log(y) } slnx2 = sigma(xs) { |x | Math.log(x) ** 2 } b = (n * slnxlny - slnx * slny) / (n * slnx2 - slnx ** 2) a = (slny - b * slnx) / n return Math.exp(a), b, fit_error(xys) { |x| (Math.exp(a) * (x ** b)) } end
迭代 enum
,如果给定 block
,则映射 block
,返回结果的总和。例如
sigma([1, 2, 3]) # => 1 + 2 + 3 => 6 sigma([1, 2, 3]) { |n| n ** 2 } # => 1 + 4 + 9 => 14
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 322 def sigma enum, &block enum = enum.map(&block) if block enum.sum end
返回一个 proc,该 proc 调用指定的拟合方法并断言误差在可容忍的阈值内。
# File minitest-5.25.4/lib/minitest/benchmark.rb, line 331 def validation_for_fit msg, threshold proc do |range, times| a, b, rr = send "fit_#{msg}", range, times assert_operator rr, :>=, threshold [a, b, rr] end end