Interviewed on Alt.NET Podcast

I had the pleasure of being interviewed along side Aaron Junod on the Alt.NET Podcast to discuss IronRubyaltdotnetmike

Michael  Moore was a wonderful host and did an amazing job editing the conversation down to something tight.  It was an exciting opportunity to talk about IronRuby specifically and Ruby in general.  Hopefully it will help spark even more interest in it.

On a personal note, I’m interested in any feedback you might have, from the technical to the stylistic. It was my first time doing a podcast, so it’s definitely a learning experience for me.

IronRuby vs JRuby vs MRI. Performance Mini-Shootout.

One of the things I went over in my eRubyCon talk was the relative performance of IronRuby compared to both JRuby  (which I consider to be a cousin of sorts to IronRuby) and MRI. I did this by running the same tests that Antonio Cangiano ran in December.

There were a few test results that really stood out.  The lists test was by far the worst for IR, where it was 56 times as slow as MRI and 3 times as slow as JRuby.  But this wasn’t the only sore spot, there were other places that show room for improvement.  Namely, vm1_blocks in which IronRuby was almost 9 times as slow as MRI.  Also so_exception where IronRuby brought up the tail by being 10 times as slow as MRI.

The nitty gritty is that IronRuby is about twice as slow as MRI with JRuby being slightly faster, overall.  As the below graph illustrates:

image 

There are a few high points in this test though.  Number one, is that IronRuby ran the majority of the tests.  There were only four failures out of forty, for a 90% success rate.  For comparison JRuby had 95% success rate. Number two, there were actually a few tests in which IronRuby beat JRuby and MRI.  No small feat for such a young implementation.

I think this mini-shootout illustrates that there is a lot of room for improvement for IronRuby.  However, a little perspective goes a long way.  JRuby was announced in 2001, IronRuby was announced last April.  The JRuby team has had 7 years to get to where they are today, whereas IronRuby has only had almost a year and a half! As the DLR improves IronRuby will receive those performance gains for free, and as compatibility becomes more stable the core team can focus on performance as well. The raw data can be downloaded here.

eRubyCon Recap

 

What a fantastic conference this was two weeks ago.  A great lineup of speakers, and fantastic after event gatherings.  And I missed the first day!  Josh Holmes has a great series of posts detailing the event, so I won’t repeat the play by play here.  But I can say that I will definitely be making the trip to Columbus for eRubyCon 2009. 

This was the first conference I have gone to where I actually presented.  My talk was originally geared more towards .NET developers interested in Ruby, thinking that there would be more Java and .NET enterprise folks there then it turned out.  After I arrived, as I listened to the attendees, I realized the audience was primarily people already doing Ruby.  I also noticed a certain level of distrust around Microsoft in general, even though the event was hosted in their office!  As I was going to be speaking on IronRuby, a Microsoft project, this concerned me a bit.  So I ended up putting in an opening section about some of, what I believe to be, the positive changes at Microsoft over the last half-decade or so.  I highlighted efforts like CodePlex and Port25.  A number of people seemed to copy down the Port25 address, so I hope I helped open some eyes in this case.  I also went over the current state of IronRuby, and compared it’s performance to JRuby.  I then asked who did .NET work in their day to day jobs and must have had about 5 people raise their hands.  Then I went through a short demo of opening up and changing a standard WinForms app using IronRuby. It seemed to go well, I’ve gotten positive feedback on it and a number of suggestions for improvement.

I can’t thank Joe O’Brien enough for the opportunity or confidence in me he showed by allowing me to speak.  The slides and demo used for my presentation are here.

Speaking at eRubyCon

Just a heads up to my faithful readership, I’ll be speaking about IronRuby at erubycon this August.  It’ll be my first  public speaking engagement at a technical conference, and my first real public speaking since High School (in-house presentations don’t count in my book).  I’m quite nervous but it’s a topic I’m passionate about so I’m really excited as well.  The title of the talk is "Because Iron is Battleship Gray: IronRuby In The Real World", and it won’t mention Silverlight or Rails.  Ruby is so much more than glitz and glam, and I think that tends to get lost in the hype.  She’s a sexy lady, but she’s got brains too!

Hope to see you there!

IronRuby QuickStart ReDuex

Back in January I did a post on getting started with IronRuby.  That post was based on Rev. 75 of the SVN tree.  As of  today (June 9th) the SVN tree is up to Rev. 113.  Obviously with things like RailsConf and TechEd driving a lot of the core teams work, a number of things have changed since January.  This post will basically be a rehash of the previous one, but updated for all the new quirks that have been introduced.

Getting The Source

As before, I recommend using TortoiseSVN to grab the source. Downloading will take a bit, after the 3.5MB of source is downloaded you should end up with a directory structure like the following:

image

Compiling IronRuby

Inside of the trunk directory you will find the IronRuby.sln file, double-clicking it will open the solution (note that the solution file is now in VS2008 format instead of the previous VS2005 format).  You may get a warning, you can select “Load the Project Normally” and uncheck “Ask me this for all projects in the solution.”

Once the solution is loaded, keep the solution on the “Debug” configuration.  Do NOT select “ExternalDebug” (you’ll get broken references if you do):

image

Next we will manually remove the “SIGNED” compilation symbol from all the projects, as of Rev. 113 you have to manually remove it from the IronRuby.Libraries, Microsoft.Scripting, and Microsoft.Scripting.Core (be sure not to delete the DLR symbol) projects.

image

Once those are removed you can build the source!

Running That Which You Have Wrought

Where has previously our compilation would output into a bin\Debug folder, the resulting files are now found in \trunk\build\debug, which should look like this:

image

Due to a conflict with rubinius, the rbx executable is now ir.

As before you can just run ir.exe and enter the wonderful world of ruby, or you can continue on to see how we roll in the .NET world.

Speaking C# With A Ruby Accent

The initial steps are basically the same as before, start a new C# console project and add references to Microsoft.Scripting.dll, Microsoft.Scripting.Core.dll, IronRuby.dll, and IronRuby.Libraries.dll.

We are going to create a simple console app that shows passing variables into and out of a ruby script.

The below program should be a good example:

 


using System;

using Ruby;

using Microsoft.Scripting.Hosting;
namespace IronRubyConsoleApp

{

    class Program

    {

        static void Main(string[] args)

        {
ScriptRuntime irruntime = IronRuby.CreateRuntime();

            ScriptEngine ir = IronRuby.GetEngine(irruntime);

            ScriptScope scope = ir.CreateScope();

            ScriptSource script = ir.CreateScriptSourceFromString("puts \"Hello, #{name}!\"\ninput + 2");

            scope.SetVariable("name", ".NET");

            scope.SetVariable("input", 2);

            int x = script.Execute<int>(scope);

            Console.WriteLine(string.Format("The Result was {0}", x));

            Console.ReadLine();

        }

    }

}

You can see a clear hierarchy here:

We have a Runtime

That has an Engine

That has a Scope

That has a Source

We create a runtime, and we get our IronRuby engine into the runtime, we create a scope and load a script using that engine.  Set a couple of variables in the scope and then execute the script within the scope that we have set the variables in.

Hopefully this is enough to get you started, you should probably check out the other CreateScriptSource methods that the engine contains, you have a veritable cornucopia of options:

image

Ruby with a .NET Accent

Another of the popular activities with IronRuby, if not the most popular, is going to be interfacing with both the .NET framework and other .NET code.  The below example shows us interfacing with System.Windows.Forms and making a simple GUI app.

 

require 'mscorlib' require ' System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' require 'System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' Swf=System::Windows::Forms Sd=System::Drawing class RubyForm <Swf::Form def add_button text, location button = Swf::Button.new button.Text = text button.Location = location self.Controls.Add button button end def initialize self.Text = "RubyForm" @rbutton = add_button "Click Me!",  Sd::Point.new(150, 150) @rbutton2 = add_button "Click Me!", Sd::Point.new(150, 100) @rbutton.Click {|sender, e| Swf::MessageBox.show 'Hello World!'} @rbutton2.Click {|sender, e| Swf::MessageBox.show 'Hello, .NET!'} end end rf = RubyForm.new rf.ShowDialog

As you can see above, when requiring items from the GAC we must include the Fully Qualified Name, including version and StrongNameToken if applicable. The above code inherits from System.Windows.Forms.Form and adds a helper class for adding buttons and wires up a couple of event handlers.  Again this is just a simple example to get you started.

