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

时间:2014-07-08 14:25:38

标签: concurrency erlang spawn otp

我有这两个功能

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框架的中间位置。

3 个答案:

答案 0 :(得分:2)

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

关于您的代码的说明:如果您需要将长列表分成满足某个谓词的元素和不需要的元素,那么使用lists:partition/2比使用{{3}}更有效lists:filter然后--。前者以线性时间运行到列表的长度,而如果您不幸,--可以在二次时间内运行。

答案 1 :(得分:2)

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

此外,我会将此队列拆分为大量优先级队列(如果可能,则独立),并同时处理它们。

在Erlang中,你真的可以监控其他进程(观察他们的&#34;退出&#34;代码)。此外,这可以使用OTP主管来完成。

答案 2 :(得分:1)

考虑到这里最糟糕的情况(根据我对您的问题/要求的理解),在同一时间到期的一百万个请求中,除了通过以下方式处理它们之外,您没有太多选择:
1.将过程限制从默认的32k增加到更合理的值。 (取决于您的资源可用性和测试结果)并一次处理过期结果(32k - 一些偏移)(默认情况)。
2.如果您可以选择跨多个节点(在同一台机器/不同的机器上)分发流程,则可以进一步处理上述方法。但同一台机器上的多个节点也将取决于您的资源可用性。

在erlang中,一旦由生成的进程执行的函数退出,进程本身就会退出。