我的 OTP 21 亮点
OTP-21 候选版本 1 刚刚发布。我想在这里介绍一下我最兴奋的更改。很可能这主要指的是 erts 和核心库中的功能,因为我最熟悉这些更改。
您可以在这里下载描述更改的自述文件:OTP 21-RC1 自述文件。或者,像往常一样,查看您感兴趣的应用程序的发行说明。例如,这里:OTP 21-RC1 Erts 发行说明。
编译器 / 解释器 #
Björn Gustavsson 去年在编译器和解释器方面做了大量工作,而我一直坐在他旁边为他加油。最大的变化是 OTP-14626 工单的一部分。在开发 BEAMJIT 时,我一直在研究 luajit 项目以及 Mike Pall 在 JIT 和解释器中所做的工作。受到这个以及我们从 BEAMJIT 项目中获得的其他一些想法的启发,我们决定是时候对 BEAM 解释器的创建方式进行重大改革了。所做的大部分更改都归结为减少内存中 beam 代码的大小,从而使更多的代码适合 L1/L3 缓存,并最终使代码运行得更快。我们使用优化将加载的代码大小减少了约 20%。这转化为大多数 Erlang 代码的性能提高了约 5%,这非常了不起。我和 Björn 很可能会在未来的博文中详细介绍这具体包含哪些内容。
另一个产生很大影响的编译器更改(至少在我们的基准测试中)是 José Valim 在 PR 1080 中贡献的 OTP-14505。此更改使编译器重写
example({ok, Val}) -> {ok, Val}.
至
example({ok, Val} = Tuple) -> Tuple.
从而消除元组的额外创建。事实证明,这是 Erlang 代码中非常常见的模式,因此这对所有程序都有好处。
可以在下面的 estone 基准测试套件中看到这种性能提升的一个示例。OTP-14626 与其他一些编译器和 erts 改进一起,将石头数量从 OTP-20.3(绿线)中的 370000 增加到 OTP-21(蓝线)中的 400000。大约增加了 7.5%。
Erlang 运行时系统 #
运行时系统中有许多更改。
文件处理 #
传统上,所有文件 IO 都是通过端口处理的。在 OTP-21 中,所有文件 IO 都被重写为使用 nifs,OTP-14256。这样做主要是为了在脏 IO 调度器中运行文件操作。它还产生了显著提高某些操作吞吐量的良好副作用。
例如,在微小读取基准测试中,OTP-21(蓝线)比 OTP-20.3(绿线)快约 2.8 倍。
此外,现在可以使用 file:open 打开设备文件,请参阅 OTP-11462。
I/O 轮询 #
检查套接字上的 I/O 的整个底层机制已被重写和优化,以适应现代操作系统内核轮询功能。有关更多详细信息,请参阅 OTP-14346 和 OTP 21 中的 I/O 轮询选项。
分布式 #
如果您想使用 RFC-2549 发送您的分布式 Erlang 消息,那么一直可以编写自己的分布式载体。但是,您必须将其实现为链接的驱动程序。随着 OTP-14459 的引入,您现在可以使用进程或端口作为分布式载体。因此,现在您可以使用 gen_pigeon,而不必调用 boost 等效项。
现在 TLS 分布使用将进程用作分布式载体的能力。这使我们不必像以前那样跳过多个障碍,从而显著提高了 TLS 分布的吞吐量。
进程信号 #
当使用 cowboy 运行基准测试并使用不使用 keep-alive 的连接对其进行锤击时,出现的一个 SMP 可扩展性瓶颈是监视所有连接的 supervisor 的链接锁。之所以出现此锁,是因为当您有很多链接的进程时,存储链接的 rb 树会变得非常大,因此插入和删除时间会增加。在 OTP-14589 中,这已更改为所有链接和监视请求现在都作为消息发送,供接收进程处理。这意味着该锁已完全删除。现在所有信号(无论是消息、链接、监视器、process_info、group_leader 等)都通过同一个队列处理。
此外,OTP-14901 现在使监视器 + 发送信号合并为一个信号。因此,gen_server:call 等函数的竞争进一步减少。
性能差异非常显著。与 OTP-20.3(绿线)相比,上面看到的 genstress 基准测试 OTP-21(蓝线)的吞吐量几乎翻了一番。
日志记录器 #
OTP-13295 为 Erlang/OTP 添加了一个全新的日志记录框架。它的灵感来自 lager、Elixir Logger 和 Python 日志记录器的工作方式。使用日志记录器,日志记录处理程序可以在进行实际调用的进程中拦截日志记录调用,而不必等待消息。这为在发生过载时尽早拒绝日志消息开辟了各种可能性,有关详细信息,请参阅 日志记录器用户指南。用户还可以添加在调用处理程序之前运行的特殊用途过滤器,以便在系统中静音或修改日志消息。
其他 #
Magnus Lång 最终修复了 HiPE,使其可以使用 beam 长期拥有的接收引用优化,OTP-14785。
inets 的 ftp 和 tfpt 部分已分离到它们自己的应用程序中,而不是捆绑在一起,OTP-14113。
rand 模块进行了大量工作,添加了新功能。我不确定何时或如何使用这种差异,但围绕此的理论令人着迷,OTP-13764。
maps 模块现在具有 maps:iterator/0 和 maps:next/1,OTP-14012。
添加了 io_lib:format/3 来限制函数的输出。这在构建日志记录框架时尤其有用,因为您可能会得到任意大的项进行格式化,并且可能希望裁剪它们以避免系统过载,OTP-14983。
最后,我不确定是否有人注意到,但从 OTP-20.3 开始,当您的系统崩溃时,处于 GARBING 状态的进程现在在崩溃转储中包含堆栈跟踪!!!