2010-02-17 17 views
5

Szukałem przykładu online pokazującego zegar w rubinie i natrafiłem na poniższy kod. Działa zgodnie z oczekiwaniami, ale czy ma to sens, że ten prosty program wykorzystuje 30 MB pamięci (jak pokazano w Menedżerze zadań Windows) i zbyt dużo procesora?Timer w wykonaniu Ruby

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

Nie mogę sobie wyobrazić, jak ten kod sens ... Nici nie są połączone, więc time_spent zawsze będzie 0 i pętla tylko stosy równoległych wątków działających jeśli Ther nakład pracy trwa dłużej niż 5 sekund. – hurikhan77

+0

Dziękuję hurikhan77, czy mogę wskazać mi dokument lub książkę o wątkach, więc nie muszę zadawać głupich pytań;)? – Elsanto

+0

http://ruby-doc.org/docs/ProgrammingRuby/html/tut_threads.html –

Odpowiedz

11

Jak zauważył w komentarzach na pytanie, wystarczy zrobić to praca jest, aby przyłączyć się na wątku:

#!/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 
... 

Jednak, jak siedzi , nie ma powodów, by używać wątki kodu w pytaniu:

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 

teraz, jeśli to, co chcesz, jest wątek th co jakiś czas robi coś, aby główny program mógł zrobić coś innego, a potem owinąłbyś całą pętlę w wątek.

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 
+0

Wielkie dzięki Wayne. Ostatnie pytanie: kod nadal zajmuje 30Mo w pamięci wirtualnej w Windows, czy to normalne? Wielkie dzięki! – Elsanto

+0

@Elsanto, nie wiem, co jest normalne w systemie Windows. W Linuksie "sleep 10; exit" zajmuje około 9 MB; powyższy kod, około 16 MB. –

+0

Zajmuje to dużo pamięci, ponieważ Ruby jest dynamicznym językiem działającym na maszynie wirtualnej Ruby. Jeśli przetłumaczysz to na C, założę się, że nie dostaniesz więcej niż 1 Mb pamięci usag (chyba że masz wycieki pamięci). Ale w świecie, w którym 8 000 000 Mb kosztuje około 50 dolarów, myślę, że 30 Mb (0,0001875 $ dll) nie stanowi problemu. –