【问题标题】:How can we easily time function calls in elixir?我们如何在 Elixir 中轻松地对函数调用进行计时?
【发布时间】:2015-06-22 12:00:46
【问题描述】:

我们如何在 Elixir 中轻松计时函数调用?

IEx 中是否有任何隐藏开关可以启用此功能?

【问题讨论】:

  • 我认为没有办法这样做。 Erlang 的timer:tc/1-2-3 可能是最简单快捷的方法。
  • @whatyouhide 不确定我做错了什么iex(54)> :timer.tc(Demo.sum 1000) ** (BadFunctionError) expected a function, got: 500500 (stdlib) timer.erl:165: :timer.tc/1
  • 正如您在我在上一条评论中链接的timer:tc/1 的文档中看到的那样,如果您只将一个参数传递给timer:tc,它必须是一个函数。你的例子是:timer.tc(fn -> Demo.sum(1000) end)。如果你想传递一个模块+函数+参数三元组,只需使用:timer.tc(Demo, :sum, [1000])
  • @whatyouhide 谢谢 :timer.tc(Demo, :sum, [1000])
  • @whatyouhide 你的评论应该是一个答案。

标签: function timing elixir


【解决方案1】:

您可以编写一个模块1 来测量给定的功能。以下函数以秒为单位返回给定函数的运行时间:

defmodule Benchmark do
  def measure(function) do
    function
    |> :timer.tc
    |> elem(0)
    |> Kernel./(1_000_000)
  end
end

像这样使用它:

iex> Benchmark.measure(fn -> 123456*654321 end)
9.0e-6

如果您想将其用于基准测试,那么还有另一个答案。

比测量单次运行执行时间更好的方法是测量每个时间范围内的操作。这需要被测代码并在给定的时间范围内重复执行它。这种方法会产生更准确的结果。

您可以使用一个名为 Benchwarmer 的库:

将 Benchwarmer 添加到您的 mix.exs

def deps do
  [ { :benchwarmer, "~> 0.0.2" } ]
end

只需传递一个内联函数:

iex> Benchwarmer.benchmark fn -> 123456*654321 end
*** #Function<20.90072148/0 in :erl_eval.expr/5> ***
1.2 sec     2M iterations   0.61 μs/op

[%Benchwarmer.Results{...}]

【讨论】:

  • 谢谢,如果能把这个构建到 Iex 工具中就好了。
  • 函数 |> :timer.tc |> elem(0) |> Kernel./(1_000_000) 返回的时间单位是多少?是微秒吗?
  • Benchwarmer 版本应该是 "~> 0.0.2" 否则安装依赖会失败。
  • @SashaFonseca 以秒为单位,因为timer.tc 返回微秒。
  • IEx 的 Hex 文档说:“第一个是代码经过真正的评估而不是编译。这意味着在 shell 中进行的任何基准测试都会产生偏差的结果。所以永远不要运行任何在 shell 中进行分析或基准测试。”这适用于这些类型的导入库吗? Aka 这实际上是一个现实的基准吗?
【解决方案2】:

这是一个 6 年前的问题的答案。但是我在搜索这种功能时遇到了这个话题,模块建议暗示着可以做:

{time, your_func_result} = :timer.tc(&your_func/arity, [your_func-args])

我想我会把它放在这里,以防其他人最终搜索它。毕竟下面是 Erlang。所以你不必在模块等中定义另一个函数。时间以微秒为单位。

【讨论】:

    猜你喜欢
    • 2012-01-26
    • 2022-08-11
    • 2011-10-30
    • 1970-01-01
    • 2011-01-21
    • 2020-01-20
    • 1970-01-01
    • 2016-02-06
    • 2011-12-24
    相关资源
    最近更新 更多