« November 2005 | Main | January 2006 »

December 2005

December 23, 2005

Ben and us

A big thanks to everyone who sent along their best wishes to us!

Carolyn made it out of the hospital much quicker (24 hours) than the last time around. She’s also feeling much stronger than she did after Matthew’s birth.

Fortunately, since Ben’s birthday is so close to Christmas, we’ve got a house full of family to help us out as we adjust to having a toddler, a baby, a dog (and four other adults!) under the same roof.

Update: Here’s a photo of Ben that I made this afternoon:

December 21, 2005

Introducing Benjamin Peter Lam

Say hello to our new boy Ben! He was born Wednesday December 21, 2005 at 9:02AM.

Here are a few more photos from his flickr photostream.

December 19, 2005

Dreamhost for $22 USD first year

I have a confession to make: I’m addicted to Red Flag Deals. Thanks to their forums, I’ve gotten more than my fair share of good deals. One deal that I thought I’d pass along here is Dreamhost hosting package for only $22 USD for the first year on a new registration.

This is an insanely good deal. With that you get a free year’s registration on a domain name of your choice, 4.8GB disk space, and 120GB / month transfer. You can create shell accounts, host an unlimited number of MySQL databases, and of course run Rails web sites as well.

Here’s a link to the original deal page on RedFlagDeals so that the props can go out to the appropriate folks.

December 17, 2005

CLR object lifetime

My Ruby CLR bridge works by creating, on the fly, small CIL shims that invoke the appropriate method(s) on a CLR object. Today I want to talk about how I manage the lifetimes of those CIL shims.

When you execute some code like a = ArrayList.new for the first time, I construct a new ArrayList Ruby class object on the fly. When you execute a method on a class instance such as a.Sort, I construct a CIL shim that knows how to invoke the Sort method on the ArrayList object. That CIL shim is bound to the Ruby class object via a call to rb_define_method.

The CIL shim is created using the DynamicMethod API in CLR 2.0. After I finish defining the body of the dynamic method using my RbDynamicMethod API, I construct a delegate object that represents that method. These delegate objects are eligible for garbage collection, which means that I need to keep a reference to them. Now, when I said that the CIL shim is bound to the Ruby class object, Ruby only knows about the function pointer to the delegate object that represents the CIL shim. That function pointer is only a weak reference to the delegate, which means that it cannot keep the delegate object from being collected by the CLR GC.

To work around this problem, I’ve added a List<Delegate> object to the Ruby class object. Its job is to hold onto references to all of the dynamically created CIL shim delegate objects for that class. When the Ruby class object is garbage collected by Ruby’s GC, my automagical object reference cleanup code will Free the GCHandle object that I use to keep a reference to the List<Delegate> object.

I actually had a far more complicated and convoluted mechanism for dealing with this problem in my initial implementation of the bridge. I’m much happier with the simplicity of this approach in V2.

December 16, 2005

MindBinders

I was looking for a source of Moleskine notebooks in Toronto (Indigo is one place to get them, but they were sold out), and I stumbled across this photo via Technorati:

When I was in grad school, I spent a lot of time creating index cards; I had several thousand by the time I was done. These look like a really nice way to replicate some of that goodness in a nice, compact form factor.

I love the depth of field on his Sony Cybershot camera (shot at F/2).

How meta can you go?

I just figured out what Ruby was doing, because I forgot just how “meta” my programming was. Consider this code frag:


