[Ironruby-core] [ANN] IronRuby 0.6 Released

Jimmy Schementi Jimmy.Schementi at microsoft.com
Thu Jul 2 15:23:22 EDT 2009


The IronRuby team is pleased to announce a new release of IronRuby: IronRuby 0.6!

== Download IronRuby 0.6
http://ironruby.net/Download

You can also check out the source code for this release
http://github.com/ironruby/ironruby/tree/v0.6.0

For a nicely formatted version of these release notes:
http://blog.jimmy.schementi.com/2009/07/ironruby-06-released.html

A copy of these release notes and changes are also here:
http://rubyforge.org/frs/shownotes.php?group_id=4359&release_id=36423

Staying true to our "Conference-driven development schedule," this release is in conjunction with ... wait, there is no conference this time! Just a good ol' monthly release of IronRuby, chock full of awesomeness. And just so happens to be the 4th of July weekend, so hopefully you have some downtime this weekend and can give the new release a spin.


== What's in the Release?

Performance has been a major focus to this release, getting startup time quicker and optimizing built-in types. And there's been more progress with Ruby compatibility (Cucumber works!) and .NET interop. Silverlight binaries are back in the release, and there are a couple of samples to help you learn IronRuby.

Most of these descriptions are from Tomas's very detailed code review emails, so thanks Tomas! For more detailed information, please see the CHANGELOG (which includes all commit messages for the release ... not just "syncing to head of tfs")


-- Lazy method compilation

Last release adaptive compilation was enabled for IronRuby, which uses a  fast-to-start-up interpreter to start up the program, while code which gets run a lot is compiling on a background thread. This gave IronRuby significant performance improvements for large apps like Rails, which has improved startup by 2.5 times.

This release we've added "lazy method transformation" to the bag of startup performance tricks. In IronRuby 0.5, a method was transformed to the DLR AST as soon as it was defined. IronRuby 0.6 postpones the transformation until the first time the method is called. This significantly improves startup time. For example (not NGEN'd):

      require 'benchmark'
      Benchmark.bm { |x|   x.report {  require 'rubygems'  }  }

      user       system     total       real
  eager transformation
      1.622410   0.031200   1.653611 (  1.581316)
  lazy transformation
      1.170008   0.031200   1.201208 (  1.099220)

This has made Rails startup time 30% faster, coming in approximately 20 seconds on my dual-core laptop running Windows 7.


-- CLR member enumeration

Now methods like Module#instance_methods, etc, include CLR member names. Though it's a lot cooler than that. The array of methods returns contains strings for Ruby methods, and objects of type IronRuby::Clr::Name to represent CLR methods that can be called by either the actual CLR name or a mangled (Ruby-esk) name. ClrName has methods to_s, to_sym, to_str, <=>, inspect, dump so that it can be used wherever a string can be used. The display string for the name uses single quotes so that you can easily distinguish CLR (dual) names from regular names (plain mutable strings). CLR strings display themselves as single quoted strings, so this fits nicely.

  >>> System::Byte.instance_methods(false)
  => ["-", "%", "&", "*", "**", "/", "-@", "[]", "^", "|", "~", "+", "<", "<<",
      "<=", "<=>", "==", ">", ">=", ">>", "abs", "div", "divmod", "modulo",
      "quo", "to_f", "to_s", "zero?", "size", 'compare_to', 'equals',
      'get_hash_code', 'to_string', 'get_type_code']
  >>> l = System::Byte.instance_methods(false).last
  => 'get_type_code'
  >>> l.ruby_name
  => "get_type_code"
  >>> l.clr_name
  => "GetTypeCode"

Even cooler, this works well for meta-programming:

  class System::Decimal
    instance_methods(false).each do |name|
      mangled = '__' + name
      alias_method(mangled, name)
      private mangled
      define_method(name) do |*args|
        puts "method called: #{name}"
        send mangled, *args
      end
    end
  end

  x, y = System::Decimal.new(1), System::Decimal.new(2)
  p x + y                           # => "method called: +"
  p x.CompareTo(y)   # => "method called: compare_to"

A new set of define_method overloads, strongly typed to ClrName, have been added to enable this. They define the real method using the ruby_name and alias it using the clr_name. So both CompareTo and compare_to calls are intercepted.


-- Generic-Method Parameters-Inference

Thanks to some work by the IronPython team, IronRuby now has parameter
inference for generic methods.

  // c.dll
  public class C {
      public void Foo<T>(T x) { Console.WriteLine(typeof(T)); }
  }

  require 'c'
  C.new.foo(1)   # System.Int32
  C.new.foo("x") # IronRuby.Builtins.MutableString
  C.new.foo(1.0) # System.Double

This needs some more TLC before it works perfectly, but this lets you use simple LINQ methods from IronRuby.

  load_assembly "System.Core"
  #=> true
  System::Linq::Enumerable.First([1,2,3])
  #=> 1
  System::Linq::Enumerable.ElementAt([1,2,3,4,5], 2)
  #=> 3


-- Testing C# with Cucumber

This release of IronRuby runs the Cucumber testing framework rather well. Try out Cucumber against some C# code here: http://wiki.github.com/aslakhellesoy/cucumber/ironruby-and-net

Given a feature file (this being the addition.feature):

  Feature: Addition
    In order to avoid silly mistakes
    As a math idiot
    I want to be told the sum of two numbers

    Scenario Outline: Add two numbers
      Given I have entered <input_1> into the calculator
      And I have entered <input_2> into the calculator
      When I press add
      Then the result should be <output> on the screen

      Examples:
        | input_1 | input_2 | output |
        | 20      | 30      | 50     |
        | 2       | 5       | 7      |
        | 0       | 40      | 40     |

A step_definition file (calculator_steps.rb):

  require 'spec/expectations'
  require 'Calculator' # Calculator.dll

  Before do
    @calc = Demo::Calculator.new # A .NET class in Calculator.dll
  end

  Given "I have entered $n into the calculator" do |n|
    @calc.push n.to_i
  end

  When /I press add/ do
    @result = @calc.Add
  end

  Then /the result should be (.*) on the screen/ do |result|
    @result.should == result.to_i
  end

And a DLL:

  using System;
  using System.Collections.Generic;

  namespace Demo {
    public class Calculator {
      private List<int>args = new List<int>();

      public void Push(int n) {
        args.Add(n);
      }

      public int Add() {
        int result = 0;
        foreach(int n in args) {
          result += n;
        }
        return result;
      }
    }
  }

Cucumber will test the addition feature:

  3 scenarios (3 passed)
  12 steps (12 passed)
  0m0.753s


-- Silverlight building and updated binaries

