Category Archives: ruby

Presenting Rack at Montreal Against Rails

I’ll be presenting Rack this Tuesday at the first Montreal Against Rails (the non-Rails meeting).

I’ll show how to use Rack and then I’d like to try something new (and probably crazy-stupid). Building a web framework with Rack is so easy, I’ll be doing pair programming with anyone from the audience to create our own custom framework live during the presentation (in 30 min). We’ll start with the code posted on RefactorMyCode as the application code, we’ll implement the framework code during the presentation. So submit your ideas there before the event.

To take part in first and biggest Montreal Ruby pair programming session and watch the other cool presentations, make sure to RSVP.

4 Comments

Filed under conference, montreal, ruby

Ruby on V8

V8Google Chrome looks cool, ok… But what is even cooler for me is V8, the super JavaScript VM.

JavaScript is a dynamic language, just like Ruby.
You can add stuff to objects at runtime, like Ruby.
It’s object oriented, like Ruby.
It has a GC, like Ruby.

What if we could run Ruby on V8?

Well, it’s a lot easier that you think. If you remember a while ago, someone released HotRuby. It runs YARV bytecode in the browser.

So I plugged the 2 together just to see what would happened => rbv8.

It’s fast (sometimes)

I used the script on HotRuby site to benchmark.

sum = ""
50000.times{ |e| sum += e.to_s }

And just for fun, I also wrote it in C:

int main (int argc, char const *argv[])
{
  char *str = malloc(sizeof(char) * 238890);
  char buf[5];
  size_t i;

  for (i = 0; i < 50000; ++i) {
    sprintf(buf, "%d", i);
    strcat(str, buf);
  }
  return 0;
}

Update: seems like my C code was the suck, thx for some commenters for pointing it out. Here's a better version which is way faster (thx to Hongli Lai):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char const *argv[])
{
  char *str = malloc(sizeof(char) * 238890);
  char buf[5];
  size_t i;
  unsigned long last = 0;

  for (i = 0; i < 50000; ++i) {
    int len = sprintf(buf, "%d", i);
    memcpy(str + last, buf, len);
    last += len;
  }
  return 0;
}

Also here's a Javascript version:

var sum = "";
for (var i = 0; i < 50000; i++) {
  sum += i.toString();
};

C:              0.017 sec
Javascript:     0.063 sec
rbv8:           0.987 sec
Firefox 3:      3.636 sec
Safari 3:       4.368 sec
Opera 9.50:     4.679 sec
Ruby 1.8.6:     9.565 sec
Ruby 1.9.0:     9.669 sec
Rubinius 0.8.0: 15.576 sec
JRuby 1.1 b1:   42.691 sec

OMG OMG OMG OMG!!! 10 times faster then YARV and faster then C!

Update: Ok... if your replace += w/ <<, YARV beats the Javascript version running on V8, thx to Nobu Nakada for noting this

But wait, don't go tell your friends yet! It seems, that all the other benchmarks I tried were slower (sometimes by a very wide margin).

But I think this means that the potential is there, it just need to be exploited properly.

Also another fun thing to note, is that if you change Fixnum#times to while i < 50000 in the Ruby code, it becomes a lot slower. No idea why.

Me wants to try

If you wanna try rbv8:
You need Ruby 1.9 installed as `ruby19` and make sure you meet V8 Pre-requisites: http://code.google.com/apis/v8/build.html#pre_reqs.

git clone git://github.com/macournoyer/rbv8.git
cd rbv8
rake
bin/rbv8 sample/concat.rb

Note that this is just a prototype. I just hacked this in an hour to benchmark it. See the README file for what needs to be done next.

63 Comments

Filed under ruby

You’re just in a giant Object.class_eval block

>> Object.methods.size
=> 85
>> def i_is_in_ur_Object; "kthxbai" end
=> nil
>> Object.methods.size
=> 86
>> String.new.i_is_in_ur_Object
=> "kthxbai"

Careful what you put in there!

2 Comments

Filed under ruby

The Class and Module love story

In Ruby, Class is a Module which, like any object, has a class.

>> Class.superclass
=> Module
>> Module.class
=> Class

But the crazy thing is, it's the complete opposite in the implementation.
(Excerpt from ruby.h)