def const_missing(symbol)
  alias_const_missing(symbol) unless symbol == :ArrayList

  obj = create_clr_class_object
  # remember that the code below is in a string
  obj.class_eval %{
    def initialize(*params)
      create_safe_ruby_instance_method(
        self.class, 'initialize') do
        include     'System.Collections'
        declare     "#{symbol}", :obj
        ...

Look at the last line of code and the declare statement. Notice how I’m referencing the symbol variable that is the input parameter to the const_missing method declaration on the first line? I have to escape that reference as a string to access that variable. Why? Because that code is embedded in a string (that’s what the funny %{ means: it’s a begin string quotation symbol).

Now this has interesting implications for other string manipulation functions that are inside of the string that is passed to obj.class_eval. For example consider this snippet of code.


sigs          = get_constructor_signatures("#{symbol}")
switch_labels = (1..sigs.length).collect { |i| ("l" + i.to_s).to_sym }

I really wanted to write the string expression as:

"l#{i}".to_sym

But this cannot work since it would try and find an i variable defined in the enclosing method. So I wound up writing it in the somewhat more verbose way that I did to make it work. I wound up scratching my head about this behavior for quite a while before I realized that, doh! the code was executing inside of a string.

That’s how powerful Ruby’s metaprogramming facilities are: oftentimes you forget that you’re really programming at a meta level of abstraction instead of at the “concrete” level.

December 15, 2005

Refactoring CIL

I had a great day today. I had one of those a-ha experiences where you get to benefit from an earlier decision in ways that you did not expect. I started down the path of generating constructor shims using RbDynamicMethod. I completed my first spike yesterday, when I successfully constructed ArrayList objects using RbDynamicMethod.

Today, I wanted to make a slightly more generic constructor shim that would let me call both a default and a single argument constructor: ArrayList() and ArrayList(Int32). While I was writing this code, I began to feel some CIL pain (it is, after all assembly language). So I did what came naturally: I began to refactor the code.

This reminds me of the talk that I saw this year at OOPSLA where Ward Cunningham was refactoring assembly language using IntelliJ. In my case, I refactored CIL using emacs :) Here’s the end result:


def initialize(*params)
  create_ruby_instance_method(self.class, 'initialize') do
    include     'System.Collections'
    declare     "#{symbol}", :obj
    ldarg_0
    switch      [:zero_param, :one_param]
    br_s        :end_switch
    label       :zero_param
    newobj      '#{symbol}()'
    stloc_s     :obj
    br_s        :end_switch
    label       :one_param
    ld_rb_param 0, 'Int32'
    newobj      '#{symbol}(Int32)'
    stloc_s     :obj
    label       :end_switch
    ret_objref  :obj
  end
  initialize(*params)
end

While this is mostly CIL, it also contains a number of macros and fun Ruby string stuff. The macros that I used are: ld_rb_param, ret_objref. As it turns out, these will be very common code fragments that will be used throughout the bridge. Writing those macros was even easier. Here’s a sample:


module RbDynamicMethodHelpers
  def ld_self
    ldarg_2
  end

  def ld_rb_param(index, type)
    ldarg_1
    case index
    when 1:
      ldc_i4_4
      add
    when 2:
      ldc_i4_8
      add
    else
      ldc_i4    index << 2
      add
    end
    ldind_i4
    call      "static Marshal::To#{type}(VALUE)" 
  end

  def ret_objref(local_variable_name)
    ld_self
    ldloc_s  local_variable_name
    call     'static Marshal::AssignToClassInstance(VALUE, Object)'
    ret
  end
end

It turned out it was a good thing that I left the method declarations as strings, since I could do some simple string manipulation to inject implement syntactic sugar methods such as ld_rb_param (which is actually a very efficient CIL implementation that is optimized for the common cases).

Oh yeah, how much extra code did I have to add to RbDynamicMethod to enable macros? I changed:

object.extend RbDynamicMethod

to:

object.extend RbDynamicMethod, RbDynamicMethodHelpers

Did I mention how much I love Ruby? :)

December 14, 2005

Hello RubyClr

I spent most of yesterday and today hacking out the first spike of the Ruby rewrite of my original Ruby to CLR bridge. I wound up adding some additional code to RbDynamicMethod to support some scenarios that I didn’t envision (nothing like having a ‘customer’ to reveal deficiencies in an API!). I also spent a lot of time learning about how objects are constructed in Ruby. Here’s a very simplified explanation of Ruby’s object model; for a complete description, see Chapter 24 of Dave Thomas’ excellent Programming Ruby.



In Ruby, objects are instances of classes. However, classes are also objects in Ruby, which means that a class is an instance of a class called Class. Let’s consider the following code fragment:


a = ArrayList.new
puts a.Count

In the first line, we’ve created an instance of class ArrayList and assigned it to the variable a. Next, we invoke the Count instance method of the ArrayList object. So far so good, right?

Next let’s see how Ruby invokes instance methods. Every Ruby object contains a reference to its class object. This is stored in an internal field called klass. When we invoke the Count method on the ArrayList object, Ruby follows the klass reference to find the ArrayList class object. It searches its method table, finds the Count method and invokes it.