This release re-adds Silverlight binaries to IronRuby, contained in the "silverlight" directory of the release. These bits have been integrated from the AgDLR project (http://github.com/jschementi/agdlr), and will be maintained in the IronRuby and IronPython source code repositories from now on. The AgDLR GitHub project will redirect to one of those for binaries for both languages in Silverlight. In addition, the SDLSDK (http://sdlsdk.codeplex.com) site will be redirecting to the IronRuby and IronPython CodePlex sites, for downloads, discussion, and issue tracking. AgDLR was a little side project to add new features to DLR Silverlight applications, and play around with Git. I'm very happy to see it merged back in with the languages.

See the integration commit for more information:
http://github.com/ironruby/ironruby/commit/33211840f7482ffaa4970a6e630725fad2a70f5d

Another notable change is that you can now build Silverlight binaries out of IronRuby's GitHub repository very easily. Given that you have Silverlight installed at "C:\Program Files\Microsoft Silverlight\2.0.40115.0", this will build IronRuby for Silverlight:

msbuild Merlin/Main/Languages/Ruby/Ruby.sln
  /p:Configuration="Silverlight Release"
  /p:SilverlightPath="C:\Program Files\Microsoft Silverlight\2.0.40115.0"

You can also build IronPython for Silverlight in a similar manner. Aliases for this will be added soon, but if you need a custom build of the DLR languages for Silverlight, this is the way to do it.


-- Samples

Six samples are included in this release. The first three are desktop samples in the "/samples" directory. The last three are Silverlight samples in the "/silverlight/samples" directory:

  1. Tutorial - An interactive IronRuby tutorial. Read more about it here:
     http://blog.jimmy.schementi.com/2009/06/ironruby-tutorial.html
  2. DiskUse - A small WPF application which visualizes the disk usage for
     a particular directory.
  3. IRPowerShell - a small library and sample applications showing how to
     interact with PowerShell from IronRuby.
  4. Clock - a simple Silverlight sample
  5. Photoviewer - do AJAX programming with IronRuby (ARAX =P)
  6. REPL - Interactive console in the browser


-- Some more interesting changes:

  - Improved DLR Interop: adds support for GetMember/SetMember with method_missing,
    Binary/Unary operators, and indexers.
  - Handling of CLR protected and private methods and properties
  - Reimplemented File.expand_path such that it does not use System.IO.Path.
    This allows us to get better compatibility with MRI. The motivating reason was
    that RSpec does File.expand_path("filename:linenumber")
  - Improves the implementation of singleton method dispatch.
    These changes improve running time of specs significantly (2x)
  - Renames Method, UnboundMethod#overloads (plural) to
    Method, UnboundMethod#overload (singular).
    The old name is still available for now and throws an exception.
  - Implements adaptively compiled rules
  - Improves performance of Array#- from quadratic algorithm to linear.
  - Improves implementation of RubyArray


== Bugs closed

Here are all 37 bugs closed since the last release (2009-05-19). You can see
more information about each one here:
http://ironruby.codeplex.com/WorkItem/List.aspx

  1521  Access is allowed to internal fields
  1502  alias_method fails for :do
  821   File.expand_path does not support a line number after filename
  1509  Proc.to_s should include line number where the block was declared
  1501  WinForms broken
  1400  $? is not always Process::Status
  1345  load_assembly(<partial_name>) should work
  1344  System.Action.new does not work
  1306  Cannot call CLR constructor of builtin type
  1184  public(:foo) does not work correctly for mixed-in methods
  1085  Cannot call new on subtypes of builtin classes whose "new" method has optional arguments
  1060  visibility of send :define_method
  917   Passing a Ruby array to a .NET method that expects an IEnumerable derivative fails with GetEnumerator call
  783   Assert in SetMethodBasesNoLock when calling #== on Ruby class inheriting from CLR class which overrides Equals
  761   Wrong behavior when calling redefined methods on object instances
  1470  Can't call the BigIntegerOverload of a method with a DefaultProtocol Attribute on the BigInteger attribute
  1426  The located assembly's manifest definition does not match the assembly reference. (ctp dev10 beta1)
  1441  Error with cyrillyc text in Sharepoint
  1352  Test Defects
  814   Allocator underfined for <type> (TypeError)
  572   Error when running Cucumber examples with IronRuby
  718   IronRuby ignores RUBYLIB environment variable
  727   to_proc not working
  1351  redist-libs should have rubygems-1.3.1
  466   ''.split(//, -1) returns [""] instead of []
  940   Can't inherit from abstract classes
  1028  Missing conversion from Duration to Fixnum (ActiveSupport)?
  374   irails Foo: undefined method for OpenSLL::Random.random_bytes
  459   throw FileNotFoundException => rescue Errno.NoEntryError
  499   Pathname#cleanpath messes up the pathname
  467   "igem install rails" fails
  375   "ir script\server" causes a YAML parser error
  461   Generic type conversion from Fixnum to Integer
  674   autoload does not use File::SEPARATOR
  1021  Time class instance
  578   yield fails in eval'd code
  605   Array#hash should properly handle recursive arrays


== Enjoy!

Please test out IronRuby 0.6 and let us know if you have any issues. We hope you enjoy this release!

  -- The IronRuby team


More information about the Ironruby-core mailing list