100% cpu

ho un applicazione che improvvisamente inizia a richiedere risorse
infinite,
questo succede quando carico una view che deve mostrarmi un elenco di
eventi filtrati per data e posizionarli in una tabella ho un ciclo di
questo tipo:

result = %(

)
(9…19).each do |hour|
result << %()
(0…6).each do |day|
result << %()
end
result << %()
end
result << %(
#{ get_event(day, hour) }
)

get_event prende i dati da una hash strutturata così:
eventi = { day_1 => { 9 => [events], 10 => [events], …}, day_2 =>
… }

qualche idea?

Ciao Alessandro,

mi verrebbe da chiedere: quanto è grande l’hash eventi e quanto sono
grandi i suoi valori? E’ possibile che la to_s diventi impegnativa.
Bisognerebbe però lanciare un profiler per sapere dove passa il suo
tempo l’applicazione.

Paolo

Alessandro S. wrote:

ho un applicazione che improvvisamente inizia a richiedere risorse
infinite,
questo succede quando carico una view che deve mostrarmi un elenco di
eventi filtrati per data e posizionarli in una tabella ho un ciclo di
questo tipo:

result = %(

)
(9…19).each do |hour|
result << %()
(0…6).each do |day|
result << %()
end
result << %()
end
result << %(
#{ get_event(day, hour) }
)

get_event prende i dati da una hash strutturata così:
eventi = { day_1 => { 9 => [events], 10 => [events], …}, day_2 =>
… }

qualche idea?

Paolo M. wrote:

mi verrebbe da chiedere: quanto è grande l’hash eventi e quanto sono
grandi i suoi valori?

L’hash contiene oggetti di tipo evento molto “piccoli” 4 campi di
tabellari (nome descrizione data utente id) ed è quasi sempre vuoto
durante i test per cui dovrebbe andare a razzo …

E’ possibile che la to_s diventi impegnativa.
Bisognerebbe però lanciare un profiler per sapere dove passa il suo
tempo l’applicazione.

non avevo pensato al profiler, ora provo e vedo!

il problema è sulla string concatenation,

qualcuno ha idea su come velocizzarlo??

ho provato con :

pippo << “abcdef…”
pippo = pippo + “abcdef…”
pippo = “#{pippo}abcdef…”

stessi risultati… circa 10 secondi per 200 righe …

Hai provato con la StringIO ?

result = StringIO.new
result << %(

)
(9…19).each do |hour|
result << %()
(0…6).each do |day|
result << %()
end
result << %()
end
result << %(
#{ get_event(day, hour) }
)
result.rewind

<%= result.read %>

4 ore di prove e test e ho risolto, tutto dipendeva da strftime, per le
date non è performante conviene fare a mano ad
es.
“#{data.day}-#{data.month}-#{data.year}” vs data.strftime("%d-%m-%Y")
differenza quasi 0.2 secondi!!!
(il primo è istantaneo)

Si impara sempre qualcosa di nuovo!

Alessandro S. wrote:

il problema è sulla string concatenation,

qualcuno ha idea su come velocizzarlo??

ho provato con :

pippo << “abcdef…”
pippo = pippo + “abcdef…”
pippo = “#{pippo}abcdef…”

stessi risultati… circa 10 secondi per 200 righe …

per chiarezza, il ciclo che sto usando è:

first.upto(last) do |cur|
  cal << %(<td>#{button({ :nocenter => true, :class => "action 

week_selector", :id => “week_View_#{cur.strftime(”%W")}#{cur.year}",
:alt => "#{
(‘Show Week’)} #{cur.strftime("%W")}" })}) if cur.wday
== first_weekday
cell_text, cell_attrs = block.call(cur)
cell_text ||= cur.mday
cell_attrs ||= {:class => options[:day_class]}
cell_attrs[:class] += " weekendDay" if [0, 6].include?(cur.wday)
cell_attrs[:class] += " today" if (cur == Date.today) and
options[:show_today]
cell_attrs = cell_attrs.map {|k, v| %(#{k}="#{v}") }.join(" “)
cal << %(<td #{cell_attrs}>

#{cur.day}<div class=“calendar_cell
#{cur.strftime(”%d_%m_%Y”)}">
#{ clerk_calendar.have_appo_day?(cur) ? %(<img
onclick=“show_appo(this)” class=“month_appo #{cur.strftime(”%d_%m_%Y")}"
src="/images/icon/month_appo.png" />) : “”}
)
cal << “” if cur.wday == last_weekday
end

fa parte di un plugin (ovviamente modificato per le mie esigenze), e
costruisce una vista mensile per un calendario.

