什么';Erlang/OTP中gen_服务器调用的开销是多少?

什么';Erlang/OTP中gen_服务器调用的开销是多少?,erlang,otp,Erlang,Otp,这种基于Erlang的可伸缩性表示,对gen_服务器的每一次呼叫、广播或消息都会有开销。它的开销是多少?它的用途是什么?所引用的成本是对外部模块的(相对盲)函数调用的成本。这是因为gen_*抽象中的所有内容都是对外部定义函数(您在回调模块中编写的函数)的回调,而不是可以由编译器在单个模块中优化的函数调用。这一成本的一部分是调用的解析(找到要执行的正确代码——这与Python或Java中的.A.long.function.or.method.call中的每个“点”提高解析成本的原因相同),另一部分

这种基于Erlang的可伸缩性表示,对gen_服务器的每一次呼叫、广播或消息都会有开销。它的开销是多少?它的用途是什么?

所引用的成本是对外部模块的(相对盲)函数调用的成本。这是因为gen_*抽象中的所有内容都是对外部定义函数(您在回调模块中编写的函数)的回调,而不是可以由编译器在单个模块中优化的函数调用。这一成本的一部分是调用的解析(找到要执行的正确代码——这与Python或Java中的.A.long.function.or.method.call中的每个“点”提高解析成本的原因相同),另一部分是实际调用本身

但是

这不是一个简单的数量,你可以计算出来,然后乘以得到一个有意义的答案,关于整个系统的运营成本

在像Erlang这样的大规模并发系统中,有太多的变量、约束点和出乎意料的廉价元素,其中并发的最困难部分被抽象掉(与调度相关的问题),并行处理中最昂贵的元素变得极其廉价(上下文切换、进程生成/终止和进程:内存比率)

真正了解大规模并发系统的唯一方法是编写一个程序,并在实际操作中对其进行度量。您可以使用gen_*抽象在纯Erlang中编写完全相同的程序,作为OTP应用程序,并度量性能差异这样的话——但基准数字对那个特定的程序来说只意味着任何东西,并且可能只意味着在那个特定的负载配置文件下的任何东西

所有这些都要牢记在心……在Erlang世界中,当我们开始梳理头发时,真正重要的数字是调度器减少的预算成本。Erlang Solutions的Lukas Larsson不久前发布了一段关于调度器的视频,详细介绍了这些成本对系统的影响方式,它们是什么,以及如何在特定的条件下调整值ircumstances()。除了与Erlang/OTP无关的外部资源(iops延迟、网络问题、NIF疯狂等),压倒性的因素不是“函数调用的成本”


然而,在所有情况下,真正了解的唯一方法是编写一个原型,该原型代表您在实际系统中期望的基本行为,并对其进行测试。

产生开销的不仅仅是对外部模块的调用——与
gen_server的交互
和其他OTP行为通常涉及进程之间的消息。例如,
genu-server:cast/2
genu-server
进程发送一条来自调用者的消息,而
genu-server:call/3
意味着向
genu-server
发送一条消息,然后向调用进程返回一条回复消息。a
genu-server:call/3
还设置了对
genu-server
进程的监视器,以便如果它死了,呼叫者就不会等待永远不会到达的回复。@SteveVinoski确实如此。但不管这是否是OTP行为,消息传递和链接开销都会存在——唯一的事情是外部调用,特别是在链接的帖子的上下文中。(这篇文章指出,定制流程代码的编写开销可以比OTP行为少。)好吧,我想一个人可以编写一个同步调用而无需链接,但这会带来更大(更奇怪)的问题。