我正在考虑使用Elixir解决问题,主要是因为它能够廉价地产生大量进程。
在我的场景中,我想创建几个“原始”进程,将特定的不可变数据加载到内存中,然后根据需要复制这些进程。副本都将使用相同的基础数据,但使用它执行不同的只读任务;例如,想象一个“原始”在记忆中有“战争与和平”的文本,并且该原始的每个副本对文本进行不同类型的分析。
我的问题:
答案 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表,但最好将它们视为不共享资源,直到你绝对不得不这样做。