In my bridge, I delay binding to a method on a CLR object until it is called. When it is called, I build a small piece of CIL code using RbDynamicMethod to call the method and marshal data back to the caller. I can delay binding to the method using the method_missing instance method of the object. In the case of the call to the Count method, you could imagine a piece of code that looks like:


alias alias_method_missing method_missing

def method_missing(name, *params)
  alias_method_missing(name, *params) unless name == :Count

  create_ruby_instance_method(self.class, 'Count') do
    include  'System.Collections'
    ldarg_2
    call     'static Marshal::ToClrObject(VALUE)'
    call     'ArrayList::get_Count()'
    call     'static Marshal::ToRubyNumber(Int32)'
    ret
  end
  self.Count
end

This is a hard-coded example that generates a shim for the Count method. The shim invokes the get_Count method to retrieve the value of the Count property of the ArrayList object. It marshals the return value (an Int32) back to the caller using the Marshal::ToRubyNumber() helper method in the RbDynamicMethod library.

Where things get interesting is the first two lines of CIL code in the shim. Here, I reach into the Ruby object and pull out the actual ArrayList object reference that is stored in a secret field of the Ruby object. This secret field is completely inaccessible to Ruby code. Once I have the object reference, I can freely invoke the get_Count instance method using the CIL call instruction.

Notice that I’m defining an instance method called Count on the ArrayList class object. At the end of the method_missing method, I invoke the Count method that I just defined. However, all subsequent calls to the Count instance method will go directly to the CIL code that I just wrote (which of course will have been compiled into x86 code as well). This means that we will have excellent performance since we completely avoid having to use the Reflection APIs in the CLR.

You’re probably wondering how the ArrayList object reference got stored in the secret field? I’ll talk about that in tomorrow’s installment of the story when we look at how objects get created in Ruby (and it’s nowhere near as simple as it looks!).

December 13, 2005

DemoCamp

I went to DemoCamp tonight and I saw a bunch of cool demos put on by folks working on startups here in Toronto.

  • The BubbleShare folks had a really cool demo of an upcoming feature of their photo sharing service. They’ve implemented the core interface of iPhoto using AJAX (you know the one: dragging a slider that dynamically resizes the thumbnails). You have to see it to believe it. Apparently this feature goes live on their site next week sometime.
  • If you’re into ego surfing, you should definitely check out Eh List. Chris Nolan’s done a really good job of aggregating a bunch of services to show you just where you rank (or don’t) in the blogosphere.
  • I’m continually amazed by how Randy Charles Morin is able to generate revenue from his various ventures. Tonight he demonstrated RMail which is a service that emails you RSS feeds. Randy monetizes this by including links within the blog entries that point back to his custom search engine.
  • Sutha Kamal of Ambient Vector demonstrated his social collaborative search engine that improves the quality of mobile search based on its analysis of your preferences and your peer group’s preferences. This is a really powerful idea that greatly improves the quality of recommendations, since you can think of search results as recommendations. This ties back into the idea that providing search context is a good thing.

It was also cool to hang out with Reg Braithwaite again. Tonight I got a great idea about building a Firefox extension based on his ideas about context-based recommendations. I so want to do something cool in this space.

Third drop of RbDynamicMethod

Here’s another drop of RbDynamicMethod. New to this release is a custom implementation of Type.GetMethod that correctly finds overloaded generic methods. The .NET implementation of this method does not support resolving generic methods, so I wound up rolling my own. If you’re interested in its implementation you should check out FindGenericMethodTemplate in the sources.

This is what using RbDynamicMethod to call a generic method looks like:


create_ruby_module_function(RbDynamicMethod, 'call_generic_min_method') do
  include   'RbDynamicMethodTests'
  ldc_i4_3
  ldc_i4_2
  call      'static GenericMethodTests::Min<Int32>(Int32, Int32)'
  call      'static Marshal::ToRubyNumber(Int32)'
  ret
end
assert_equal 2, call_generic_min_method

This should be the last drop of this library for the next little while since I think it’s good enough to begin building my new Ruby to CLR bridge on top of it.

Photos

  • www.flickr.com
    This is a Flickr badge showing public photos from John Lam. Make your own badge here.

Recent Comments

Recent Posts

May 2008

Sun Mon Tue Wed Thu Fri Sat
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Blog powered by TypePad