RubyConf: Sydney and Rubinius

Posted by Nick Sieger Fri, 20 Oct 2006 19:07:00 GMT

Update: Evan has posted code and has a page set up for the project.

Evan Phoenix (nee Webb), of Seattle.rb, is presenting on Sydney and Rubinius, an experiment in improving the ruby interpreter. Sydney has died, and Rubinius has risen from its ashes, appropriately.

Why

  • Why would you write a new Ruby interpreter? It’s fun, it’s a good challenge.
  • What’s wrong with the existing interpreter -- are you hating on Matz? Of course not.

Today’s Ruby interpreter is like a big dump truck -- sometimes a little slow, but it works for us. YARV is like the red, shiny fire truck. Both big and complex. Rubinius, by comparison, is like a dune buggy. Fast, light, but you’re going to get sand in your eyes if you drive it a lot.

The project, admittedly, is naive.

  • Simple architecture and implementation.
  • As little background magic as possible
  • No opaque C backend
  • Leverage axiom of simple == powerful
  • Less magic means more introspection
    • More control for the developer
    • Richer introspection: Backtrace, MethodTable objects

What was Sydney?

  • Giant patch to 1.8.2 that included reentrancy and thread-safety
  • Turned out to be a major PITA
  • CRuby uses a large number of C globals, references to which had to be tracked and fixed

Transition to Rubinius

  • Ruby borrowed a lot from Smalltalk, so why not try an implementation based on the same concepts?
  • Prototype A ported the blue-book implementation to Ruby
  • It worked and validated the basic concept and approach
  • Prototype B took ideas from A but implemented a bytecode interpreter and compiler. Used RubyInline to access raw memory operations.
  • At this time the goal emerged to have a translator which could take a prototype and bootstrap itself into C code.
  • Prototype S was a manual translation of Prototype B into C code to make the implementation quicker.
  • Prototype W was created to translate parts of Prototype B so that there is a maintainable core in Ruby code itself.

Questions

Q. Since you were starting over, could you use a platform-independent library to ease the process, such as APR? Yes -- currently using String and PointerArray from glib.

Q. How is performance? Too early to tell -- I hope to know by the end of the conference. Prototype S became runnable and usable on the plane here.

Q. Can you clarify the goal? To create a Ruby interpreter in Ruby that can translate itself out into a C interpreter.

Q. Have you figured out how to link in external libraries in a platform independent way? No. My hope is that the decision will be made to write a common framework for translating to system calls, e.g., SWT.

Q. Have you looked at PyPy? (similar project for Python) Yes, and it’s f-in complicated. It worries me actually.

Q. Could you have it generate backend code in another language/platform (Java bytecode, CLR)? Yes, I certainly hope so, otherwise I’m wasting my time.

Q. How will you add native thread support in a cross-platform way? I hope I won’t have to, by leveraging external tools.

Q. If you’re building a Ruby-to-C translator, why write a Ruby interpreter at all? If I didn’t, what would I translate? You still need some core engine to translate. Would it be a subset of Ruby? Yes.

Q. Looks very similar to Squeak, have you looked at Squeak code and talked to Squeak people? Looked at code a lot, I’ve really stolen all of their ideas. I haven’t talked to the folks yet because I’m afraid they might laugh at me.

Resulting Works

  • SydneyParser: Used parser from Sydney and stole ParseTree’s algorithm for generating a sexp that represents the Ruby code.
  • SegfaultProtection: detects a segfault in an extension, saves the Ruby interpreter, and raises a memory fault exception instead.

The Nitty Gritty (Red Pill)

  • All components separated by APIs for swappability
  • Garbage collector: baker two-space copy collector, and a train GC
  • Bytecode interpreter: small set of instructions driven by tests and need, so there are no extraneous operations
  • Compiler: written completely in Ruby, using ParseTree and SexpProcessor. Intended to compile itself to be used as a base compiler for Prototype S.

Future

  • Other backends -- Java, Smalltalk

More questions

Q. Worried about fragmentation? Yes, but I really want to make it as compatible as possible with the current interpreter.

Q. Rubinius bytecode compatibile with YARV? No, but I hope to be able to write a bridge to YARV in Rubinius.

Q. Have you looked at Valgrind for the C code? Yes, I have. Good possibility for future direction.

Q. Can you demo some code? They’re incredibly boring. “Look I got a MethodTable object, I asked for one.”

Posted in  | Tags , ,  | 5 comments | no trackbacks

RubyConf 2006 Begins

Posted by Nick Sieger Fri, 20 Oct 2006 19:04:00 GMT

The RubyConf room is filling up this morning. I’ll be doing my best to live-blog the conference here so stay tuned!

DSCF4909.JPG

DSCF4908.JPG

Posted in  | Tags , ,  | no comments | no trackbacks

Auto RSpec

Posted by Nick Sieger Wed, 13 Sep 2006 20:35:00 GMT

