【问题标题】:What is the best way of doing computationally intensive tasks in Erlang w/o scalability sacrifices?在不牺牲可伸缩性的情况下,在 Erlang 中执行计算密集型任务的最佳方法是什么?
【发布时间】:2015-12-27 02:09:04
【问题描述】:

Erlang Interoperability 指南讨论了不同的互操作性机制。以下是我的结论:

  • 端口和 Erl_Interface 程序:操作系统调度,限制可扩展性。

  • 端口驱动程序:危险,因为端口驱动程序崩溃会导致 模拟器也关了。

  • C 节点:节点服务器需要像 Erlang 应用程序一样扩展以避免 可扩展性牺牲。

  • NIF:Loic 总和 他们很好。

有些人主张使用 OpenCL,基本上将资源匮乏的计算委托给 GPU,同时让 Erlang 模拟器拥有 CPU。这听起来棒极了,但您的服务器需要有合适的 GPU。

使用 JInterface 并与为每个请求生成一个线程的 Java 进程通信可能是一种选择。

那么有没有人遇到过经过实践测试并证明效果很好的解决方案?

【问题讨论】:

  • 您链接到的 NIF 的描述看起来已经过时且不准确。例如,在调度程序上运行“超过几微秒”的 NIF 不会导致问题;仅当 NIF 运行超过几毫秒时才会发生这种情况。此外,enif_schedule_nif function 提供了一种很好的方法来分解长 NIF 以避免调度程序问题,加上实验性的dirty scheduler functionality NIF 可以运行任意时间,而不会导致调度程序打嗝。
  • 要使用脏调度器功能,您需要构建模拟器并启用实验性脏调度器支持。我认为运行具有实验功能的生产代码的想法不会有很多爱好者。一般来说,NIF 似乎有点危险。正如 Loic 指出的那样,它们可能会使您的虚拟机崩溃。在 Windows 下编译使用它们的库是一场噩梦——我不喜欢在 Windows 上运行 Erlang。
  • 实验性的脏调度器功能有一天会成为常规功能,希望在 Erlang 19 中。我为 Erlang/OTP 实现了脏调度器功能,并在启用它的情况下运行所有​​ Erlang 17 和 18 虚拟机,并且没有任何问题。另外,请参阅these measurements,它显示了将进程切换到脏调度程序所涉及的少量开销。

标签: erlang scalability erlang-ports erlang-driver jinterface


【解决方案1】:

实际上所有的解决方案都会发生。由于我一直与他们中的一些人紧密合作,因此我可以说以下几点:

  • 端口是安全的,但端口通信很慢。如果端口崩溃,VM 会继续工作。如果您不与您的端口进行广泛的通信或您不信任该端口 - 这是您的选择

  • NIF 非常快。如果您的数据流很好,您应该使用它们。当然它们是不安全的,因此您必须仔细编写 NIF 库,并且您最好学习一些 C 语言(大多数 NIF 创建者都会跳过这一点)。实际上,使用特定模式可以轻松克服调度问题。您应该在从 Erlang 接收数据并从 Erlang 线程分离处理后立即启动执行实际工作的新 C 线程。所以你很快就退出了 NIF 函数,返回 Erlang 并等待来自 C 代码的消息。

  • Java 节点或 C 节点用于可以完全移动到节点的任务。那是一些漫长而繁重的工作。

牢记上述注意事项,您可以决定最适合您的任务的方式。

【讨论】:

  • 你同意没有灵丹妙药吗?端口是可扩展性与可靠性之间的权衡,除非写得很好,否则 NIF 会对 Erlang 的弹性构成风险。从集成的角度来看,可扩展的 C 或 Java 节点可能非常适合。
  • @coolfeature,与 NIF 相比,独立节点的通信速度仍然较慢。 Erlang 只有有限的套接字池(如果我没记错的话),你必须序列化/反序列化数据。如果处理数据的时间明显大于序列化/传输/反序列化的时间,那么独立节点将适合您。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多