views:

113

answers:

1

Hi all, I was looking for an online example demonstrating a timer in ruby and came across the code below. It works as expected but does it make sense that this simple program uses 30Mo of memory (as shown in windows task manager) and way too much CPU?

Thanks a lot

def time_block
  start_time = Time.now
  Thread.new { yield }
  Time.now - start_time
end

def repeat_every(seconds)
  while true do
    time_spent = time_block { yield } # To handle -ve sleep interaval
    sleep(seconds - time_spent) if time_spent < seconds
  end
end

repeat_every(5) {
}
+1  A: 

As noted in the comments to the question, all it takes to make it work is that you join on the thread:

#!/usr/bin/ruby1.8

def repeat_every(interval, &block)
  loop do
    start_time = Time.now
    Thread.new(&block).join
    elapsed = Time.now - start_time
    sleep([interval - elapsed, 0].max)
  end
end

repeat_every(5) do
  puts Time.now.to_i
end

# => 1266437822
# => 1266437827
# => 1266437832
...

However, as it sits, there's no reason to use threads for the code in the question:

def repeat_every(interval)
  loop do
    start_time = Time.now
    yield
    elapsed = Time.now - start_time
    sleep([interval - elapsed, 0].max)
  end
end

repeat_every(5) do
  puts Time.now.to_i
end

# => 1266437911
# => 1266437916
# => 1266437921

Now, if what you want is a thread that does something at intervals, so that the main program can do something else, then you'll wrap that entire loop in a thread.

def repeat_every(interval)
  Thread.new do
    loop do
      start_time = Time.now
      yield
      elapsed = Time.now - start_time
      sleep([interval - elapsed, 0].max)
    end
  end
end

thread = repeat_every(5) do
  puts Time.now.to_i
end  
puts "Doing other stuff..."
thread.join

# => 1266438037
# => Doing other stuff...
# => 1266438042
# => 1266438047
Wayne Conrad
Thanks a lot Wayne.Last question : the code still takes up 30Mo in virtual memory in windows, is that normal?Thanks a lot!
Elsanto
@Elsanto, I don't know what's normal in Windows. In Linux, "sleep 10 ; exit" takes up about 9MB; the above code, about 16MB.
Wayne Conrad