2

假设我们有一个涉及数千个进程的 erlang 应用程序。假设有一个资源 X,它可能是一个元组、一个列表或任何 erlang 术语,所有这些进程可能需要随时从中读取/挑选一些东西。

这种情况的一个例子是 API 系统,其中客户端进程可能需要在远程机器上读写。Ant 碰巧您不希望为每个读/写请求创建一个新连接。因此,您所做的就是创建一个连接池,将它们视为一个开放的管道/套接字/通道池。

现在,这个资源池将由数千个进程共享,因此对于每个读取或写入需求,您希望该进程检索任何可用的开放通道/资源。

问题是,如果我有一个进程(单个进程)保存此信息,无论是在其进程字典中还是在其接收循环中。这意味着所有进程在需要空闲资源时都必须向该进程发送消息。由于对该单一资源的高需求,这个单一进程在任何时候都会有一个巨大的邮箱。

或者我可以使用 ETS 表,并且只有一行,比如#resources{key=pool,value= List_of_openSockets_or_channels}. 但这意味着,我们所有的进程都将尝试在(高概率)相同的瞬时时间从 ETS 表中读取同一行。

如果 10,000 个进程同时/几乎同时尝试读取同一行/记录,ETS 表将如何处理?然而,如果我使用一个进程,它的邮箱,如果 10,000 个进程同时为相同的资源向它发送消息(并且它需要回复每个请求者)。请记住,此操作可能会如此频繁地发生。什么选项(不考虑进程下降的可用性问题等等)会提供更高的吞吐量,从而让进程更快地获得他们需要的东西?

有没有其他更好的方法来处理 Erlang VM 中的高需求数据结构,即使它们都同时需要该资源,也可以提供对数百万个进程的非常快速的访问?

4

2 回答 2

4

简短的回答:简介。尝试不同的方法并验证您的系统的行为方式。

首先,我会看看 ETS 的{read_concurrency, true}选项。从文档中

{read_concurrency,boolean()}性能调优。默认为假。当设置为 true 时,该表针对并发读取操作进行了优化。在支持 SMP 的运行时系统上启用此选项时,读取操作会变得更便宜;特别是在具有多个物理处理器的系统上。但是,在读取和写入操作之间切换变得更加昂贵。当并发读取操作比写入操作频繁得多时,或者当并发读取和写入以大的读取和写入突发(即,大量读取未被写入中断,大量写入未被中断)时,您通常希望启用此选项读)。当常见的访问模式是一些读操作与一些重复的写操作交错时,您通常不希望启用此选项。在这种情况下,启用此选项会导致性能下降。read_concurrency 选项可以与 write_concurrency 选项结合使用。当大型并发读取突发和大型并发写入突发很常见时,您通常希望将这些组合起来。

其次,我会考虑缓存的可能性。进程是否只读取该信息一次或多次?如果他们多次访问它,您可以读取一次并将其存储在您的进程状态中。

第三,您可以尝试在整个系统中复制和分发该信息。分而治之。

于 2013-04-19T09:20:49.180 回答
2

如果您使用进程方法,为了避免在“服务器”进程的消息队列上序列化所有读取请求,您必须复制。

使用 ETS 表read_concurrency感觉更自然,这是我在开发 Dialyzer 并行版本时使用的东西。但是,在这种情况下,ETS 访问从来都不是瓶颈。

于 2013-04-19T13:14:51.493 回答