为什么函数运行速度越快我调用的越多?

时间:2016-03-16 10:37:05

标签: benchmarking elixir

我试图在尝试优化函数之前尝试执行函数。 (代码是Elixir,但我使用的是Erlang' :timer.tc。)

我的一般方法是"多次运行,然后计算平均持续时间。"但平均值越大,我运行的次数越多(达到一定程度)。

一个例子:

some_func = fn ->
  # not my actual function; it's a pure function,
  # but exhibits the same speedup
  :rand.uniform() 
end

run_n_times = fn (count, func) ->
  Enum.each(1..count, fn (_i) ->
    func.()
  end)
end

n = 20

{microseconds, :ok} = :timer.tc(run_n_times, [n, some_func])
IO.puts "#{microseconds / n} microseconds per call (#{microseconds} total for #{n} calls)"

增加n值的输出就像这样(格式轻微):

174.8       microseconds per call (3496    total for 20      calls )
21.505      microseconds per call (4301    total for 200     calls )
4.5755      microseconds per call (9151    total for 2000    calls )
0.543415    microseconds per call (108683  total for 200000  calls )
0.578474    microseconds per call (578474  total for 1000000 calls )
0.5502955   microseconds per call (1100591 total for 2000000 calls )
0.556457    microseconds per call (2225828 total for 4000000 calls )
0.544754125 microseconds per call (4358033 total for 8000000 calls )

为什么函数运行速度越快,我称之为基准测试的结果是什么?例如,是否存在像#34;运行某些> = 200k次的经验法则为了基准"?

3 个答案:

答案 0 :(得分:5)

由于你的功能非常快(基本上什么也没做),我认为你在这里看到的是设置的开销,而不是函数运行时的任何加速。在这种情况下,在开始运行函数之前,您必须构造一个范围,构造一个匿名函数并调用Enum.each函数。对于少量重复,这些因素可能对基准测试的整体运行时间的贡献大于实际重复次数。

答案 1 :(得分:0)

我是PawełObrok在他的回答中写的第二个。您可以通过在循环内多次调用函数来优化代码:

<ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyleSmall"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="45dp"
    android:padding="5dp"
    android:visibility="gone" />

这是10个电话,但你可以100或1000个。你在同一个循环中做的越多,开销就越小。

答案 2 :(得分:0)

我不知道Erlang到底做了什么,但是如果你在Javascript中使用现代Javascript解释器做同样的事情,那么前几个调用将被解释(慢)。然后解释器会发现你正在调用这个函数并用一个快速而脏的编译器编译它。另外一百个调用,并且解释器通过适当的编译器计算出正在发生的事情并再次编译它。另外一千次调用,它再次使用高度优化的编译器进行编译。那样可以准确地给出你找到的那种数字。