Erlang:阻止C NIF呼叫行为

 Libra 发布于 2022-12-15 17:54

我观察到C NIF的阻塞行为,当它们被许多Erlang进程同时调用时.可以做成非阻塞吗?这里有mutex工作,我无法理解吗?

PS一个基本的"Hello world"NIF可以通过在特定调用它的情况下使其成为sleep一百来进行测试.可以观察到,调用NIF的其他PID等待该睡眠在执行之前执行.microsecondsPID

在并发可能不会造成问题的情况下(例如,数组推送,计数器增量),非阻塞行为将是有益的.

我共享链接至4个要旨,其包含的spawner,conc_nif_callerniftest分别模块.我试图修改价值,Val我确实观察到了非阻塞行为.通过为spawn_multiple_nif_callers函数指定一个大整数参数来确认这一点.

链接 spawner.erl,conc_nif_caller.erl,niftest.erl,最后是niftest.c.

下面的行由我的Mac上的Erlang REPL打印.

Erlang/OTP 17 [erts-6.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

mpm.. 5

NIF本身没有任何互斥锁.您可以在C中实现一个,并且在加载NIF的对象时有一个,但这应该只使用加载模块执行一次.

可能发生的一件事(我敢打赌这是发生了什么),是你的C代码搞砸了Erlang调度程序.

在返回之前执行冗长工作的本机函数会降低VM的响应性,并可能导致各种奇怪的行为.这种奇怪的行为包括但不限于极端的内存使用,以及调度程序之间的负载均衡.由于冗长的工作可能发生的奇怪行为也可能因OTP版本而异.

和描述的是什么lengty work意思,你是如何解决的.

用极少的话说(简化很少):

对于核心,创建了一个调度程序.每个都有一个他可以运行的进程列表.如果一个调度程序列表为空,他将尝试继续使用另一个调度程序列表.如果没有(或者不够)仍然存在,这可能会失败.

Erlang调度程序在一个进程中花费了大量的工作,而不是移动到另一个进程,花费一些工作量,然后转移到另一个进程.等等,等等.这与系统进程中的调度非常相似.

这里非常重要的一件事是计算工作量.默认情况下,每个函数调用都分配了一些减少量.添加可能有两个,你的模块中的调用函数将有一个,发送消息也一个,一些内置可能有更多(如list_to_binary).如果我们收集2 000个减少量,我们会转移到另一个流程.

那么C函数的成本是多少?这只是一次减少.

代码就像

loop() ->
   call_nif_function(),
   loop().

可能需要整整一个小时,但调度程序将停留在这一个过程中,因为他仍然没有计入2 000减少.换句话说,他可能被困在NIF内部而无法前进(至少在很短的时间内).

围绕这一点的方法很少,但一般规则是统计NIF不应该花很长时间.因此,如果你有很长的C代码,也许你应该使用驱动程序.他们应该更容易实施和管理,修补NIF.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有