如何更有效地在 Erlang 中生成进程?

Posted

技术标签:

【中文标题】如何更有效地在 Erlang 中生成进程?【英文标题】:How to spawn processes in Erlang more efficiently? 【发布时间】:2014-08-29 08:07:29 【问题描述】:

我有这两个功能

check_requests(Timestamp,Plan,AddInfo)->
    Day,_Month,_Year,Hour,Minute,Second,Micro = Timestamp,
    ExpiredRequests = lists:filter(fun(Elem) -> 
                               _ID,Time,_Key,_Action = Elem,
                               Time < Day,Hour,Minute,Second,Micro
                               end, Plan),
    NewPlan = Plan -- ExpiredRequests,
    make_requests(ExpiredRequests,AddInfo),
    NewPlan.

make_requests([],_)->ok;
make_requests([ExpiredRequest|Rest],AddInf)->
    _ID,_Time,Key,Action = ExpiredRequest,
    spawn(?MODULE,request,[AddInf,Action,Key]),
    make_requests(Rest,AddInf).

主要思想是我有一个计划,每个请求都有一个到期时间,应该执行。到期后,我想与其他可能及时到期的请求同时执行该请求,因此我使用新进程生成请求函数。现在,如果我有数百万个请求,我将有数百万个进程,我认为这是不希望的。请求执行最多可能持续一分钟。 我想知道当我生成的函数完成后进程会发生什么。它被杀死了吗?还是它仍然存在并且应该被垃圾收集?我真的需要并发请求并且不知道我还能如何实现它。 还有一些 OTP 行为在这种情况下可能会有所帮助吗?我还没有研究过 OTP,我处于整个 Erlang 框架的中间位置。

【问题讨论】:

【参考方案1】:

当函数完成运行时,生成的进程退出。不需要进行垃圾收集;整个进程堆被释放。 (超过 64 字节的二进制文件除外,它们保存在共享堆中。)

关于您的代码的注释:如果您需要将一个长列表分成满足某个谓词的元素和不满足某个谓词的元素,使用lists:partition/2 比使用lists:filter 然后-- 更有效.前者以线性时间运行到列表的长度,而-- 如果你不走运,可以以二次时间运行。

【讨论】:

【参考方案2】:

您的任务完全是一个“最大堆/优先级队列”模板。应该解决的不是过滤列表,而是弹出具有最高优先级的元素(到期日期越接近给定时刻,优先级越高) 在优先级队列中提取元素将花费 O(1) 时间。 只有当所有进程同时过期时,您才需要遍历所有队列。

另外,我会将这个队列分成大量的优先级队列(如果可能的话独立),并同时处理它们。

在 Erlang 中,您确实可以监控其他进程(查看它们的“退出”代码)。此外,这可以使用 OTP 主管来完成。

【讨论】:

【参考方案3】:

考虑到最坏的情况(根据我从您的问题/要求中了解到的情况),一百万个请求同时到期,除了通过以下方式批量处理它们之外,您别无选择: 1.将进程限制从默认的32k增加到一些更合理的值。 (取决于您的资源可用性和测试结果)并一次处理过期结果(32k - 一些偏移量)(默认情况)。 2. 如果您可以选择将进程分布在多个节点(在同一台机器/不同机器上),您可以进一步研究上述方法。但是,同一台机器上的多个节点再次取决于您的资源可用性。 在 erlang 中,一旦衍生进程正在执行的函数退出,进程本身就会退出。

【讨论】:

以上是关于如何更有效地在 Erlang 中生成进程?的主要内容,如果未能解决你的问题,请参考以下文章

Erlang 语言中的进程与并发

Erlang中的Google Oauth2

如何在 Elixir 中生成随机数?

如何在 Python 中生成一个新的独立进程

通过 bash 在 linux 中生成一个完全独立的进程

如何有效地查询多个表以在 dataGrid 中生成 excel STYLE 报告