2012-08-22 19 views
5

usando 1.9.2p290 rubí (2011-07-09 revisión 32553) [x86_64-linux]multiplicación de Fixnum más rápida en ruby?

que he estado haciendo un montón de perfiles y que ha llegado a mi conocimiento que el rubí Fixnum multiplicación es muy lento.

A través de algunos perfiles, he aprendido que esto es (parcialmente) porque cada llamada a Fixnum # * implica 6 llamadas a Kernel # kind_of.

Sé que puede escribir extensiones C, pero estas multiplicaciones se extienden por todo el código. Entonces, ¿hay alguna forma de evitar esto por encima de Ruby?

gracias

+0

Eso es bastante interesante. ¿Qué estás usando para perfilar el código? Hubiera supuesto que la multiplicación nativa de Ruby fue relativamente eficiente. –

+0

@BlakeTaylor Estoy usando ruby-prof – user844942

Respuesta

5

tengo serias dudas de que esas medidas son exactas, por varias razones:

  1. Usted no indica qué implementación de Rubí está utilizando, pero ruby-prof es un perfilador de Ruby. Perfila el código de Ruby. No hay implementación de Ruby que sepa dónde Fixnum#* es el código de Ruby. En MRI, YARV, MRuby y tinyrb es código C, en Rubinius es código C++, en MacRuby es código Objective-C, en JRuby y XRuby es código Java, en RubyGoLightly es código Go, en IronRuby y Ruby. NET es código C#, en MagLev y SmallRuby es código Smalltalk, en Cardinal es código PASM. ruby-prof puede crear un perfil de código de Ruby, no puede crear un perfil de C, C++, Objective-C, Java, C#, Go, Smalltalk o PASM. Solo Ruby. Por lo tanto, simplemente no puede perfil Fixnum#*.

  2. No es necesario que Fixnum#* verifique la clase más de una vez. Sabe que self es un Fixnum, porque de lo contrario la llamada no se habría enviado al método Fixnum#* en primer lugar, por lo que solo debe verificar el argumento. También necesita verificar si el resultado se ajustará a Fixnum o no, pero lo haría internamente, no con una llamada al kind_of? (de hecho, eso ni siquiera tiene sentido: para poder llamar a un método en el resultado de la multiplicación, primero tendría que construir el objeto resultante, y para construir el objeto resultante, ya tendría que saber si encaja en un Fixnum o no).

  3. No haría esa verificación de clase llamando al kind_of? y revisando toda la maquinaria de envío de métodos y de búsqueda de métodos de Ruby. Es una función interna de la aplicación Ruby, que tiene acceso a todos los detalles de implementación internos privados, sería simplemente comprobar la clase directa o llamar a alguna función intérprete interno, no el método de Ruby kind_of?

  4. he comprobado la ejecución de Fixnum#* en varias implementaciones populares de Ruby y no encontró ninguna llamada al kind_of?. Lamentablemente, no indicó la implementación de Ruby que está utilizando.

+0

Gracias por su respuesta. Ciertamente podría estar equivocado acerca de esto. Esto es lo que estoy viendo mi producción de perfiles:? '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' no estoy seguro de si Estoy familiarizado con la salida del gráfico de Ruby-prof, pero las líneas debajo del nombre de un método son métodos llamados desde ese método. No tengo idea de qué implementación estoy usando. O vino con Ubuntu o lo obtuve de apt-get. ¿Sabes cómo puedo averiguarlo? – user844942

+1

Tenías razón, por cierto. Vea mi respuesta si tiene curiosidad sobre lo que estaba sucediendo. – user844942

2

Bueno, creo que lo he descubierto. Estoy usando la biblioteca GSL, y parece que parchea Fixnum # * con código que puedes ver aquí: https://github.com/romanbsd/rb-gsl/blob/master/lib/gsl/oper.rb#L15

Este código incluye ... espera ... 6 llamadas a Kernel # kind_of? en una gran declaración "o".

No voy a pretender comprender totalmente cómo funciona o por qué sucede, pero la ruta del código coincide perfectamente con la salida del generador de perfiles.

Cuestiones relacionadas