Publicado Ruby 3.0.0

28/12/2020Artículo original

Nos complace anunciar la publicación de Ruby 3.0.0. Desde el 2015 desarrollamosRuby 3 con esfuerzo, con metas de desempeño, concurrencia y tipado. Especialmenteen desempeño, Matz estableció “Ruby3 será 3 veces más rápido que Ruby2”también conocido como Ruby 3×3.

Optcarrot 3000 frames

Con el punto de referencia Optcarrot, quemide desempeño con un solo hilo de ejecución con la carga de emular juegos para NES,¡logra un desempeño 3 veces más rápido que Ruby 2.0!

Se midió en el ambiente anotado en [benchmark-driver.github.io/hardware.html](https://benchmark-driver.github.io/hardware.html).La [contribución 8c510e4095](https://github.com/ruby/ruby/commit/8c510e4095) se usócomo Ruby 3.0. Podría no resultar 3 veces más rápido en de su ambiente o con otrospunto de referencia.

Ruby 3.0.0 cubre esas metas asi

  • Desempeño
  • Concurrencia RactorPlanificador de fibras (Fiber Scheduler)
  • Tipado (Análisis Estático)

Con la mejora en desempeño mencionada, Ruby 3.0 introduce diversascaracterísticas nuevas que se describen a continuación.

Desempeño

MJIT

Se implementaron muchas mejoras en MJIT. Ver detalles en NEWS.

Con Ruby 3.0, el compilador justo a tiempo (JIT) se supone que da mejoras endesempeño en cargas de trabajo limitadas, como juegos(Optcarrot),Inteligencia Artificila(Rubykon)o cualquier aplicación que emplee la mayoría del tiempo llamando unos pocos métodosmuchas veces.

Aunque Ruby 3.0 disminuyó significativamente el tamaño del código compilado justo a tiempo,aún no está listo para optimizar cargas de trabajo como aplicaciones Rails, quesuelen emplear el tiempo en muchos métodos, y por eso sufren de demasiados desatinoscon el i-cache debido al JIT. Esté pendiente de Ruby 3.1 que incluirá otrasmejoras en esta área.

Concurrencia / Paralelismo

Ractor (experimental)

Un Ractor es una abstracción de concurrencia al estilo Actor-modelo,diseñada para brindar una forma de ejecución en paralelo sinpreocuparse por la seguridad de los hilos (thread-safe) de ejecución.

Puede crear múltiples ractors y puede ejecutarlos en paralelo.Un Ractor permite hacer programas paralelos con seguridad en los hilosde ejecución porque los ractors no comparten objetos normales.La comunicación entre ractors se soporta mediante envío demensajes.

Para limitar los objetos que se comparten, Ractor introduce diversasrestricciones a la sintaxis de Ruby (no hay cambio cuando no hay múltiplesRactors).

La especificación e implementación no es madura y podría cambiar afuturo, por eso esta característica se señala como experimentaly con el primer Ractor.new se presenta una advertencia de característicaexperimental.

El siguiente programita mide el tiempo de ejecución de un punto de referenciafamoso, la función tak(Función Tak – Wikipedia),que se ejecuta 4 veces de manera secuencial o 4 veces en paralelo con ractores.

deftarai(x,y,z)=x<=y?y:tarai(tarai(x-1,y,z),tarai(y-1,z,x),tarai(z-1,x,y))require'benchmark'Benchmark.bmdo|x|# sequential versionx.report('seq'){4.times{tarai(14,7,0)}}# parallel versionx.report('par'){4.times.mapdoRactor.new{tarai(14,7,0)}end.each(&:take)}end
Benchmark result: user system total realseq 64.560736 0.001101 64.561837 ( 64.562194)par 66.422010 0.015999 66.438009 ( 16.685797)

El resultado se midió en Ubuntu 20.04, con procesador Intel(R) Core(TM) i7-6700(4 núcleos, 8 hilos por hardware). Muetra que la versión paralelaes 3.87 veces más rápido que la versión secuencial.

  Machine Learning: ¿Qué es y para qué sirve el análisis exploratorio? (con un ejemplo para que lo veas claro)

Vea más detalles en doc/ractor.md.

Planificador (Scheduler) de Fibras

Se introduce Fiber#scheduler para interceptar operaciones que bloquean.Esto permite una concurrencia liviana sin cambiar elcódigo existente. De un vistazo general y vea como funciona en“Don’t Wait For Me, Scalable Concurrency for Ruby 3”.

Los métodos y clases que se soportan en el momento son:

  • Mutex#lock, Mutex#unlock, Mutex#sleep
  • ConditionVariable#wait
  • Queue#pop, SizedQueue#push
  • Thread#join
  • Kernel#sleep
  • Process.wait
  • IO#wait, IO#read, IO#write y métodos relacionados (e.g.#wait_readable, #gets, #puts y así sucesivamente).
  • IO#selectno es soportado.

Este programa de ejemplo realizará varias peticiones HTTP concurrentemente:

require'async'require'net/http'require'uri'Asyncdo["ruby","rails","async"].eachdo|topic|AsyncdoNet::HTTP.get(URI"https://www.google.com/search?q=#{topic}")endendend

Usa async que provee un ciclo de eventos.Este ciclo de eventos usa ganchos Fiber#scheduler para lograrun Net::HTTP no-bloqueante. Otras gemas pueden usar esta interfazpara proveer ejecución no-bloqueante para Ruby, y aquellas gemas puedenser compatibles con otras implementaciones de Ruby (e.g. JRuby, TruffleRuby)que pueden soportar los mismos ganchos no-bloqueantes.

Análisis Estático

RBS

RBS es un lenguaje para describir los tipos de los programas Ruby.

Los verificadores de tipos, incluyendo TypeProf y otras herramientasque soporten RBS entenderán mejor los programas Ruby con definiciones RBS.

Usted puede escribir la definición de clases y módulos: métodos que sedefinen en la clase, variables de instancia y sus tipos, y relacionesde herencia/mix-in.

El objetivo de RBS es soportar los patrones que comúnmente se venen programas en Ruby y permitir escribir tipos avanzados incluyendotipos unión, sobrecarga de métodos y genéricos. También soporta tipadopato (duck typing) con tipos de interfaz.

Ruby 3.0 se distribuye con la gema rbs, que permite analizary procesar definiciones de tipos escritas en RBS.El siguiente es un pequeño ejemplo de RBS con una clase, un modulo ydefiniciones de constantes.

module AplicacionMensajeria VERSION: String class Channel attr_reader nombre: String attr_reader mensajes: Array[Mensaje] attr_reader usuarios: Array[Usuario | Robot] # `|` significa tipos unión, `Usuario` o `Robot`. def initialize: (String) -> void def publicar: (String, de: Usuario | Robot) -> Mensaje # Se soporta sobrecarga de métodos. | (File, de: Usuaurio | Robot) -> Mensaje endend

Ver más detalles en elarchivo README de la gema rbs.

TypeProf

TypeProf es una herramienta para análisis de tipos incluida en el paqueteRuby.

Actualmente, TypeProf sirve como una forma de inferencia de tipos.

Lee código Ruby plano (sin anotiaciones de tipos), analiza que métodos sedefinen y como se usan, y genera un prototipo de la firma de los tipos enformato RBS.

  Cuando una oferta de trabajo te pide más años de experiencia en un software de los que han pasado desde que se creó

Aquí hay una simple demostración de TypeProf.

Entrada de ejemplo:

# prueba.rbclassUsuariodefinitialize(nombre:,edad:)@nombre,@edad=nombre,edadendattr_reader:nombre,:edadendUsuario.new(nombre: "Juan",edad: 20)

Salida de ejemplo:

$ typeprof prueba.rb# Classesclass Usuario attr_reader nombre : String attr_reader edad : Integer def initialize : (nombre: String, edad: Integer) -> [String, Integer]end

Puede ejecutar TypeProf, tras guardar el archivo de entrada como “prueba.rb” ytecleando “typeprof prueba.rb”.

También puede probar TypeProf en línea. (TypeProf corre al lado del servidor, así que ¡disculpe si no está operando!)

Ver detalles en la documentación de TypeProfy en las demostraciones.

TypeProf es experimental y aún no es una herramienta madura, sólo soporta unsubconjunto del lenguaje Ruby y la detección de errores de tipos es limitada.Pero está creciendo rapidamente para mejorar la cobertura de lascaracterísticas del lenguaje, el desempeño del análisis y la usabilidad.Toda retroalimentación es bienvenida.

Otras características notables

  • El reconocimiento de patrones en una línea se ha rediseñado (experimental)se añade =>. Puede usarse como una asignación al lado derecho.0=>apa#=> 0{b: 0,c: 1}=>{b:}pb#=> 0in se ha cambiado para retornar true o false.# version 3.00in1#=> false# version 2.70in1#=> raise NoMatchingPatternError
  • Se agrega un patrón Encontrar (Find). (experimental)case[“a”,1,”b”,”c”,2,”d”,”e”,”f”,3]in[*pre,String=>x,String=>y,*post]ppre#=> [“a”, 1]px#=> “b”py#=> “c”ppost#=> [2, “d”, “e”, “f”, 3]end
  • Se agrega una definición de métodos que no requiere end.defcuadrado(x)=x*x
  • Hash#except ahora es un método incorporado.h={a: 1,b: 2,c: 3}ph.except(:a)#=> {:b=>2, :c=>3}
  • Memory view se agrega como característica experimentalEste es un nuevo conjunto de llamados en la API de C para intercambiar áreas de memoria puras, como arreglos numéricos o mapas de bits de imagenes, entre las librerías que son extensiones. Las librerías que son extensiones pueden compartir también los metadatos del área de memoria que constan de la forma, el formato del elemento y así sucesivamente. Usando esta clase de metadatos, las librerías que son extensiones pueden compartir apropiadamente incluso un arreglo multidimensional. Esta nueva característica se diseñó empleando como referencia el protocolo de colchón (buffer ) de Python.

Performance improvements

  • Pegar código largo en IRB es 53 veces más rápido que con Ruby 2.7.0.Por ejemplo el tiempo requerido para pegar este código de ejemplopasa de 11.7 segundos a 0.22 segundos.
  • A IRB se le ha añadido la orden measure. Permite una medición sencilla del tiempode ejecución.irb(main):001:0> 3=> 3irb(main):002:0> measureTIME is added.=> nilirb(main):003:0> 3processing time: 0.000058s=> 3irb(main):004:0> measure :off=> nilirb(main):005:0> 3=> 3

Otros cambios notables desde 2.7

  • Los argumentos de palabra clave se separan de otros argumentos. En principio, el código que presente una advertencia en Ruby 2.7 nofuncionará. Ver detalles eneste documento.Por cierto, el re-envío de argumentos ahora soporta argumentos principales.defmethod_missing(meth,…)send(:”do_#{meth}”,…)end
  • El reconocimiento de patrones (case/in) ya no es experimental.
  • La característica $SAFE se eliminó por completo; ahora es una variableglobal normal.
  • El orden de la traza de llamados (backtrace) se había invertidoen Ruby 2.5, pero esto se ha revertido. Ahora las trazas de llamados secomportan como en Ruby 2.4; se imprime primero un mensaje de error y el númerode línea donde ocurrió la excepción; las funciones que había hecho la llamadase imprimen después.
  • Se actualizaron algunas librerías estándar. RubyGems 3.2.3Bundler 2.2.3IRB 1.3.0Reline 0.2.0Psych 3.3.0JSON 2.5.1BigDecimal 3.0.0CSV 3.1.9Date 3.1.0Digest 3.0.0Fiddle 1.0.6StringIO 3.0.0StringScanner 3.0.0etc.
  • Las siguientes librerías ya no son gemas distribuidas con ruby. Instale lasgemas correspondientes para usar sus funcionalidades. sdbmwebricknet-telnetxmlrpc
  • Las siguientes gemas por omisión ahora se distribuyen con Ruby.
  • Los siguientes archivos de stdlib ahora son gemas y se publicaron enrubygems.org. Englishabbrevbase64drbdebugerbfindnet-ftpnet-httpnet-imapnet-protocolopen-urioptparseppprettyprintresolv-replaceresolvrindasetsecurerandomshellwordstempfiletmpdirtimetsortunweakrefdigestio-nonblockio-waitnkfpathnamesyslogwin32ole
  Entrevista a Javier Cantón, el padre de Wave Engine

Ver más detalles en el archivoNEWSo en la bitácora de contribuciones

Con estos cambios, 4028 archivos cambiados, 200058 inserciones(+), 154063 eliminaciones(-)desde Ruby 2.7.0!

!Feliz Navidad, Feliz Año Nuevo y disfrute programando con Ruby 3.0!

Descargas

  • https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.tar.gzSIZE: 19539509SHA1: 233873708c1ce9fdc295e0ef1c25e64f9b98b062SHA256: a13ed141a1c18eb967aac1e33f4d6ad5f21be1ac543c344e0d6feeee54af8e28SHA512: e62f4f63dc12cff424e8a09adc06477e1fa1ee2a9b2b6e28ca22fd52a211e8b8891c0045d47935014a83f2df2d6fc7c8a4fd87f01e63c585afc5ef753e1dd1c1
  • https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.tar.xzSIZE: 14374176SHA1: c142899d70a1326c5a71311b17168f98c15e5d89SHA256: 68bfaeef027b6ccd0032504a68ae69721a70e97d921ff328c0c8836c798f6cb1SHA512: 2a23c2894e62e24bb20cec6b2a016b66d7df05083668726b6f70af8338211cfec417aa3624290d1f5ccd130f65ee7b52b5db7d428abc4a9460459c9a5dd1a450
  • https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.zipSIZE: 23862057SHA1: 2a9629102d71c7fe7f31a8c91f64e570a40d093cSHA256: a5e4fa7dc5434a7259e9a29527eeea2c99eeb5e82708f66bb07731233bc860f4SHA512: e5bf742309d79f05ec1bd1861106f4b103e4819ca2b92a826423ff451465b49573a917cb893d43a98852435966323e2820a4b9f9377f36cf771b8c658f80fa5b

Qué es Ruby

Ruby fue desarrollado inicialmente por Matz (Yukihiro Matsumoto) en 1993,y ahora es desarrollado como código abierto. Corre en muchasplataformas y se usa en todas partes del mundo especialmente paradesarrollo web.

Publicado por naruse el 2020-12-25
Traducción de vtamara

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Contiene enlaces a sitios web de terceros con políticas de privacidad ajenas que podrás aceptar o no cuando accedas a ellos. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad