[Erlang 0058] Erlang Function调用效率

简介:

   Erlang方法调用有m:f(a),M:F(a),fun,f(),apply/3几种方法,调用效率如何呢?《Erlang/OTP in Action》一书中有一个总结我们看下:

 
 
  即模块内调用和模块间的方法调用速度差异不大;要关注一下元编程方式调用(apply调用)要慢的多,除此之外除非是在性能要求特别高的场景否则不必过于在意这点性能差异;这个在官方文档中有大致相同的结果:
 

Here is an intentionally rough guide to the relative costs of different kinds of calls. It is based on benchmark figures run on Solaris/Sparc:

  • Calls to local or external functions (foo(), m:foo()) are the fastest kind of calls.
  • Calling or applying a fun (Fun(), apply(Fun, [])) is about three times as expensive as calling a local function.
  • Applying an exported function (Mod:Name(), apply(Mod, Name, [])) is about twice as expensive as calling a fun, or about six times as expensive as calling a local function.
    DocLink: http://www.erlang.org/doc/efficiency_guide/functions.html


概念明确

   对于上面的结论,明确一下上面表中 跨模块调用这个概念在Erlang中常用的表达方式:
In the first form of function calls, ExprM:ExprF(Expr1,...,ExprN), each of ExprM and ExprF must be an atom or an expression that evaluates to an atom. The function is said to be called by using the  fully qualified function name. This is often referred to as a  remote or  external function call

速度差异因何而来

      fun包含或者间接包含了实现了该方法的指针调用不涉及hash-table的查询,apply/3必须要在HashTable中查找funtion对应的Code实现,所以通常比直接调用或者fun调用速度要慢. 
     

编译时优化

   在参数个数确定的时候,apply/3的调用会在编译时被优化为m:f(a)形式的external function call.通过一段代码看一下:
复制代码
a() -> 
    M=erlang,
    F=now,
    apply(M,F,[]).

b(M,F,A) -> 
   apply(M,F,A).

c(M,F) ->
   apply(M,F,[a,b,c]).
   
d(M)->
   apply(M,do_something,[]).
复制代码

  我们添加to_core参数,看一下编译出来的Core Erlang代码:

复制代码
'a'/0 =
    %% Line 33
    fun () ->
     %% Line 36
     call 'erlang':'now'
         ()
'b'/3 =
    %% Line 38
    fun (_cor2,_cor1,_cor0) ->
     %% Line 39
     call 'erlang':'apply'
         (_cor2, _cor1, _cor0)
'c'/2 =
    %% Line 41
    fun (_cor1,_cor0) ->
     %% Line 42
     call _cor1:_cor0
         ('a', 'b', 'c')
'd'/1 =
    %% Line 44
    fun (_cor0) ->
     %% Line 45
     call _cor0:'do_something'
         ()
 
复制代码

   可以看到在参数个数确定的情况下,apply/3的调用已经都被优化为mfa的调用方式.

   Erlang代码加载自后的调用方式细节需要找资料深入研究一下,估计是在Code Server相关的代码中,待续
目录
相关文章
|
27天前
|
中间件 Docker Python
【Azure Function】FTP上传了Python Function文件后,无法在门户页面加载函数的问题
通过FTP上传Python Function至Azure云后,出现函数列表无法加载的问题。经排查,发现是由于`requirements.txt`中的依赖包未被正确安装。解决方法为:在本地安装依赖包到`.python_packages/lib/site-packages`目录,再将该目录内容上传至云上的`wwwroot`目录,并重启应用。最终成功加载函数列表。
|
2月前
|
JavaScript
箭头函数与普通函数(function)的区别
箭头函数是ES6引入的新特性,与传统函数相比,它有更简洁的语法,且没有自己的this、arguments、super或new.target绑定,而是继承自外层作用域。箭头函数不适用于构造函数,不能使用new关键字调用。
|
2月前
|
数据可视化 开发者 索引
详解Wireshark LUA插件函数:function p_myproto.dissector(buffer, pinfo, tree)
在 Wireshark 中,LUA 插件通过 `function p_myproto.dissector(buffer, pinfo, tree)` 扩展协议解析能力,解析自定义应用层协议。参数 `buffer` 是 `PacketBuffer` 类型,表示原始数据包内容;`pinfo` 是 `ProtoInfo` 类型,包含数据包元信息(如 IP 地址、协议类型等);`tree` 是
84 1
|
2月前
|
JavaScript
箭头函数与普通函数(function)的区别
箭头函数是ES6引入的新语法,相比传统函数表达式更简洁,且没有自己的this、arguments、super或new.target绑定,而是继承自外层作用域。这使得箭头函数在处理回调和闭包时更加灵活方便。
|
2月前
|
C++ 容器
函数对象包装器function和bind机制
函数对象包装器function和bind机制
22 0
|
4月前
【Azure Durable Function】PowerShell Activity 函数遇见 Newtonsoft.Json.JsonReaderException: The reader's MaxDepth of 64 has been exceeded.
【Azure Durable Function】PowerShell Activity 函数遇见 Newtonsoft.Json.JsonReaderException: The reader's MaxDepth of 64 has been exceeded.
|
4月前
|
安全 JavaScript 应用服务中间件
【Azure Function App】如何修改Azure函数应用的默认页面呢?
【Azure Function App】如何修改Azure函数应用的默认页面呢?
|
4月前
|
C# C++ Python
【Azure 应用服务】Azure Durable Function(持久函数)在执行Activity Function时候,因为调用函数名称错误而导致长时间无响应问题
【Azure 应用服务】Azure Durable Function(持久函数)在执行Activity Function时候,因为调用函数名称错误而导致长时间无响应问题
|
5月前
|
C++ 运维
开发与运维函数问题之使用std::function实现回调函数的示例如何解决
开发与运维函数问题之使用std::function实现回调函数的示例如何解决
41 7
|
4月前
|
SQL JavaScript 前端开发
【Azure 应用服务】Azure JS Function 异步方法中执行SQL查询后,Callback函数中日志无法输出问题
【Azure 应用服务】Azure JS Function 异步方法中执行SQL查询后,Callback函数中日志无法输出问题

热门文章

最新文章