2015-01-21 12 views
6

Ho un oggetto complesso, my_object, che maresciallo condi smistamento in Ruby 2.2.0 2.1.5 lento di

Marshal.dump (my_object)

ho benchmark le prestazioni di chiamare quella linea 100 volte in entrambe 2.1.5p273 e 2.2.0, e al di sotto sono i risultati:

2.1.5 
        user  system  total  real 
Marshal Dump 7.310000 0.120000 7.430000 ( 8.988470) 
Marshal Dump 7.520000 0.050000 7.570000 ( 8.210356) 
Marshal Dump 7.610000 0.050000 7.660000 ( 8.432685) 

2.2.0 
        user  system  total  real 
Marshal Dump 26.480000 0.150000 26.630000 (29.591742) 
Marshal Dump 24.100000 0.300000 24.400000 (28.520397) 
Marshal Dump 26.210000 0.210000 26.420000 (29.993412) 

(. ho eseguito il punto di riferimento per 3 volte per ogni versione, di essere approfondita)

Come si può vedere, si tratta di prendendo io n eccesso di 3 volte più lungo in 2.2.0 vs 2.1.5. Ho azzerato su Marshal.dump perché, usando la gemma del rubino-prof, mi ha mostrato che quella era la linea che si stava comportando male; ma non riesco a trovare un modo per ottenere i metodi che Marshal.dump stesso chiama nel profiler.

Edit: vedere la mia risposta con un Repro minimo, ritrovato dopo molti esperimenti

+1

Per coloro che desiderano seguirlo, l'ho ridotto a una riproduzione minima e l'ho registrato qui: https://bugs.ruby-lang.org/issues/10761. Il problema non sembra essere la dimensione ma piuttosto la complessità, poiché ho dovuto creare un oggetto con molti livelli di oggetti nidificati al suo interno per riprodurre il problema. – davej

+1

Il modo in cui hai modificato la domanda originale scompare e questa domanda ... beh, non è una domanda, è fondamentalmente una risposta. Penso che il tutto sia interessante, ma per gli standard SO penso che meriti un downvote. – iain

+0

@ian: Davvero? Le mie scelte erano lasciare la domanda che non aiutava veramente nessuno, o pubblicare qualcosa che è, direi, un grosso problema, o eliminare l'intera domanda. Ho fatto quello che sentivo fosse il migliore per la comunità. Onestamente, è una meschinità come la tua che dà ai geek una cattiva reputazione. – davej

risposta

4

La posizione di origine è nil.

Marshal.method(:dump).source_location 
#=> nil 

Ciò significa che si tratta di un metodo implementato C, e non c'è altro codice Ruby che è possibile rintracciare. In altre parole, è un metodo atomico/elementare.

Se ritieni che il tuo risultato sia valido, ti suggerisco di postarlo come bug in Ruby trunk. Diversi problemi di prestazioni sono stati trovati per le versioni più recenti di Ruby, quindi il tuo caso non sembra insolito.

+0

grazie per la tecnica e il suggerimento. Ora inizia la ricerca per trovare una versione riproducibile del problema! – davej

1

Fa fluttuare il marshalling che causa il rallentamento.

require 'benchmark' 

class ToBeMarshaled 

    def initialize n 
    @a = [] 
    n.times do |i| 
     @a << i.to_f 
    end 
    end 

end 

tbm = ToBeMarshaled.new(10000) 

n = 100 

Benchmark.bm do |x| 
    x.report("Marshal Dump") {for i in 1..n; Marshal.dump(tbm); end} 
end 

risultati (correvano benchmark 3 volte per ogni versione di Ruby):

2.1.5 
        user  system  total  real 
Marshal Dump 0.640000 0.010000 0.650000 ( 0.744080) 
Marshal Dump 0.670000 0.000000 0.670000 ( 0.758597) 
Marshal Dump 0.650000 0.020000 0.670000 ( 0.747583) 

2.2.0 
        user  system  total  real 
Marshal Dump 25.070000 0.220000 25.290000 (27.980023) 
Marshal Dump 24.100000 0.160000 24.260000 (26.633049) 
Marshal Dump 24.440000 0.230000 24.670000 (27.540826) 

~ 35 volte più lento.

Se si prende il ".to_f" fuori di tale codice, si ottiene:

2.1.5 
        user  system  total  real 
Marshal Dump 0.160000 0.000000 0.160000 ( 0.180247) 
Marshal Dump 0.180000 0.000000 0.180000 ( 0.189485) 
Marshal Dump 0.160000 0.010000 0.170000 ( 0.191304) 

2.2.0 
        user  system  total  real 
Marshal Dump 0.120000 0.010000 0.130000 ( 0.146710) 
Marshal Dump 0.130000 0.010000 0.140000 ( 0.159851) 
Marshal Dump 0.130000 0.000000 0.130000 ( 0.143917) 

2.2.0 bordi leggermente fuori 2.1.5.

Problemi correlati