Summary

In this post we downloaded the IronRuby source, compiled it, and worked with IronRuby both from C# and by running a ruby script against .NET objects.  Hopefully this gets you going a little faster and onto the fun stuff quicker!

Links

IronRuby Homepage

IronRuby RubyForge Project

Ruby Language Homepage

John Lam’s homepage

Announcing Zliby — All Zlib, Pure Ruby

A few weeks ago Dr. Wayne Kelly posted on the IronRuby mailing list the set of libraries and methods that had to be implemented in order to perform a rubygems setup.  This is an important first step towards full rails support.  I volunteered to take on the task of porting the Zlib library.  I thought, why not implement it in pure Ruby, that way there would be no external dependencies.  It would have to be API compatible with the ruby-core Zlib implementation, so it could be used in place of the natively compiled libraries. 

After about a week of hacking on it, I’ve decided to make the initial public release of Zliby.  Right now the only thing that’s implemented is Zlib::Inflate’s inflate functionality and Zlib::GzipReader’s read functionality.  Eventually all of the ruby-core Zlib API will be implemented, and I hope to add other compression support going forward.  Before you ask, yes it’s slower then a native implementation, but it’s portable, and has not be optimized for speed in any way yet.  Also, since it’s being developed for use in IronRuby, there are a few constructs that I can’t currently use (Array#pack for instance) though I will be able to in the future. Comments, feedback, and suggestions welcome!

Links:

Zliby Project at RubyForge

Ruby-Core Zlib API Docs

Zlib Homepage

The Grass May Not Be Greener Yet, But The Soil Is More Fertile

 

The founder of the Ruby.NET project announced yesterday that he is leaving active development of that project and moving over to fully supporting the IronRuby effort.  Based on everything I’ve heard about Dr. Kelly and Ruby.NET, this is fantastic news.  Hopefully this will spurn even more activity on the IronRuby project.  Some of the important quotes from his post are:

"I’ve come to the conclusion that the DLR is clearly here to stay – it’s becoming an even more important part of the Microsoft platform."

"I now believe that IronRuby is more likely to succeed as a production quality implementation of Ruby on the .NET platform."

That’s quite an endorsement.  I have a feeling the next year or so will be the year of the DLR, we’ll begin seeing it’s API solidify with more and more languages being implemented on it.

That all said, IronRuby still has one major roadblock.  That is the perception of it’s corporate sponsor.  I had another dev tell me this today:

"Well, ironruby is mostly being  developed inside Microsoft, so almost everyone that talks about  ironruby dev day-to-day does so on  MS-internal mailing lists. "

John Lam say it ain’t so…

The ironruby-core mailing list is fairly active, and the MS-PL is OSI approved.  Yet, Microsoft has to actively be promoting these things, otherwise the outside perception will not change and IronRuby will be the less for it I fear.

What IronRuby needs more than anything right now is a large group of outside contributors, so come on down and get coding, testing, and documenting!

(Semi) Practical IronRuby

So you followed the quick start I posted earlier, and you’re thinking “So what? What good is IronRuby and DLR to me?” The DLR provides an extensible, powerful way to add scripting capabilities to your application. Let’s take a look at how IronRuby and C# can really interact. We’ll create an “IronLogo” application, consisting of a windows form we can draw on utilizing a simple DSL implemented in Ruby. Commands can be loaded via a file or through a console.

Our bulk of our application is actually going to be in C#, the details aren’t important, but let’s take a quick look at the class definition.

LogoWindow Class Diagram

I’ve hidden a lot of the cruft, but the important things here are the TurtlePoint property that holds a Point object of the turtle’s current location, and the MoveTurtle method. What we’re going to want to do is take the current turtle’s location and move some offset. Of course we don’t have to write some complicated command parser, so we’re going to use IronRuby and the DLR to handle all the heavy lifting. Let’s take a quick look at the application’s Main method:

 

1 static void Main()

2 {

3 Application.EnableVisualStyles();

4 Application.SetCompatibleTextRenderingDefault(false);

5

6 LogoWindow logowin = new LogoWindow();

7

8 IScriptEngine ruby = IronRuby.GetEngine(IronRuby.CreateRuntime());

9

10 Dictionary<SymbolId, object> globalvars = IronRuby.GetExecutionContext(ruby.Runtime).GlobalVariables;

11 globalvars[SymbolTable.StringToId("logowin")] = logowin;

12

13 IScriptScope IronLogoScope = ruby.Runtime.CreateScope();

14

15 ruby.Execute(IronLogoScope, ruby.CreateScriptSourceFromString(Properties.Resources.IronLogoRuby, SourceCodeKind.File));

16

17 logowin.PassScopeAndEngine(IronLogoScope, ruby);

18

19 logowin.ShowDialog();

20

21 }

You can see a lot of the same stuff happening here as you did in the quick start, though there are some subtle differences. First, if you look at line 11 you can see that we’re actually assigning a global variable to the reference to our windows form. That’s right, our Ruby code will be able to access our Window form object directly, all though the magic of the DLR! Also, on line 13, I create a scope using the Runtime property of the engine, this is important as this will create a scope that has references to the right engine, context, and so forth. We learned from the quick start about the IScriptEngine.Execute command, but what are we running on line 15? Why, it’s an embedded text file that contains our ruby code that implements the DSL! Would you believe it’s only 15 lines? See for yourself:

 

1 def up(steps=1)

2 $logowin.MoveTurtle($logowin.get_TurtlePoint.X, $logowin.get_TurtlePoint.Y – steps)

3 end

4

5 def dn(steps=1)

6 $logowin.MoveTurtle($logowin.get_TurtlePoint.X, $logowin.get_TurtlePoint.Y + steps)

7 end

8

9 def rt(steps=1)

10 $logowin.MoveTurtle($logowin.get_TurtlePoint.X + steps, $logowin.get_TurtlePoint.Y)

11 end

12

13 def lt(steps=1)

14 $logowin.MoveTurtle($logowin.get_TurtlePoint.X – steps, $logowin.get_TurtlePoint.Y)

15 end

Here you can see we’re defining four methods, they take a parameter called “steps” (which defaults to one) and then accesses the main form object through the global variable and calls the MoveTurtle method, as well as accessing the TurtlePoint method (remember that properties are really just syntactic sugar/metadata for method pairs, so we’re actually calling the get method directly).

The other bit of trickery in the Main method is on line 17, this is where I pass both my engine and the scope that the above Ruby script was executed in, to the LogoWindow form.

Let’s take a look at what we can do in the LogoWindow form since we have a reference to our scripting engine and scope. Let’s say we want to be able to load a script of our DSL and have the application run it. Let’s create a text file that looks like so:

up 10
lt 10
dn 10
rt 10
dn 10

As you can see, what it really consists of is just calls of the methods we defined above, let’s see how we load such a file in the application:

 

147 private void applyIronLogoScriptToolStripMenuItem_Click(object sender, EventArgs e)

148 {

149 OpenFileDialog ofd = new OpenFileDialog();

150 ofd.Filter = “IronLogo Files (*.ilogo)|*.ilogo|All Files (*.*)|*.*”;

151 ofd.Title = “Apply An IronLogo File…”;

152 if (ofd.ShowDialog() == DialogResult.OK)

153 {

154 this.scriptengine.Execute(this.scriptscope, this.scriptengine.CreateScriptSourceFromFile(ofd.FileName));

155

156 }

157 }

Thats…. it really. See how simple that is? Loading the file results in our methods being executed and our Turtle being moved:

Logo having been run

Yay for the power of the DLR! What if we want to be more interactive though? We actually want to open a console and let people run the commands interactively. No fear, with the DLR that’s easy as well! Since this is a Windows application first, we do need to import a couple of external Windows API funcitons, namely AllocConsole and FreeConsole. Once we do that we can then create a console window and tell the DLR to open a Ruby console in it. There’s some Threading trickery going on that I’ll spare you from, but the method for actually opening a console looks like this:

 

1 private void RunConsole()

2 {

3 if (AllocConsole())

4 {

5 this.consoleopen = true;

6 Ruby.Hosting.RubyCommandLine rubycommandline = new RubyCommandLine(new Ruby.Runtime.RubyContext(ScriptDomainManager.CurrentManager));

7 Microsoft.Scripting.Shell.SuperConsole superconsole = new Microsoft.Scripting.Shell.SuperConsole(rubycommandline, this.scriptengine, true);

8 rubycommandline.Run(this.scriptengine, superconsole, new Ruby.Hosting.RubyConsoleOptions());

9

10 }

11 }

11 lines of code…and the real heavy lifting is only done in three of them. Wow. All that work, done for us. What you end up with after that is something that looks like this:

Interactive Logo session

Summary

There you have it, a simple implementation of LOGO as a DSL in Ruby, running on the DLR, interoperating with our C# code. I’ve uploaded the above application to CodePlex for your enjoyment.

IronLogo CodePlex Project

IronRuby Quick Start

IronRuby is Microsoft’s, with collaboration by the public, implementation of Ruby on their Ruby LogoDynamic Language Runtime. There’s another version of Ruby for .NET called, ironically, Ruby.NET that runs directly on the CLR. This post won’t be about that though, if you want to see a comparison, look here for a fairly good write up.

Downloading IronRuby from the SVN server and compiling in VS2005 was actually pretty painless. But after that I couldn’t find any, working, examples of getting an Ruby script running in the DLR. A big part of this is due to IronRuby still being officially “pre-Alpha” with the Scripting Host API in flux. Regardless, I hope this will be enough to get some people trying to use the latest SVN (rev. 75) up and running.

Building The Source

Download the latest revision from RubyForge using SVN, if you need a client I HIGHLY recommend TortiseSVN. Once you’re done downloading the source, you should be able to open the IronRuby.sln file in Visual Studio. We only need to make one change, and that’s to the Microsoft Scripting Project. Bring up the project properties and go to the Build tab:

signed.png

We have to remove the Conditional compilation symbol of “SIGNED”, otherwise the Scripting host will be looking for Microsoft signed copies of the IronRuby library, which we don’t have. After that go ahead and build the solution (cross your fingers if it makes you feel better).

When all is done you should end up with a bin\Debug folder in your SVN root that looks something like this:

debugdir.png

You can go ahead and start rbx from right there and begin playing with Ruby if you’d like. But if that’s all we wanted to do we would have just downloaded Ruby, right? This is IronRuby, let’s do it the .NET Way!


Hosting IronRuby in C#

Create a new Console Application solution in Visual Studio, say RubyExample. Add References to the Microsoft.Scripting.dll, IronRuby.dll, and IronRuby.Libraries.dll files.

Let’s begin with the most basic, a simple Hello World:
using System;using Ruby;using Ruby.Runtime;using Microsoft.Scripting;using Microsoft.Scripting.Hosting;namespace RubyExample{ static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { IScriptEnvironment scriptenvironment = ScriptEnvironment.GetEnvironment(); IScriptEngine rubyengine = scriptenvironment.GetEngine(“ruby”); scriptenvironment.ExecuteSourceUnit(rubyengine.CreateScriptSourceFromString(“puts’Hello World! \nPress Any Key To Continue..’”) ); Console.ReadKey(); } }
Let’s take a quick look at what we’re doing here. We’re setting up a ScriptEnvironment, this is where our Dynamic languages are going to live and play. Then out of that environment we’re asking for someone who understands Ruby. After that we’re just saying, hey ScriptEnvironment, run what the Ruby guy says.

So that’s pretty nifty, we could also tell the RubyEngine to CreateScriptSourceFromFile and move whatever code we want out of a string constant. Which is probably a good idea for anything beyond a line a two. But what if we actually want to talk back and forth? Let’s move on to the next example.

Accessing Global Variables

The easiest way to pass data between IronRuby and C# is via Global Variables. See below for an example.

As you can see I switched it up a bit and inited the Environment and Engine a bit differently, one way is more general, the other specific to IronRuby. The power of the ScriptingHost API is you can on the fly decide what language you want to use. But if you know you’re only going to be doing IronRuby, you can use the above method.

The real trick is in the second line, we get a reference to the GlobalVariables of the current IronRuby execution context. Once we have that we can start assigning global variables values and retrieving them back.

Summary

Hopefully this is enough to get you started. As I continue to delve into IronRuby, I will be sure to post what I find here, so keep an eye out!

IronRuby Homepage
IronRuby RubyForge Project
Ruby Language Homepage
DLR Hosting Spec
John Lam’s homepage