Questo pezzo di codice ci mette circa 7 secondi (sono ben 30 cicli) il
tempo delle chiamate ai vari metodi è trascurabile (vicino a 0)

Alessandro S. wrote:

4 ore di prove e test e ho risolto, tutto dipendeva da strftime, per le
date non è performante conviene fare a mano ad
es.
“#{data.day}-#{data.month}-#{data.year}” vs data.strftime(“%d-%m-%Y”)
differenza quasi 0.2 secondi!!!
(il primo è istantaneo)

Si impara sempre qualcosa di nuovo!

Fantastico! Googlando dopo questa notizia ho trovato Date::Performance,
una gemma che riscrive l’implementazione della classe Date in C.

Documentazione: http://tomayko.com/src/date-performance/
Installazione: gem install date-performance --source=http://tomayko.com

Attenzione però che durante l’installazione dice

WARNING: RubyGems 1.2+ index not found for:
http://tomayko.com/

e fin qui tutto chiaro, e poi:

RubyGems will revert to legacy indexes degrading performance.

il che è un po’ preoccupante anche perché non ho trovato spiegazioni in
giro. Immagino però che le performance ridotte siano quelle di rubygems.

L’applicazione Rails su cui sto lavorando invece continua a funzionare
dopo la require ‘date/performance’ per cui tutto bene. Solo che non era
lenta prima e non pare più veloce adesso, anche se di strftime ne usa.

Se Alessandro avesse ancora a portata di mano il profiler forse potrebbe
dirci se questa nuova strftime è veloce quanto dice. Sarebbe meglio una
strftime veloce che la conversione manuale, no?

Paolo

Ho inserito i risultati del test sul mio blog:

http://www.webair.it/blog/2009/03/05/ruby-ancora-sulle-prestazioni/

Paolo M. wrote:

Alessandro S. wrote:

4 ore di prove e test e ho risolto, tutto dipendeva da strftime, per le
date non è performante conviene fare a mano ad
es.
“#{data.day}-#{data.month}-#{data.year}” vs data.strftime(“%d-%m-%Y”)
differenza quasi 0.2 secondi!!!
(il primo è istantaneo)

Si impara sempre qualcosa di nuovo!

Fantastico! Googlando dopo questa notizia ho trovato Date::Performance,
una gemma che riscrive l’implementazione della classe Date in C.

Documentazione: http://tomayko.com/src/date-performance/
Installazione: gem install date-performance --source=http://tomayko.com

Attenzione però che durante l’installazione dice

WARNING: RubyGems 1.2+ index not found for:
http://tomayko.com/

e fin qui tutto chiaro, e poi:

RubyGems will revert to legacy indexes degrading performance.

il che è un po’ preoccupante anche perché non ho trovato spiegazioni in
giro. Immagino però che le performance ridotte siano quelle di rubygems.

L’applicazione Rails su cui sto lavorando invece continua a funzionare
dopo la require ‘date/performance’ per cui tutto bene. Solo che non era
lenta prima e non pare più veloce adesso, anche se di strftime ne usa.

Se Alessandro avesse ancora a portata di mano il profiler forse potrebbe
dirci se questa nuova strftime è veloce quanto dice. Sarebbe meglio una
strftime veloce che la conversione manuale, no?

Paolo

Bhe ho fatto un pò di test (un bel pò) non ho installato
date-performance (che avevo trovato anche io :stuck_out_tongue: ) per quei messaggi
inquietanti…

Allora sulla classe Date passando da una chiamata strftime a una
“manuale” risparmio in media 1 decimo di secondo, se nel codice hai
poche chiamate non te ne accorgi, ma un ciclo come il mio che ne
eseguiva una 60-70ina inizia a diventare doloroso…

appena ho 1 oretta faccio una serie di test con profiler sulle 3 classi
e pubblico i risultati

Alessandro S. wrote:

Ho inserito i risultati del test sul mio blog:

WebAir | web. for passion » Ruby – Ancora sulle Prestazioni

Ottimo lavoro. Ne ho approfittato per inserire come commento i risultati
dei benchmark con date-performance.

Riassunto: Date.strftime si velocizza di 60 volte. I dettagli sono sul
blog.

Paolo M. wrote:

Alessandro S. wrote:

Ho inserito i risultati del test sul mio blog:

WebAir | web. for passion » Ruby – Ancora sulle Prestazioni

Ottimo lavoro. Ne ho approfittato per inserire come commento i risultati
dei benchmark con date-performance.

Riassunto: Date.strftime si velocizza di 60 volte. I dettagli sono sul
blog.

La installo subito!
(analizzando i benchmark ho notato che la lentezza di date deriva da un
sacco di chiamate alla classe String che come detto in precedenza è iper
lenta)