sleep() 对于作业调度应用程序的主循环来说是个好主意吗

发布于 2024-07-29 05:19:45 字数 312 浏览 9 评论 0原文

我正在用 Ruby 为我的工作编写一个作业调度应用程序(主要是以给定频率使用各种协议移动文件)

我的主循环如下所示:

while true do
  # some code to launch the proper job
  sleep CONFIG["interval"]
end

它的工作方式就像一个魅力,但我不太确定它是否是足够安全,因为应用程序可能在运行 CPU 密集型软件的服务器上运行。

有没有其他方法可以做同样的事情,或者在我的情况下 sleep() 足够安全吗?

I'm writing a job-scheduling app in Ruby for my work (primarily to move files using various protocol at a given frequency)

My main loop looks like this :

while true do
  # some code to launch the proper job
  sleep CONFIG["interval"]
end

It's working like a charm, but I'm not really sure if it is safe enough as the application might run on a server with cpu-intensive software running.

Is there another way to do the same thing, or is sleep() safe enough in my case ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一指流沙 2024-08-05 05:19:45

每当我觉得需要阻塞时,我都会使用事件循环; 通常是libev。 下面是一个 Ruby 绑定:

http://rev.rubyforge.org/rdoc/

基本上,sleep 是完全可以的。 但是,如果您想做其他事情,例如睡眠并等待 TCP 连接或文件句柄变得可读,那么您将不得不使用事件循环。 那么,为什么不一开始就使用一个呢?

您的应用程序的流程将是:

main {
   Timer->new( after => 0, every => 60 seconds, run => { <do your work> } )
   loop();
}

当您想做其他事情时,您只需创建观察者,它就会为您发生。 (您正在运行的作业也可以创建观察者。)

Any time I feel the need to block, I use an event loop; usually libev. Here is a Ruby binding:

http://rev.rubyforge.org/rdoc/

Basically, sleep is perfectly fine if you want your process to go to sleep without having anything else going on in the background. If you ever want to do other things, though, like sleep and also wait for TCP connections or a filehandle to become readable, then you're going to have to use an event loop. So, why not just use one at the beginning?

The flow of your application will be:

main {
   Timer->new( after => 0, every => 60 seconds, run => { <do your work> } )
   loop();
}

When you want to do other stuff, you just create the watcher, and it happens for you. (The jobs that you are running can also create watchers.)

绻影浮沉 2024-08-05 05:19:45

对于快速而肮脏的事情,使用睡眠可能是可以的。 但对于需要更多鲁棒性或可靠性的事情,我建议睡眠是邪恶的:)睡眠的问题是线程(我假设 Windows 这里......)真正睡着了 - 调度程序不会运行线程直到睡眠间隔过去一段时间。

在此期间,线程不会因为任何事情而被唤醒。 这意味着它无法被取消,或唤醒以处理某种事件。 当然,该进程可以被终止,但这并不会给休眠线程一个唤醒并清理任何东西的机会。

我对 Ruby 不熟悉,但我认为它有某种功能可以等待多种事情。 如果可以的话,我建议您不要使用睡眠,而是等待两件事\

  1. 一个定期唤醒线程以完成其工作的计时器。
  2. 当进程需要取消或停止时设置的事件(例如捕获 control-C)。

如果有某种事件可以用来表示需要工作,那就更好了。 这将避免轮询计时器。 这通常会导致资源利用率降低和系统响应速度更快。

Using sleep is likely OK for quick and dirty things. But for things that need a bit more robustness or reliability I suggest that sleep is evil :) The problem with sleeping is that the thread is (I'm assuming Windows here...) is truly asleep - the scheduler will not run the thread until some time after sleep interval has passed.

During this time, the thread will not wake up for anything. This means it cannot be canceled, or wake up to process some kind of event. Of course, the process can be killed, but that doesn't give the sleeping thread an opportunity to wake up and clean anything up.

I'm not familiar with Ruby, but I assume it has some kind of facility for waiting on multiple things. If you can, I suggest that instead of using sleep, you waint on two things\

  1. A timer that wakes the thread periodically to do its work.
  2. An event that is set when he process needs to cancel or quite (trapping control-C for example).

It would be even better if there is some kind of event that can be used to signal the need to do work. This would avoid polling on a timer. This generally leads to lower resource utilization and a more responsive system.

梦里的微风 2024-08-05 05:19:45

如果您不需要精确的间隔,那么这对我来说是有意义的。 如果您需要在没有漂移的情况下定期被唤醒,您可能需要使用某种外部计时器。 但是当您睡眠时,您不会使用 CPU 资源。 任务切换是昂贵的。

If you don't need an exact interval, then it makes sense to me. If you need to be awoken at regular times without drift, you probably want to use some kind of external timer. But when you're asleep, you're not using CPU resources. It's the task switch that's expensive.

☆獨立☆ 2024-08-05 05:19:45

虽然 sleep(timeout) 非常适合某些设计,但有一个重要的警告需要记住。

Ruby 使用 SA_RESTART 安装信号处理程序(请参阅此处),这意味着您的 sleep (或等效的 select(nil, nil, nil, timeout))不能轻易被中断。 您的信号处理程序将触发,但程序将立即返回睡眠。 如果您希望及时对 SIGTERM 等做出反应,这可能会很不方便。

考虑一下

#! /usr/bin/ruby
Signal.trap("USR1") { puts "Hey, wake up!" }
Process.fork() { sleep 2 and Process.kill("USR1", Process.ppid) }
sleep 30
puts "Zzz.  I enjoyed my nap."

……执行大约需要 30 秒,而不是 2 秒。

作为一种解决方法,您可以在信号处理程序中抛出异常,这会中断上面的睡眠(或其他任何内容!)。 您还可以切换到基于 select 的循环并使用 自管技巧在收到信号后“早”醒来。 正如其他人指出的那样,功能齐全的事件库也是可用的。

While sleep(timeout) is perfectly appropriate for some designs, there's one important caveat to bear in mind.

Ruby installs signal handlers with SA_RESTART (see here), meaning that your sleep (or equivalent select(nil, nil, nil, timeout)) cannot easily be interrupted. Your signal handler will fire, but the program will go right back to sleep. This may be inconvenient if you wished to react timely to, say, a SIGTERM.

Consider that ...

#! /usr/bin/ruby
Signal.trap("USR1") { puts "Hey, wake up!" }
Process.fork() { sleep 2 and Process.kill("USR1", Process.ppid) }
sleep 30
puts "Zzz.  I enjoyed my nap."

... will take about 30 seconds to execute, rather than 2.

As a workaround, you might instead throw an exception in your signal handler, which would interrupt the sleep (or anything else!) above. You might also switch to a select-based loop and use a variant of the self-pipe trick to wake up "early" upon receipt of a signal. As others have pointed out, fully-featured event libraries are available, too.

ぶ宁プ宁ぶ 2024-08-05 05:19:45

它在睡眠时不会使用 CPU,但如果你睡了很长时间,我会更担心正在运行的 ruby​​ 解释器在不执行任何操作时占用内存。 不过,这没什么大不了的。

It wont use CPU while it is sleeping but if you are sleeping for a long time I would be more concerned of the running ruby interpreter holding up memory while it wasn't doing anything. This is not that big of a deal tho.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文