Elixir / Erlang可以复制一个进程,包括它的内存吗?

时间:2015-03-13 13:24:18

标签: process erlang elixir

我正在考虑使用Elixir解决问题,主要是因为它能够廉价地产生大量进程。

在我的场景中,我想创建几个“原始”进程,将特定的不可变数据加载到内存中,然后根据需要复制这些进程。副本都将使用相同的基础数据,但使用它执行不同的只读任务;例如,想象一个“原始”在记忆中有“战争与和平”的文本,并且该原始的每个副本对文本进行不同类型的分析。

我的问题:

  • 是否可以在Elixir / Erlang VM中复制现有流程,内存内容等?
  • 如果是这样,每个副本是否会消耗与原始内存一样多的内存,或者它们是否可以共享内存,因为Unix进程使用“copy on write”策略? (在这种情况下,不会有后续写入。)

3 个答案:

答案 0 :(得分:6)

没有内置的方法来复制进程。最简单的方法是启动"原始"过程和"副本"并将消息中的所有相关数据发送到副本。流程不会共享数据,因此没有更有效的方法。将数据放在ETS表中只能部分地帮助共享,因为ETS表中的数据在使用时会被复制到进程中,但是,您不需要在进程堆中包含所有数据。

答案 1 :(得分:5)

除了存储在变量(和the process dictionary)中的内容之外,Erlang进程没有特定于进程的数据,因此要生成进程内存的副本,只需生成一个通过所有进程的新进程相关变量作为函数的参数。

通常,进程之间不共享内存;一切都被复制了。例外情况是ETS表(尽管数据是在进程读取时从ETS表复制的),以及大于64字节的二进制文件。如果你存储"战争与和平"在二进制文件中,并将其发送到每个工作进程(或在您生成这些工作进程时传递它),然后进程将共享内存,只有在他们想要修改二进制文件时才复制它。有关详细信息,请参阅Erlang效率指南中的chapter on binaries

答案 2 :(得分:1)

您认为Erlang / Elixir进程与Unix进程类似。它们根本不是,我真的希望它们有一个不同的名称,因为它们在标准的Unix意义上确实不是线程或进程。我花了一些时间来探讨差异。

你必须抛弃所有关于流程的先入为主的想法,他们都错了。 Eprocesses具有以下特征。

  • 它们既便宜又快捷。使用很多,总是有更多。

  • 他们没有资源[1]。 (即使写入stdout也是另一个Eprocess的消息。)

  • 与标准Unix IPC相比,IPC(或消息)速度非常快,开销相对较低。

在您的情况下,我会尝试创建一个管理数据的服务器,让每个分析工作者向服务器发送消息,告知其所需的数据块。让Eprocess或多或少是完全可以接受的 共享内存管理员。

对我来说,最有用的思考Eprocesses的方法是作为具有自己的执行线程的对象。

[1]嗯,有ETS表,但最好将它们视为不共享资源,直到你绝对不得不这样做。