假设我们有一个涉及数千个进程的erlang应用程序。假设有一个资源X可能是元组,列表或任何erlang术语,所有这些进程可能需要随时从中读取/提取某些内容。
这种情况的一个例子是API系统,其中客户端进程可能需要在远程机器上进行读写。对于每个读/写请求,您不希望创建新的连接。那么,你做了什么,你创建了一个连接池,将它们视为一个开放的管道/插座/通道池。
现在,这个资源池将由数千个进程共享,这样对于每个读取或写入请求,您希望该进程检索任何可用的开放通道/资源。
问题是,如果我有一个进程(单个进程)保存此信息,无论是在其进程字典中还是在其接收循环中。这意味着,只要需要免费资源,所有流程都必须向此流程发送消息。由于对这一单一资源的高需求,这个单一进程随时都会有一个庞大的邮箱。
左或我可以使用ETS表,只有一行,比如#resources{key=pool,value= List_of_openSockets_or_channels}
。但这意味着,我们所有的过程都会尝试在(高概率)相同的瞬时时间从ETS表读取同一行。
如果10,000进程在同一时间/几乎同一时间处理相同的行/记录,ETS表如何处理?然而,如果我使用一个进程,它的邮箱,如果10,000个进程同时向它发送一条消息,同一资源(并且它需要回复每个请求者)。请记住,此操作可能会频繁发生。什么选择(关于流程的可用性问题等等)会提供更高的吞吐量,以便流程可以更快地获得他们需要的东西?
还有其他更好的方法,能够以一种能够快速访问数百万个进程的方式处理Erlang VM中的高需求数据结构,即使它们都需要同时使用该资源?
答案 0 :(得分:3)
简短回答:个人资料。尝试不同的方法并验证系统的行为方式。
首先,我会看看ETS'{read_concurrency, true}
选项。来自the documentation:
{read_concurrency,boolean()} 性能调优。默认值为false。 设置为true时,表格针对并发读取进行了优化 操作。在具有SMP的运行时系统上启用此选项时 支持,阅读操作变得便宜得多;特别是在系统上 有多个物理处理器。但是,在read和之间切换 写操作变得更加昂贵。您通常想要启用 当并发读取操作更频繁时,此选项 比写操作,或并发读写时 大量读写突发(即大量读取不被中断) 写道,许多写入没有被读取中断)。你通常这样做 当公共访问模式很少时,不希望启用此选项 读操作重复与几个写操作交错。在 在这种情况下,启用此功能会降低性能 选项。 read_concurrency选项可以与 write_concurrency选项。您通常希望在何时将它们组合起来 大并发读突发和大并发写突发 常见的。
其次,我会看一下缓存的可能性。进程只读取一次或多次?如果他们多次访问它,您可以阅读一次并将其存储在您的过程状态中。
第三,您可以尝试在整个系统中复制和分发该信息。划分et impera。
答案 1 :(得分:2)
如果您使用流程方法,为了避免在“服务器”流程的邮件队列中序列化所有读取请求,您必须复制。
使用带有read_concurrency
的ETS表感觉更自然,这是我在开发Dialyzer的并行版本时使用的。但是,在这种情况下,ETS访问从来就不是瓶颈。