2012-08-22 11 views
5

utilizzando 1.9.2p290 rubino (2011-07-09 revisione 32553) [x86_64-linux]più veloce moltiplicazione Fixnum in rubino?

Ho fatto un sacco di profilazione ed è venuto alla mia attenzione che rubino Fixnum moltiplicazione è molto lento.

Attraverso alcuni profili, ho appreso che questo è (parzialmente) perché ogni chiamata a Fixnum # * comporta 6 chiamate a Kernel # tipo_di.

So che è possibile scrivere estensioni C, ma queste moltiplicazioni sono diffuse in tutto il codice. Quindi, c'è comunque da evitare questo sovraccarico all'interno di Ruby?

grazie

+0

È piuttosto interessante. Cosa stai usando per profilare il codice? Avrei immaginato che la moltiplicazione nativa di Ruby fosse relativamente efficiente. –

+0

@BlakeTaylor Sto usando ruby-prof – user844942

risposta

5

Dubito seriamente che queste misure sono accurate, per diverse ragioni:

  1. Non dichiarate quale implementazione di Ruby che si sta utilizzando, ma ruby-prof è un profiler di Ruby. Identifica il codice Ruby. Non esiste un'implementazione Ruby che conosca dove Fixnum#* è un codice Ruby. In MRI, YARV, MRuby e tinyrb è codice C, in Rubinius è codice C++, in MacRuby è codice Objective-C, in JRuby e XRuby è codice Java, in RubyGoLightly è codice Go, in IronRuby e Ruby. NET è il codice C#, in MagLev e SmallRuby è il codice Smalltalk, in Cardinal è il codice PASM. ruby-prof può profilare il codice Ruby, non può profilare C, C++, Objective-C, Java, C#, Vai, Smalltalk o PASM. Solo Ruby. Pertanto, è semplicemente impossibile profilo Fixnum#*.

  2. Non è necessario per Fixnum#* controllare la classe più di una volta. Sa che self è un Fixnum, perché altrimenti la chiamata non sarebbe stata inviata al metodo Fixnum#* in primo luogo, quindi è sufficiente controllare l'argomento. Inoltre, deve verificare se il risultato si adatta o meno a Fixnum, ma lo farebbe internamente, non tramite una chiamata a kind_of? (infatti, non ha nemmeno senso: per poter chiamare un metodo sul risultato della moltiplicazione, dovrebbe prima costruire l'oggetto risultato, e per costruire l'oggetto risultato, dovrebbe già sapere se si adatta a Fixnum o meno).

  3. Non farebbe questo controllo di classe chiamando kind_of? e passando attraverso l'intero sistema di ricerca metodo e dispacciamento metodo Ruby. E 'una funzione interna di attuazione Ruby, ha accesso a tutti i dettagli di implementazione interni privati, sarebbe solo verificare la classe direttamente o chiamare una qualche funzione interprete interno, non il metodo di Ruby kind_of?

  4. ho controllato l'attuazione di Fixnum#* in varie implementazioni popolari di Ruby e non ha trovato qualsiasi chiamate a kind_of?. Sfortunatamente, non hai indicato quale implementazione di Ruby stai usando.

+0

Grazie per la risposta. Potrei certamente sbagliarmi su questo. Ecco quello che sto vedendo la mia uscita profiler:? '23.52% 9.49% 5.17 2.08 0.00 3.08 808.533 Fixnum # *' ' 2.27 2.27 0.00 0.00 4851198/5355534 Kernel # kind_of' non sono sicuro se si Conosciamo l'output del grafico di ruby-prof, ma le linee al di sotto del nome di un metodo sono metodi chiamati da quel metodo. Non ho idea di quale implementazione sto usando. O è venuto con Ubuntu o l'ho preso da apt-get. Sai come posso scoprirlo? – user844942

+1

Avevi ragione, a proposito. Vedi la mia risposta se sei curioso di sapere cosa stava succedendo. – user844942

2

Beh, penso di aver capito. Sto usando il libray GSL, e sembra che corregga il Fixnum # * con il codice che puoi vedere qui: https://github.com/romanbsd/rb-gsl/blob/master/lib/gsl/oper.rb#L15

Questo codice include ... attendere ... 6 chiamate al numero # del kernel di tipo? in una grande enunciazione.

Non ho intenzione di fingere di capire completamente come funziona o perché succede, ma il percorso del codice si abbina perfettamente con l'output del profiler.

Problemi correlati