6 consejos de optimización para Ruby MRI

ruby, rails 1 comentario »

Ilya Grigorik ha publicado un interesante post con 6 consejos para optimizar nuestro código Ruby si utilizamos el intérprete MRI.

ruby

Minimizar las búsquedas en el AST

Si utilizamos Ruby 1.8, nuestro MRI no generará bytecode. Por ello, cada llamada a un método, cada utilización de una variable, etc., realizará una búsqueda en el Abstract Syntax Tree (AST), es decir, en una estructura en árbol que representa la sintaxis de nuestro código fuente.

Debemos, por lo tanto, tener en cuenta que abusar de la metaprogramación puede hacer que el rendimiento de nuestra aplicación se vea degradado.

Optimizar para la caché

En relación con el punto anterior, para minimizar las búsquedas en el AST, Ruby MRI mantiene una caché de las variables locales. Es decir, utilizar variables locales será más rápido:

@var = "local variable, which is cached by Ruby, and requires a single lookup"
self.var = "requires walking the AST, and results in multiple lookups"

Mejor la interpolación que la concatenación

puts "This string embeds #{var1} and #{var2} through interpolation"  # faster
puts "This string concatenates " << var1 << " and " << var 2  # slower

Utilizar métodos destructivos

Cuando disponemos de un método no destructivo y su pareja destructiva, como gsub y gsub!, suele ser más eficiente utilizar el método destructivo. Los métodos no destructivos suelen ser más lentos ya que tienen que realizar copias de los objectos.

hash = {}
hash = hash.merge({1 => 2}) # duplicates the original hash
hash.merge!({1 => 2}) # equivalent to previous line, and faster

Utilizar bloques en lugar de Symbol.to_proc

@widget_ids = @widgets.map(&:id) # Symbol.to_proc method, order of magniture slower...
@widget_ids = @widgets.collect {|w| w.id } # faster and simpler

Compruebalo tú mismo

Si tienes dudas sobré qué código será más rápido, es sencillo comprobarlo:

require 'benchmark'
 
n = 100000
Benchmark.bm do |x|
   x.report('copy') { n.times do ; h = {}; h = h.merge({1 => 2}); end }
   x.report('no copy') { n.times do ; h = {}; h.merge!({1 => 2}); end }
end
copy  0.350000   0.060000   0.410000 (  0.419445)
no copy  0.250000   0.020000   0.270000 (  0.276030)

Rails y subversion

ruby, rails 0 comentarios »

Si utilizamos subversion como software de control de versiones, cada vez que creemos un nuevo proyecto rails, habrá una serie de tareas que tendremos que llevar a cabo.

Supongamos que el repositorio está creado y accesible en la URL:

http://svn.misite.com/miproyecto

Lo primero que tendremos que hacer, siguiendo las buenas prácticas del control de versiones con subversion, es crear tres carpetas: trunk, tags y branches.

$ REPO=http://svn.misite.com/miproyecto
$ svn mkdir --message="Layout inicial" $REPO/trunk $REPO/tags $REPO/branches
Commit de la revisión 1.

Después creamos la aplicación rails como siempre:

$ rails miproyecto
      create  
      create  app/controllers
      create  app/helpers
      ...

Ahora, en lugar de hacer un svn import, lo recomendable es hacer un svn checkout del trunk en el directorio de la aplicación y a continuación añadir la estructura de directorios del proyecto. De esta manera podemos eliminar algunos ficheros del control de versiones antes de hacer el commit:

$ cd miproyecto
$ svn checkout $REPO/trunk .
Revisión obtenida: 1
$ svn add --force .
A         lib
A         lib/tasks
...

Los ficheros de log no necesitaremos que estén bajo el control de versiones:

$ svn revert log/*
Se revirtió 'log/development.log'
Se revirtió 'log/production.log'
Se revirtió 'log/server.log'
Se revirtió 'log/test.log'
$ svn propset svn:ignore "*.log" log
propiedad 'svn:ignore' asignada en 'log'

De la misma manera, como cada desarrollador puede tener un database.yml diferente, será una buena idea eliminarlo del control de versiones:

$ svn revert config/database.yml 
Se revirtió 'config/database.yml'
$ mv config/database.yml config/database.yml.sample
$ svn add config/database.yml.sample 
A         config/database.yml.sample
$ svn propset svn:ignore "database.yml" config
propiedad 'svn:ignore' asignada en 'config'
$ cp config/database.yml.sample config/database.yml

Asimismo, el fichero schema.rb, al ser generado dinámicamente por las migraciones, no tiene sentido tampoco que esté bajo el control de versiones:

$ svn propset svn:ignore "schema.rb" db
propiedad 'svn:ignore' asignada en 'db'

También interesará eliminar del control de versiones cualquier fichero que se genere en tmp:

$ svn propset svn:ignore "*" tmp
propiedad 'svn:ignore' asignada en 'tmp'

Ahora ya podremos hacer nuestro primer commit al repositorio:

$ svn commit -m "Nueva aplicación"

Entradas relacionadas


Enlaces :ruby, :rails => “junio 2008″

ruby, rails 0 comentarios »

Noticias destacadas de Ruby y Rails durante el mes de junio de 2008:


Enlaces :ruby, :rails => “mayo 2008″

ruby, rails 2 comentarios »

Noticias destacadas de Ruby y Rails durante el mes de mayo de 2008:


Ruby sube al octavo noveno puesto en el ranking TIOBE

ruby, rails 2 comentarios »

Hace poco comentaba que Ruby es el octavo lenguaje de programación que más libros vende. En el ranking que elabora TIOBE sobre la popularidad de los lenguajes de programación, Ruby ha subido también al octavo puesto al noveno puesto.

tiobe mayo 2008

En la gráfica puede observarse cómo los líderes siguen siendo Java y C, ambos lenguaje estáticos y ambos en clara tendencia bajista desde hace años. Visual Basic, PHP (se mantienen) y C++ (bajista) están prácticamente empatados. Perl, en sexto puesto, también es bajista desde hace unos tres años. Los lenguajes emergentes y en ascenso son Python, C#, Ruby y Delphi.

Visto en el blog de aspgems.