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相关的代码中,待续
分类:
Erlang
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
2008-05-06 工厂模式与OO设计原则