【问题标题】:Alternatives to erlang:get_stacktrace/0 for getting information on the caller of a function?erlang:get_stacktrace/0 的替代方法,用于获取函数调用者的信息?
【发布时间】:2016-04-16 00:25:50
【问题描述】:

我正在处理一个从我们现有代码库中相对热门的代码路径调用的函数。该函数所做的第一件事是在 try catch 块中调用 erlang:get_stacktrace/0 以便我们可以获取堆栈跟踪:

the_function() ->  
  [_|Trace] = try error(x) of
     _ -> error(impossible)
  catch 
     error:x -> erlang:get_stacktrace()
  end,
  ...

我们保留堆栈跟踪,以便获得有关函数调用者的信息。我读过erlang:get_stacktrace/0 并不总是一个便宜的调用函数(http://erlang.org/pipermail/erlang-questions/2013-November/075928.html)。由于这是在热代码路径上,我想用更简单的东西替换它。有没有其他方法可以让我获得有关调用函数的信息,例如模块和函数名称、行号等...而无需调用 get_stacktrace

【问题讨论】:

  • 该问题假定获取有关调用者的信息是绝对要求。你为什么需要它?您是始终需要它,还是仅在出现错误时才需要它?你真正想要完成什么?您是否考虑过要求调用者简单地将所需信息作为参数传递?
  • @SteveVinoski 我正在使用现有的代码库,是的,关于调用者的信息是一项要求。我可以更新代码,以便可以将所需的调用者信息作为另一个参数传递。这将涉及更新多个调用函数,这是我想避免的。我听说 erlang:process_info/2 可能会给我相同的信息,而且调用起来可能比 get_stacktrace 便宜。对此有什么想法吗?
  • 如果它是一个看起来很热门的函数,我建议尽可能简化它,即使这意味着调用者必须做额外的工作才能调用它。我不知道是否改为调用process_info/2 会更好;您必须对其进行测量才能确定。
  • @SteveVinoski 看起来process_info/2get_stacktrace/0 更有效率,至少在我的测试中是这样。
  • @SteveVinoski 我认为您的第一个建议可能是最好的解决方案。我会让调用者传入一个额外的参数。谢谢!

标签: erlang


【解决方案1】:

如果您需要知道从哪里调用您,那么 get_stactrace 可能还不够,因为调用者可能已经在堆栈外进行了优化。

相反,我会考虑这样的事情:

the_function(Normal, Args, {Module, Line}) ->
  try something(Normal, Args)
  catch error:x -> print_error(Module, Line).

-define(?the_function(Normal, Args), the_function(Normal, Args, {?MODULE, ?LINE})).

现在您将对the_function 的所有调用更改为?the_function,并在编译时为您添加第三个参数。

您可以使用解析转换来做一个更复杂的版本。

【讨论】:

  • 我做了一些跟踪来验证调用者实际上是堆栈跟踪的一部分。看起来在所有情况下调用函数都存在于堆栈跟踪中。使用宏会使调用函数的更改更简单,但我仍然犹豫要不要进行更改。根据我的测试,现在看起来 process_info 可能就足够了,而且速度更快。
猜你喜欢
  • 1970-01-01
  • 2012-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-30
  • 1970-01-01
  • 2011-05-05
  • 2021-11-24
相关资源
最近更新 更多