typedef struct {
    VALUE super;
    struct st_table *iv_tbl;
} rb_classext_t;

struct RClass {
    struct RBasic basic;
    rb_classext_t *ptr;
    struct st_table *m_tbl;
    struct st_table *iv_index_tbl;
};
#define RCLASS_IV_TBL(c) (RCLASS(c)->ptr->iv_tbl)
#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
#define RCLASS_SUPER(c) (RCLASS(c)->ptr->super)
#define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl)
#define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m)
#define RMODULE_M_TBL(m) RCLASS_M_TBL(m)
#define RMODULE_SUPER(m) RCLASS_SUPER(m)

We see it gets the instance variable table (RMODULE_IV_TBL) just like it's a class. Modules are stored in RClass structs.

I know. I'm totally confused too.

1 Comment

Filed under ruby

You See the Invisible Block?

require "rubygems";require "thin";require"markaby"; class Invisible
HTTP_METHODS =[:get,:post,:head,:put,:delete];attr_reader :request,
:response, :params; def initialize(&block); @actions =[]; @with=[];
@layouts={};@views={};@helpers=Module.new;@app=self; instance_eval(
&block) if block end; def action(method, route, &block); @actions<<
[method.to_s, build_route(@with*"/"+route),block] end;HTTP_METHODS.
each{|m|class_eval "def #{m}(r='/',&b); action('#{m}', r, &b) end"}
def with(route); @with.push(route);yield;@with.pop end; def render(
*args,&block);options=args.last.is_a?(Hash)?args.pop: {};@response.
status=options.delete(:status)||200;layout=@layouts[options.delete(
:layout)||:default];assigns={:request=>request,:response=>response,
:params=>params,:session=>session};content=args.last.is_a?(String)?
args.last : Markaby::Builder.new(assigns,@helpers, &(block||@views[
args.last] )).to_s ; content = Markaby::Builder.new( assigns.merge(
:content => content), @helpers, &layout).to_s if layout; @response.
headers.merge!(options);@response.body=content end;def layout(name=
:default, &block); @layouts[name]=block end; def view(name,&block);
@views[name]=block end; def helpers(&block);@helpers.instance_eval(
&block ) ; instance_eval(&block)  end;  def session;  @request.env[
"rack.session"]end; def use(middleware, *args);@app=middleware.new(
@app,*args) end; def run(*args);Thin::Server.start(@app, *args) end
def call(env); @request = Rack::Request.new(env); @response =Rack::
Response.new; @params = @request.params; if action = recognize(env[
"PATH_INFO"], @params["_method"] ||env["REQUEST_METHOD"]); @params.
merge!(@path_params);action.last.call;@response.finish; else; [404,
{}, "Not found"]; end; end; def self.run(*args,&block);new(&block).
run(*args) end; def self.app;@app||=self.new end;def self.call(env)
@app.call(env) end; private; def build_route(route);pattern= route.
split("/").inject('\/*') { |r, s| r << (s[0] == ?: ? '(\w+)' : s) +
'\/*' } + '\/*';[/^#{pattern}$/i,route.scan(/\:(\w+)/).flatten] end
def recognize(url, method); method =method.to_s.downcase; @actions.
detect do |m,(pattern,keys),_| method==m&&@path_params=match_route(
pattern,keys,url)end;end;def match_route(pattern,keys,url);matches,
params=(url.match(pattern)||return)[1..-1],{};keys.each_with_index{
|key,i| params[key]=matches[i]};params;end;end; def method_missing(
method, *args,  &block);  ; if Invisible.app .respond_to?(method) ;
Invisible.app. send( method, *args, &block);  else; super; end; end

No!

6 Comments

Filed under ruby

RubyFringe == Awesome

RubyFringeNick Sieger though us about Jazz, Giles Bowkett got a standing ovation, Zed Shaw sang “Matz can’t patch” and “Don’t fuck Chad’s community”, Geoffrey Grosenbach was wearing a kilt, Hampton Catlin presented Haml for Javascript, Damien Katz made me cry and Tom Preston-Werner is my new hero.

Better reviews

2 Comments

Filed under conference, ruby

MeshU slides and code

Code is at http://github.com/macournoyer/meshu

5 Comments

Filed under conference, ruby, thin