Erlang睡眠如何(晚上?) [英] How does Erlang sleep (at night?)

查看:133
本文介绍了Erlang睡眠如何(晚上?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在Erlang服务器上每隔几个小时运行一次小的清理过程.

I want to run a small clean up process every few hours on an Erlang server.

我知道计时器模块.我在一个使用链式timer:sleep命令的教程中看到了一个示例,该示例等待多天后发生的事件,我发现这很奇怪.我知道与其他语言相比,Erlang进程是独特的,但是一次将进程/线程休眠数天,数周甚至数月的想法似乎很奇怪.

I know of the timer module. I saw an example in a tutorial used chained timer:sleep commands to wait for an event that would occur multiple days later, which I found strange. I understand that Erlang process are unique compared to those in other languages, but the idea of a process/thread sleeping for days, weeks, and even months at a time seemed odd.

因此,我着手找出睡眠的实际细节.我发现最接近的是一篇博客文章,提到睡眠是通过接收超时实现的,但仍然留下了问题:

So I set out to find out the details of what sleeping actually does. The closest I found was a blog post mentioning that sleep is implemented with a receive timeout, but that still left the question:

这些睡眠/类似睡眠的功能实际上是做什么的?

我的进程在睡眠时是否占用了资源?上千个睡眠进程是否会使用那么多资源,例如,上千个进程为没有执行任何操作的递归调用服务?重复休眠或长时间休眠会导致性能下降吗?虚拟机是否一直在消耗资源以查看结束进程睡眠的条件是否已经建立?

Is my process taking up resources as it sleeps? Would having thousands of sleeping process use as many resources, as say, thousands of process servicing a recursive call that did nothing? Is there any performance penalty from repeatedly sleeping within processes, or sleeping for long periods of time? Is the VM constantly expending resources to see if the conditions to end the processes' sleep are up?

此外,如果有人能提出一种比睡觉一次暂停数小时或数天更好的方法,我是否希望对此发表评论?

And as a side note, I'd appreciate if someone could comment on if there is a better way than sleeping to pause for hours or days at a time?

推荐答案

这是任何erlang进程的业力:它等待还是死:o)

That is the Karma of any erlang process: it waits or dies :o)

产生一个进程时,它开始执行直到最后一个执行行,然后死亡,返回最后一个求值.

when a process is spawned, it start executing until the last execution line, and die, returning the last evaluation.

要使进程保持活动状态,没有其他解决方案可以循环调用永无休止的调用.

To keep a process alive, there is no other solution to recursively loop in a never ending succession of calls.

当然,有几种条件使其停止或进入睡眠状态:

of course there are several conditions that make it stop or sleep:

  • 循环结束:进程收到一条消息,告诉他 停止递归
  • 一个接收块:该过程将等待,直到出现一条消息 消息中发布了与接收组中的一个条目匹配的条目 队列.
  • VM调度程序暂时将其停止以允许访问CPU 其他过程
  • end of the loop: the process received a message which tell him to stop recursion
  • a receive bloc: the process will wait until a message matching one entry in the receive bloc is posted in the message queue.
  • The VM scheduler stop it temporarily to let access to the CPU to other processes

在最后两种情况下,执行将在VM调度程序的责任下重新开始.

in the 2 last cases the execution will restart under the responsibility of the VM scheduler.

在等待期间它不占用CPU带宽,但保持与开始等待时完全相同的内存布局. Erlang OTP提供了一些使用hibernate选项将这种内存布局减少到最小的方法(请参阅gen_serevr或gen_fsm的文档,但这仅在我心中用于高级用法).

while waiting it uses no CPU bandwidth, but keeps the exact same memory layout it had when it started waiting. The Erlang OTP offers some means to reduce this memory layout to the minimum using the hibernate option (see the documentation of gen_serevr or gen_fsm, but it is for advanced usage only in my mind).

创建信号"以定期(或几乎定期)触发进程的简单方法实际上是使用带有timout的接收块(超时限制为65535 ms),例如:

a simple way to create a "signal" that will fire a process at regular (or almost regular) interval is effectively to use receive block with timout (The timeout is limited to 65535 ms), for example:

on_tick_sec(Module,Function,Arglist,Period) -> 
    on_tick(Module,Function,Arglist,1000,Period,0).
on_tick_mn(Module,Function,Arglist,Period) -> 
    on_tick(Module,Function,Arglist,60000,Period,0).
on_tick_hr(Module,Function,Arglist,Period) -> 
    on_tick(Module,Function,Arglist,60000,Period*60,0).



on_tick(Module,Function,Arglist,TimeBase,Period,Period) ->
    apply(Module,Function,Arglist),
    on_tick(Module,Function,Arglist,TimeBase,Period,0);
on_tick(Module,Function,Arglist,TimeBase,Period,CountTimeBase) ->
    receive
        stop -> stopped
    after TimeBase ->
        on_tick(Module,Function,Arglist,TimeBase,Period,CountTimeBase+1)
    end.

和用法:

1> Pid = spawn(util,on_tick_sec,[io,format,["hello~n"],5]).
<0.40.0>
hello                
hello                
hello                
hello                        
2> Pid ! stop.
stop
3>

计时器模块是在单独进程中运行的标准gen_server.计时器模块中的所有功能都是公共接口,它们执行对计时器服务器的隐藏的gen_server:call或gen_server:cast.这是隐藏服务器内部并允许进一步发展而又不影响现有应用程序的常见用法.

The timer module is a standard gen_server running in a separate process. All the function in the timer module are public interfaces that execute a hidden gen_server:call or gen_server:cast to the timer server. This is a common usage to hide the internal of a server and allow further evolutions without impact on existing applications.

服务器内部使用一个表(表)来存储它必须执行的所有操作以及每个计时器引用,并且服务器使用其自己的功能在需要时唤醒(最后,VM必须注意这一点? ).

The server uses internally a table (ets) to store all the actions it has to do along with each timer reference and it uses its own function to be awaken when needed (at the end, the VM must take care of this ?).

因此,您可以在不影响计时器服务器行为的情况下使进程休眠.休眠机制是

So you can hibernate a process without any effect on the timer server behavior. The hibernation mechanism is

  • 棘手,请参阅文档,网址为休眠/3定义,您将看到您必须自己重建"上下文,因为所有内容都已从流程上下文中删除,并且系统存储了一个tuple(Module,Function,Arguments}以重新启动您的流程在需要的时候.
  • 花费一些时间进行垃圾收集并重新启动进程
  • tricky, see documentation at hibernate/3 definition, you will see that yo have to "rebuild" the context by yourself since everything was removed from the process context, and a tuple(Module,Function,Arguments} is stored by the system to restart your process when needed.
  • cost some time in garbage collecting and process restart

这就是为什么我说它确实是一项高级功能,需要充分的理由才能使用.

It is why I said that it is really an advance feature that need good reason to be used.

这篇关于Erlang睡眠如何(晚上?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