关于erlang:谈谈erlang的nif

258次阅读

共计 1310 个字符,预计需要花费 4 分钟才能阅读完成。

简述

在某个需要的驱动下,心愿实现线程间共享的路由树。鉴于如下的外围需要:

  • 读多写少,写入操作重,读取操作轻。
  • 性能足够快,不心愿有单点。
    鉴于有数据共享需要,没有单点的状况下,erlang 中简直只有 ets 了。因为 ets 仅能实现 k,v 查问,不能实现更简单的读写需要,比方寻找某个子网 (key=”192.168.x.x”) 下的任意 IP(values = [“192.168.1.1”, “192.168.2.3”]),于是决定用 NIF 来实现。这是第一次尝试在理论业务中应用 NIF。这里做一下总结。

实现时的考量

数据转换 erlang_term to c and c to erlang_term

大部分语言都提供 c 拓展,第一件事就是,如何把语言的内置类型转为 c 中的类型,以及如何将 c 中的数据结构转为语言的内置类型。
这里能够

  • 间接应用 enif_get/enif_make 系列接口。
  • 参考 https://github.com/goertzenat…,利用 c ++ template,在编译期主动依据类型开展雷同的 enif_get/enif_make 系列代码。

资源管理

参考 https://www.erlang.org/doc/ma…
次要有两种:

  • 本人治理,比方将资源存储在动态变量中,提供 destroy_nif 之类,由用户销毁。
  • erlang 治理,nif 不治理资源,erlang_term 复制进来后,由 erlang 的援用计数治理。

动静类型

能够用 enif_term_to_binary/enif_binary_to_term 系列接口,在同样的数据结构中存储动静的 erlang 构造。

线程平安

一般来说,nif 是在 erlang 的 scheduler 线程执行的。所以,须要用 enif_mutex/enif_rwlock 系列接口爱护资源,防止未定义的行为。也能够间接应用 c ++ 的 mutex,操作系统 api 等等。
如:https://en.cppreference.com/w…

调度器和上下文切换

erlang 调用 nif 是没有上下文切换的。那么就会有一个问题,如果 nif 始终占用 cpu 怎么办?如何偏心调度?
https://www.erlang.org/doc/ma…
nif 函数应该尽快(1ms 内)返回。否则,会导致一些异样行为,我遇到的状况是日志刷不进去(调度异样)。为防止这种状况,咱们须要更简单的策略如下。

协程化:

  • 用 enif_consume_timeslice 看本人是否还有工夫片。
  • 用 enif_schedule_nif yield to scheduler。

    异步化:

    另起 thread 计算,在用 enif_send 将后果发回去,这样不影响调度线程。

    Dirty Nif:

    其实就是官网的 worker thread,按 cpu/io bound 分类,防止影响一般调度器。

调试

占位。原理上,和一般 c 程序调试动静库没有太多区别。工作流倒是能够记录一下。

总结

  1. 没有银弹,nif 有其应用的场景:小音讯,大计算。

参考

  1. https://www.erlang.org/doc/ma…
  2. https://www.erlang.org/doc/tu…
  3. https://github.com/goertzenat…
正文完
 0