Update: (2 months later) If you’re reading this, you’re probably interested in my Rails plugin for this instead.

Hot off the presses, after a few hours of hacking and tweaking, may I present Auto+RSpec, otherwise known as The Mashup of RSpec on Rails and autotest. This is not an official release of any sort, but “may work for you.” It’s not a clean hack, as it exposes some areas for autotest to grow if the maintainers decide to open it up to alternatives to Test::Unit. After spending a little time looking at the autotest code, I think it would be nice to allow hooks for autotest plugins to define project conventions (i.e., @exceptions and the #tests_for_file method) as well as a result parsing API.

For now, if you’re an RSpec on Rails user, you can try this out as follows:

  • Install ZenTest if you haven’t already: sudo gem install ZenTest.
  • Download rspec_autotest.rb and put in your vendor/plugins/rspec/lib directory (you did say you’re using RSpec on Rails didn’t you?)
  • Download rspec_autotest.rake and put in your lib/tasks directory
  • Start autotest with rake by typing rake spec:autotest
  • Note: if you’re using RSpec 0.6, you might have better success with the files located here.

Next steps for this will be to work out whether this code should live in RSpec on Rails or autotest, or some combination of those.

Now, spec’ers, be off in search of that Red/Green/Refactor rhythm of which sage agilists speak!

Bonus tip: add the following code to your .autotest file to run spec with rcov:

  Autotest.add_hook :initialize do |at|
    # run spec with rcov
    if at.respond_to? :spec_command
      at.spec_command = %{rcov --exclude "lib/spec/.*" -Ilib --rails "/usr/lib/ruby/gems/1.8/gems/rspec-0.6.0/bin/spec" -- --diff}
    end
  end

Posted in , ,  | Tags , , ,  | 8 comments | no trackbacks

QOTD

Posted by Nick Sieger Tue, 06 Jun 2006 15:03:00 GMT

Spotted the following thread on ruby-talk:

Pat Maddox: I hate when languages put a condom on my code.
Gennady Bystritsky: What does it make your code, then? ;-)
Mat Schaffer: Pregnant!

Posted in ,  | Tags  | no comments | no trackbacks

.irbrc on Windows

Posted by Nick Sieger Tue, 30 May 2006 16:57:00 GMT

Having trouble getting IRB to use a .irbrc file on Windows? The following seems to work:

  1. Create the .irbrc file in your %USERPROFILE% directory.
  2. Create an environment variable in the System Properties->Advanced Tab->Environment Variables area called HOME and set it to %USERPROFILE%.

An alternate approach is to create an environment variable called IRBRC and set it to the full path of the .irbrc file.

Perhaps IRB should be updated to look in %USERPROFILE% on Windows?

Plug: for handy .irbrc contents refer to this previous post.

Posted in  | Tags  | 1 comment | no trackbacks

Rails is simpler than Office

Posted by Nick Sieger Fri, 26 May 2006 03:32:00 GMT

Before my big blog drought at the beginning of the year, I had an entry queued up talking about some success I’d experienced with Rails. A lot in the Rails world has progressed since then, but I still think the story is worth documenting. Also, the code to generate a PDF of mailing labels may be useful to somebody out there.

I’ve had some Rails success lately building a home-use mailing list manager/rolodex application. There are plenty of ways that such a list could be maintained without resorting to a full web application framework such as Rails, but what the heck! The mailing list started life as an MS Access database; after my work computer was re-imaged I no longer had “access to Access” so it had a temporary layover in an Excel spreadsheet. Within the past couple of months I had moved it to a MySQL database as a way to nurture my fledgling Rails efforts.

Ok, so nothing real special so far, except that in order to print mailing labels (one of the primary reasons for keeping such a list) I’d have to export the names to a .csv file and do a mail merge with Word. Until the most recent mailing.

On a Saturday night I had the brainstorm to use Austin Ziegler’s PDF::Writer library to create a printable PDF directly from the Rails app, thus skipping the need to go through the mail merge rigamarole. Only a couple of hours of effort later, I had my mother-in-law’s Christmas mailing list printed out! Anyone who has ever done a mail merge with Word knows that clicking a single link to create the printable versions of the mailing labels is a huge improvement in usability. And finally, no MS bits were harmed in the production of this mailing!

