2010-02-17 17 views
5

Stavo cercando un esempio online che dimostrava un timer in ruby ​​e ho trovato il codice qui sotto. Funziona come previsto ma ha senso che questo semplice programma utilizzi 30Mo di memoria (come mostrato in Windows Task Manager) e troppa CPU?Timer in prestazioni Ruby

Grazie mille

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

non riesco a immaginare come quel codice ha un senso ... I fili non sono mai uniti, in modo time_spent sarà sempre 0 e il ciclo pile appena su discussioni che corre parallela se ther carico di lavoro richiede più di 5 secondi. – hurikhan77

+0

Grazie a hurikhan77, ti dispiace indicarmi un documento o un libro sui thread, quindi non devo fare domande stupide;)? – Elsanto

+0

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

risposta

11

Come notato nei commenti alla domanda, tutto quello che serve per farlo funzionare è che si uniscono sul filo:

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

Tuttavia, in quanto si trova , non c'è alcun motivo per utilizzare i thread per il codice nella questione:

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 

Ora, se quello che vuoi è un filo esimo fa qualcosa a intervalli, in modo che il programma principale possa fare qualcos'altro, quindi avvolgere l'intero ciclo in una discussione.

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

Grazie mille Wayne. Ultima domanda: il codice occupa ancora 30Mo nella memoria virtuale in Windows, è normale? Grazie mille! – Elsanto

+0

@Elsanto, non so cosa sia normale in Windows. In Linux, "sleep 10; exit" occupa circa 9 MB; il codice precedente, circa 16 MB. –

+0

Ci vuole molta memoria perché Ruby è un linguaggio dinamico in esecuzione su una macchina virtuale Ruby. Se lo traduci in C, scommetto che non avrai più di 1 Mb di memoria usag (a meno che tu non abbia perdite di memoria). Ma in un mondo in cui 8.000.000 Mb costano circa 50 dollari, penso che 30 Mb ($ 0.0001875 dllrs) non siano un problema. –