My starting point in building the code to generate PDFs was this page in the Rails wiki. I decided to use the method that describes installing an “rpdf” template handler. Nowadays, you may as well use Josh Charles’ Rails PDF plugin, but for posterity I’ve packaged up my effort as a simple plugin as well (install into an existing Rails application with ./script/plugin install http://svn.caldersphere.net/svn/main/plugins/pdfrender).

With the plugin in place, all that’s necessary is a controller method to set up the data for the view, and the view code itself. The controller is as straightforward as you’d expect:

class AddressController < ApplicationController
  # ...

  def pdf
    @addresses = Address.find(:all, :order => 'last_name, first_name')
    render :layout => false
  end
end

The view code is a little more hairy but with a little thought the dimensioning and layout code could easily be DRY’d out.

FONT = "Times-Roman"
FONT_SIZE = 12

COLS = 3
LABELS_PER_PAGE = 30
LABELS_PER_COL = 10

# margins: .5in top & bottom, 0.19 in left and right
# table column widths: 2.63in | 0.13in | 2.63in | 0.13in | 2.63in
# table rows: 1in height

MARG_X = pdf.in2pts 0.19
MARG_Y = pdf.in2pts 0.5

CELL_Y = pdf.in2pts 1
CELL_X = pdf.in2pts 2.63

COL_PAD_X = pdf.in2pts 0.19

COL1_X = MARG_X 
COL2_X = COL1_X + CELL_X + COL_PAD_X
COL3_X = COL2_X + CELL_X + COL_PAD_X

CELL_PAD_X = pdf.in2pts 0.13
CELL_PAD_Y = pdf.in2pts 0.25
CELL_LINE_Y = FONT_SIZE + 2

def cell_x(col)
  [COL1_X, COL2_X, COL3_X][col] + CELL_PAD_X
end

def cell_y(row, line)
  MARG_Y + ((LABELS_PER_COL - row) * CELL_Y) - CELL_PAD_Y - (line * CELL_LINE_Y)
end

def add_label(row, col, addr, pdf)
  if addr
    pdf.add_text_wrap(cell_x(col), cell_y(row, 0), CELL_X, addr.name, FONT_SIZE)
    pdf.add_text_wrap(cell_x(col), cell_y(row, 1), CELL_X, addr.address, FONT_SIZE)
    pdf.add_text_wrap(cell_x(col), cell_y(row, 2), CELL_X, "#{addr.city}, #{addr.state} #{addr.zip}", FONT_SIZE)
  end
end

pdf.select_font(FONT)

pages = @addresses.length / LABELS_PER_PAGE
pages += 1 if (@addresses.length % LABELS_PER_PAGE) > 0

0.upto(pages - 1) do |page|
  start = page * LABELS_PER_PAGE
  address_page = @addresses[start..start+LABELS_PER_PAGE]

  0.upto(LABELS_PER_COL - 1) do |row|
    add_label(row, 0, address_page[row*COLS], pdf)
    add_label(row, 1, address_page[row*COLS+1], pdf)
    add_label(row, 2, address_page[row*COLS+2], pdf)
  end

  pdf.new_page unless page + 1 == pages
end

And that’s it! Avery labels in Rails!

Posted in ,  | Tags , ,  | no comments | no trackbacks

JRuby on Rails and ActiveRecord on JDBC

Posted by Nick Sieger Mon, 15 May 2006 03:12:00 GMT

Tom and Charlie have just experienced what can only be described as a watershed moment in the grand scheme of dynamic languages on the JVM. The Rails experience may soon be visiting a Java application server near you! Even though JRuby will be in perpetual catch-up mode with C Ruby, Tom and Charlie and the rest of the JRuby contributors have shown incredible perseverance in tracking the Ruby language despite the lack of any formal specification. Maybe Rails will never be mainstream, but the possibilities just got a whole lot more interesting. I agree with Obie that this could be a game-changer.

Now, a few comments about the ActiveRecord JDBC adapter. This code can still be considered alpha quality at best. It’s awesome that Tom and Charlie will be able to demo a top-to-bottom, working Rails app on JRuby, but don’t jump to conclusions yet that this will be anything like a write-once, deploy-to-any-database kind of experience. But you didn’t think it would, did you? We all learned that about Java a long time ago, right?

You can check out the code here. At the moment, I’ve only tried it with MySQL. Most of the problems with it come from the lossy mapping from ActiveRecord’s abstraction of the database to JDBC’s. (Although I suspect as more JDBC drivers are tried that there will eventually be compatibility issues with different implementations of the JDBC spec.)

Probably the thorniest issue is the one of type conversion. ActiveRecord has a fairly simple notion of types: :string, :text, :integer, :float, :datetime etc. Compare this to JDBC’s. What a mess! Right now there are arrays of procs for each AR type that try to guess the best JDBC type to use. This will certainly need improvement to become a more robust solution.

Probably the most promising approach may be to create a patch that refactors much of the AR adapters’ type conversion methods into separate modules that could be included into instances of the JDBC adapter depending on the underlying database. Then the JDBC types wouldn’t be needed at all -- the existing AR database metadata could be reused. Presumably this would require some petitioning of the Rails core team to accept the changes even though the changes don’t buy AR itself any additional flexibility.

If you have a chance to try out the code or can think of any additional tricks that would help the ActiveRecord JDBC implementation along, let me know!

Tags , , ,  | no comments | no trackbacks

Older posts: 1 ... 3 4 5