You are here: Blogsphere Longtail

Rails BlogSphere

BlogSphere

Keep up to date with your favourite Rails bloggers in context.

Read more about how it works


My120_135 RE: RE: Связь многие ко многим в рамках одной таблицы

by Ruslan Voloshin | 1 day ago | Read more

> может стоит ипользовать плагин acct_as_tree ?? Именно он раньше и использовался, но там нельзя сделать множество родительских узлов... > поможет has_and_belongs_to_many или has_many :through Это понятно, но это подходит для связывания двух разных таблиц отношением N:M, а мне надо для одной таблицы...

Andrewburke OfficeTime: Great Time-Tracking App for OS X

by Andrew Burke | 1 day ago | Read more

I've built several of my own time tracking applications over the years, but I'm now using a fantastic commercial product: OfficeTime.

Why I like Ruby #1: alias_method

by Leonardo Borges | 1 day ago | Read more

So you found yourself in the need to override a method but still count on it’s old behaviour? No problem! Override it with your new code, call super and…. Uh oh!! Suddenly this turned into a problem… Let me give some more context. I was testing Ferret (and the acts_as_ferret plugin) in a project to provide full [...]

Facebook's Iphone App.

by Abraham Alaka | 1 day ago | Read more

Facebbok's Iphone Application.

Reviews of BeatThat.com

by John Norman | 1 day ago | Read more

A couple of fresh reviews of DigitalAdvisor’s new product BeatThat.com: CNet Xconomy

Por2006-me-150 Apparence des écrans "scaffold" générés

by Richard Piacentini | 1 day ago | Read more

Bonjour à toutes et à tous,

Je suis assez nouveau sur RoR, alors si ma question vous paraît hallucinante, remettez-la dans son contexte ...

Note préliminaire : je développe depuis 15 ans, et je trouve Ruby et RoR franchement intéressants !

Mon problème : lors de la génération des "scaffold", on obtient entre autres des pages au format ".html.erb" toutes faites (c'est le but). Il n'y a aucun effort de la part du générateur concernant la présentation dans les pages générées, ce qui me paraît tout à fait normal.

Ma question : comment faire en sorte que les pages générées soient plus en rapport avec le look général de mon application ? Actuellement, je suis obligé de ré-écrire quasiment intégralement les pages générées pour qu'elles ait un aspect acceptable du point de vue utilisateur (quand je dis ré-écrire, je veux dire : modifier de très nombreuses lignes - une majorité, en fait -).

dura lex sed lex, ...

by Igor Gajsin | 1 day ago | Read more

... ну или сказочный долбоебизм. Но первая версия вероятнее

Viximo in Forbes!

by Dennis Eusebio | 1 day ago | Read more

Congrats to Vixmio for its recent write up in Forbes. “For Web publishers, Viximo offers a soup-to-nuts virtual gifting service that provides digital content from its community of independent developers, billing via Paypal, a revenue-share program with artists and their sites, and analytical tools that track what goods sell well. The aim, says Frasca, is to [...]

MAGLAB on Energy 97.7FM

by Kamel Al-Asmar | 1 day ago | Read more

A week ago Jumana (our administrative assistant at Akhtaboot) transferred a phone call for me. This call was from a guy who speaks English and I wasn’t able to hear his voice clearly. But I figured out that he needs a sponsorship from Akhtaboot. I’m not going to tell you the whole story but at [...]

F8 08 Summary

by Abraham Alaka | 1 day ago | Read more

On the 23rd of July 08, facebook held their annual showcase with the developer community. In the past its often been used to make major announcements that affected the platform. This year’s event was held at the San Francisco Design Center 635 8th Street, San Francisco, CA 94301. Below is a summary.

D Installing gem on Leopard

by Akhil Bansal | 1 day ago | Read more

May be you guys have noticed that when you try to install a new gem on your machine it says some thing like “Updating meta data for 500 gems” and display one dot per gem. These dots moves very slowly and stops in some time. I faced this situation many times and found a solution [...]

Karl If It's Not Nailed Down, Steal It

by Rick Bradley | 1 day ago | Read more

If It's Not Nailed Down, Steal It: (posted by cardioid)

Karl Hello Functor: pattern based method dispatch in ruby | Lambda @ Copa

by Rick Bradley | 1 day ago | Read more

Hello Functor: pattern based method dispatch in ruby | Lambda @ Copa: (posted by cardioid)

20080420-n8pc7aby9dw1fdr661t4cc5xek Apps Daddy Likes...

by Mario Aquino | 1 day ago | Read more

I have been asked more than once by friends and associates about what applications I use or recommend for OSX. I am sure this is not an uncommon occurrence for folks who enjoy sharing the positive experiences they have had on the Apple platform. This morning I remembered a site I came across many months ago that allows people to track the applications they use (and I believe it also notifies

Me Plugin: localized_dates

by Clemens Kofler | 1 day ago | Read more

After nearly two years of Rails development it’s more than time that I released my first (official) plugin. So here it goes.

If you’ve watched Rails on Lighthouse and GitHub lately, you’ve probably noticed that I’ve proposed quite a number of patches, especially regarding the new Rails i18n plugin (which by the way got me the 2nd place in the July 2008 Rails Hackfest – congrats to Tarmo Tnav at this point).

However, the date and time API got only partial i18n/l10n coverage – date and time formatting wasn’t included – which is where my new plugin, localized_dates, might come in handy.

The quickest way to get going is to simply install the plugin from its GitHub repository:

./script/plugin install git://github.com/clemens/localized_dates.git

As part of its installation, this will copy two locale files (en-US.rb and de-AT.rb) to your config/locales folder. en-US is basically there to keep the current functionality and date definitions in place. de-AT serves as a demo on how you can write your own locale.

If you need any further help, I suggest reading the README over at GitHub.

If you like it, consider rating it at its Agile Webdevelopment plugin page.

-)” 3:04 am - Comment

by Logan Koester | 1 day ago | Read more

-)” 3:04 am - Comment

My120_135 RE: Ограничение кол-ва символов в поле

by Ruslan Voloshin | 1 day ago | Read more

А не проще купить книжку за 100 гр. и прочитать стандартные главы об испозьзовании валидаторов ?

Testing MarsEdit

by Papon Yongpisanpop | 1 day ago | Read more

Using MarsEdit to Writing a blog on my Mac. Testing Upload media:

Karl Stealth USB CapsLocker | macetech.com

by Rick Bradley | 1 day ago | Read more

Stealth USB CapsLocker | macetech.com: (posted by cardioid)

Opera Web Standards Curriculum

by Pedro Sousa | 1 day ago | Read more

Opera published the Web Standards Curriculum, a series of articles which were released in association with the Yahoo! Developer Network, the goal is to: teach you standards-based web development, including HTML, CSS, design principles and background theory, and JavaScript basics.  I find the initiative very positive, there’s already 23 articles and 30 more are coming until the end of [...]

Nigel Jump Fail

by Nigel Ramsay | 1 day ago | Read more

Jump Fail:
Shared by Nigel
Ouch

Submitted by Alex M

Pixelhandler128 Found an old rant on Web Desig…

by Bill Heaton | 1 day ago | Read more

Found an old rant on Web Design/Standards/Senantics from back in 2001… http://rant.cc/DgR … We’ve come a long way

My120_135 RE: Опять ошибка

by Ruslan Voloshin | 1 day ago | Read more

На любой rake консоль выдает это: C:\lovdbyless>rake lovdbyless:getting_started (in C:/lovdbyless) rake aborted! undefined method `remove_task' for #<rake::application:0x2cdebd0> C:/lovdbyless/rakefile:10 (See full trace by running task with --trace) C:\lovdbyless>rake (in C:/lovdbyless) rake aborted! undefined method `remove_task' for #<rake::application:0x2ce04d0> C:/lovdbyless/rakefile:10 (See full trace by running task with --trace)

My120_135 RE: Ограничение кол-ва символов в поле

by Ruslan Voloshin | 1 day ago | Read more

http://api.rubyonrails.com/classes/ActiveRecord/Validations/ClassMethods.html#M001049

Profile Seth Godin: Is architect a verb?

by Nate Klaiber | 1 day ago | Read more

In light of yesterday's discussion on the title of a designer, Seth Godin has an interesting post today that shows a move from designer to architect.

Architecture, for me anyway, involves intention, game theory, systems thinking and relentless testing and improvement. Fine with me if you want to call it design, just don't forget to do it. (via)

My120_135 Ограничение кол-ва символов в поле

by Ruslan Voloshin | 1 day ago | Read more

Есть ли стандартные методы для реализации субжа? Т.е. я например создал форму, и в ней input или textarea, и хочу чтобы было ограничение в этим полях на максимальный ввод символов (скажем, 100).

Janu_bw Comics in my Pants

by Jack Nutting | 1 day ago | Read more

Some time ago, perhaps inspired by the daily comics-watching antics of The Comics Curmudgeon and Garfield Minus Garfield, I started a new comics-oriented blog. The premise of this blog is simple: Most of these so-called "comics" or "funnies" are anything but funny; Many of them can be enhanced (I'll stop short of saying "improved" or "made funnier") by replacing the last text bubble with a single stupid punchline. The results can be humorous, absurd, ribald, or scatological. See for yourself at Comics In My Pants. I've kept it going for a month now, dredging through the daily strips looking for spots where my punchline of choice seems to fit, at least syntactically. Enjoy!

Me Qt::JRuby v0.2.1

by Nicolas Mérouze | 1 day ago | Read more

Je n’ai pas parlé de la version 0.2 le mois dernier, mais voici la version 0.2.1 qui marque l’arrivée d’un package permettant de développer son application sans avoir à installer quoi que ce soit (à part Java).

Je l’ai nommé Qt::JRuby Complete. Il suffit de le télécharger, le décompresser et d’éditer le fichier main.rb qui contient déjà une petite application. Ensuite pour lancer l’application, il suffit de taper la commande suivante :

java -jar ./jars/qtjruby-0.2.1.jar main.rb

L’archive est un peu lourde puisqu’il y a beaucoup de composants à l’intérieur (JRuby Complete + Qt Jambi pour Windows, Linux et Mac OS X). Dans les prochaines semaines/mois je ferais une application qui permettra de packager une application directement avec les composants que l’on (comme le fait Shoes depuis peu) et quelques petites autres choses pour faciliter le déploiement.

Je vais maintenant pouvoir me concentrer sur l’enrichissement du DSL et de la documentation. Bref encore plein de travail pour ce projet.

Dernière petite chose, il y a maintenant 3 dépôts différents : un pour le Core, un pour le DSL et un pour le reste.

Nigel Bible: 19 translations on your iPhone

by Nigel Ramsay | 1 day ago | Read more

Bible: 19 translations on your iPhone:

Filed under: App Store

When I was going through a minor existential crisis a few years ago, I read the Bible from cover to cover. The copy I had was the rattiest, oldest paperback version…

Mh77 Bara bra länkar

by Magnus Hjelm | 1 day ago | Read more

Ända sedan LaterThis lanserades har jag funderat på ett sätt att visa de mest populära länkarna som sparas. Ungefär som Delicious gör. Men eftersom det bara sparas ett par hundra länkar om dagen så blir det för lite data för att titta på hur ofta en länk blir sparad och använda det som underlag för [...]

Tom-eric jRuby updates

by Tom-Eric Gerritsen | 1 day ago | Read more

Charles Nutter heeft een blogpost geschreven met daarin een samenvatting van wat er de laatste tijd allemaal met jRuby gebeurt.

Stories built around core mechanics

by Tom Armitage | 1 day ago | Read more

or: “what games story can learn from Stephen Moffat” So Braid finally came out. I was in shock when I saw the release date; wonderful as it was, I was never sure I was going to get a chance to play it. I shouldn’t have worried. It’s out, I’ve got it, and so far, it’s been [...]

D When Ultrasphinx is used with polymorphic associations…

by Akhil Bansal | 1 day ago | Read more

Lets first consider simple has_many and belongs_to associations as: class Article < ActiveRecord::Base has_many :comments end class Comment < ActiveRecord::Base belongs_to :article end Now if you wish to index the title of associated article with comment for searching, you just need to add ” is_indexed :fields => :body, :include => [{ :association_name => ‘article’, :field => ‘title’, :as=> [...]

The Rubyist - una rivista su Ruby

by Matteo Alessani | 1 day ago | Read more

The Rubyist - per rubisti da rubisti - è una rivista per sviluppatori ruby pubblicata da Jeremy McAnally . Costa circa 8$ in versione cartacea e 3$ in pdf su Lulu. Ci sono interessanti interviste a Rein Henrichs e Hampton Catlin, articoli di Jamie van Dyke, Ben Scofield e Yehuda Katz niente di veramente approfondito [...]

Jayfields Be Your Start-Up

by Jay Fields | 1 day ago | Read more

It's impossible not to ponder striking it rich at a start up, but there's another alternative if you're looking to make some good money -- build your brand.

In January of 2005 I created a blog. I truly can't remember why I created it, but I do remember that I was making $60,000 a year. Then in February I joined ThoughtWorks and my blog became part of blogs.thoughtworks.com. I had instant readership, but not a lot to say.

Two and a half years and a lot of blog posts later I turned down an offer that was $174,000 a year. This wasn't $174,000 a year because the work sucks. It was a good job, but I wasn't ready to leave ThoughtWorks. It's been a year since then, and I know it was the right decision.

Now, I didn't make millions, but tripling your salary in two and a half years is still quite nice. There's no question that my brand was responsible for my ever increasing salary requirements. In fact, when I was interviewing two of the three interviewers started their interviews with "I read your material, you've got exactly what we need here. So why don't you ask me the questions instead". My brand had already gotten me the job.

Building a brand isn't as hard as you might think. There's really only 3 things you need to focus on.
  • Writing
  • Presenting
  • Contributing
If you do all three of those, you'll have a brand in no time.

But, before you do those three things, you'll need to read two books that will give you the proper guidance.note: both books are required reading whether you are building a brand or not.

Once you have the requisite reading covered it's time to make your mark.

Writing
Writing isn't hard. Writing well is hard, but you're a programmer, so you needn't worry about that. No one expects you to be a good writer, they're happy if you are, but they're forgiving if you're not. Don't use your poor writing skills as an excuse not to write.

Don't know what to write about? The answers are all around you. Anything you do that's interesting, there's 100 people searching Google for how to do it. Any question a colleague asks you, someone is searching Google for the same answer. Anything that's valuable to you... yes, someone is googling for it.

Take the time to write the answer in a blog entry. People will remember if your blog consistently shows up in their Google searches.

Create a blog. Blogger is free and definitely good enough. Here's a few thoughts on blogging.
  • Don't roll your own, you don't need the maintenance headache.
  • Name it something simple, but be sure to include your name. Disco Stu's Ramblings is funny, but you want to build your brand, not Disco Stu's.
  • Buy your name as a domain and put the blog as a directory (I didn't do this correctly). If I had it to do over my blog would be at http://jayfields.com/blog. This is important for Google Page Rank. If you do it the way I did you'll have different page rank for your homepage and your blog. Not the end of the world, but not ideal.
  • Keep it focused. If you want to write about programming and gambling, create two different blogs. Also, avoid "Sorry I haven't written in awhile" posts. People aren't dying for your next post. They're subscribed because they want technical content, not stories about how you've been busy remodeling your home.
  • Keep blog posts short if possible. Anything over 1500 words is article material. If you can't find somewhere to publish the article, then your blog is fine. But, remember that people don't like reading long blog entries (like this one)
At first, stick to writing blog entries. They're not too hard and don't require as much polish. They also let you start building a catalog of material. Once you have enough similar posts, start rolling them into articles to post on InfoQ or other similar sites. Eventually, if you write enough articles, you can roll them up into a book. It will take years, but so does writing a book from scratch and doing it this way allows you to get constant feedback without any deadline pressure.

Presenting
Of the 3 things you need to do, I think presenting is the hardest to get going with. You aren't likely to pick up a speaking spot at a good conference if no one has heard of you. So, you'll need to rely on your writing to build your brand a bit, then you can present on the topics that you write about. Alternatively, if you create some open source software that generates buzz you can also pick up a few speaking engagements. Getting started is the hardest part, but once you give a few good talks you'll quickly be turning things down because you just can't fit it in your schedule.

If you're serious about speaking I also highly recommend SpeakEasy. I spent two and a half miserable days at SpeakEasy learning how bad I was at public speaking. The experience was priceless. I can't say enough good things about what I learned in those two and a half days.

Contributing
The last suggestion is the easiest. Contribute some open source software. There's so many ways to contribute.
  • Pick an existing project that you use and create a patch for an outstanding bug.
  • Extract something interesting from your codebase and release it as open source. You don't need millions of adopters. If you create something valuable to 20 people you'll gain 20 people advocating your brand.
  • Be the documentation guy. Almost all open source software suffers from poor documentation. Make it your speciality. You'll quickly make friends if you do the work others don't feel like doing.
  • Join a mailing list for your favorite open source project and be active. Be the guy that's always willing to help the recent adopters.
I'm sure there's other ways as well. It doesn't matter how you contribute, just get out and start contributing.

Oh, and don't submit patches as disco_stus_brother. You're name is your brand, use it.

My120_135 RE: RE: chm справочник для rails 2.0.2

by Ruslan Voloshin | 1 day ago | Read more

Ок!! пройдись по этой ссылкой http://webfile.ru/2143737

093cb09b6 WTF???!!! => Andreas Zaron und Verena Rendtorff: “Cliff...

by Björn Wolf | 1 day ago | Read more



WTF???!!! => Andreas Zaron und Verena Rendtorff: “Cliff & Rexonah” Das ganz groߟe Glück (im Zug nach Osnabrück) (via Tobias Mann)

My120_135 RE: chm справочник для rails 2.0.2

by Ruslan Voloshin | 1 day ago | Read more

Не скачивается, мот ктонить перезальет?

08 am - Comment

by Logan Koester | 1 day ago | Read more

08 am - Comment

My120_135 RE: RE: Связь многие ко многим в рамках одной таблицы

by Ruslan Voloshin | 1 day ago | Read more

acts_as_tree не катит: каждый элемент дерева может иметь только одного родителя. поможет has_and_belongs_to_many или has_many :through

RAWK!

by Mando Escamilla | 1 day ago | Read more

RAWK!

OMG! Misfits of science! http://tinyurl.com/6syz98

by Mando Escamilla | 1 day ago | Read more

OMG! Misfits of science! http://tinyurl.com/6syz98

Also, for the curious: use of eval() in openSIMS flash components is officially awesome and not at...

by Mando Escamilla | 1 day ago | Read more

Also, for the curious: use of eval() in openSIMS flash components is officially awesome and not at all gratuitous :)

Ryan-orange-large Gun Stances

by Ryan L. Cross | 1 day ago | Read more

Gun Stances

Portrait Autotools?

by Jan Varwig | 1 day ago | Read more

Why didn’t ANYONE notice how FUCKED UP this is: These factors led to the development of Automake. automake, like autoconf, is a program run by a developer. The developer writes files named Makefile.am; these use a simpler syntax than ordinary Makefiles. automake reads the Makefile.am files and produces Makefile.in files. The idea is that [...]

100_5106-785540 Track Your Stolen Laptop For Free

by Johannes Fahrenkrug | 1 day ago | Read more

Just a quick note: I just read about Adeona, a project from the University of Washington that lets you track a stolen laptop for free (of course you have to install it before you have someone steal it ;-)). The Mac OS version can even take snapshots of the thief with the iSight camera, like this one:


I just installed it and I hope that I'll never need to use it. Having some hooded freak messing with my MacBook Pro is just a too terrible thought to bear.

Bookmark for "The Art Of Braid"

by Matt Tarbit | 1 day ago | Read more

The Art Of Braid. On the evolution of David Hellman's dreamy, painterly art stylings for Braid, released this week on XBLA.

'Twas Brillig

by Charles Nutter | 1 day ago | Read more

It's been a long time since I posted last. I figured it was time to get at least a basic update out to folks.

JRuby's been clicking along really well. Perhaps a little too well. Our bug tracker counts 476 open bugs and climbing, even while we're trying to periodically sweep through them. We're slipping behind, but there's a silver lining: every other bug is filed by someone new. So there's happiness in slavery.

Since my last post, a lot has happened. We pushed out JRuby 1.1.3 around the middle of July, which boasted a whole bunch of new awesome. Vladimir Sizikov posted a really nice rundown of the changes.

My favorite item has to be the improved interpreter performance, which now is clearly faster than MRI's interpreter. So whether you're running interpreted or compiled in JRuby, you should be getting pretty solid straight-line performance.

There were also dozens upon dozens of compatibility fixes, an upgrade to RubyGems 1.2, and lots of other miscellaneous changes to make JRuby a little friendlier and easier to use. It's nice to be able to focus on that kind of stuff now that compatibility is mostly a done deal (ok, high 90th percentile...but pretty darn good).

So then...what's on the slate for the next JRuby release?

Making the Leap?

We had originally been talking about JRuby 1.1.3 being the last planned release in the 1.1 line. It had reached a really solid level of stability and performance, people were putting it in production for all sorts of apps, and we were generally very happy with it. "Last planned release" doesn't mean we wouldn't continue to do maintenance releases as needed...it just means we weren't going to do day-to-day development against the 1.1 line.

The primary reason for this is a number of large-scale projects we'd been putting off. For example, the "Java Integration" (JI) subsystem of JRuby has long been a serious thorn in our sides. Based off probably a dozen different people's contributions over nearly eight years, it had become an impenetrable maze of code, half in Java, half in Ruby, but all clearly in the "suck" column. And I'm not saying anything negative about the contributors who wrote all that suckage (which includes me)...they all made valiant attempts to improve the situation. But a dozen 5% solutions had led us down an ever-more-terrifying rabbit hole. We faced the ultimate decision: fix or rewrite?

We were all set to rewrite. I'd already started an experiment I called "MiniJava", a mostly code-generated replacement for JI that boasted dynamic dispatch speed no slower than Ruby to Ruby and static dispatch speed (from Java into Ruby) only about two times slower than Java calling Java. There were many levels of awesome there, but one serious problem: no tests.

JRuby's JI layer has evolved over a long period of time, and has been worked on by a mix of TDD fans and non-fans. There have also been numerous attempts to rewrite portions of the system, usually ending far short of intentions and with no new tests for functionality added along the way. As a result, any attempt to replace the JI layer would be an exercise in pain: even *we* didn't know how it all works. It's probably not exaggerating to say that existing test cases covered less than half of JI functionality, and that the current JRuby team probably understood less than half of JI's implementation. Not a great place to start from.

Faced with the certainty of pain and knowing, workaholic that I am, that a large portion of the rewrite would probably fall on my shoulders, I decided to give it one more go. I decided to attempt an in-place refactoring of JRuby's Java Integration layer, tens of thousands of lines of spaghetti Java and Ruby code.

Redemption

I've had false starts before. The compiler had at least two partial attempts that failed to go anywhere. I've rewritten the JRuby interpreter several times. Hell, I can't count the number of times I tried to refactor JRuby's IO subsystem before finally succeeding. But JI...man, that is some seriously heinous code. So I had to start small. How about something I was already intimately familiar with: method dispatch.
puts "Measure bytelist appends (via Java integration)"
5.times {
puts Benchmark.measure {
sb = org.jruby.util.ByteList.new
foo = org.jruby.util.ByteList.plain("foo")
1000000.times {
sb.append(foo)
}
}
}

puts "Measure string appends (via normal Ruby)"
5.times {
puts Benchmark.measure {
str = ""
foo = "foo"
1000000.times {
str << foo
}
}
}

Here's one of our JI benchmarks. The idea here is that since JRuby's String type is backed by a ByteList, appending to a ByteList through Java integration should be roughly equivalent in execution cost to appending to a String. Or at least, that would be the ideal situations. It was not, however, the case in JRuby 1.1.3.
JRuby 1.1.3

Measure bytelist appends (via Java integration)
3.580000 0.000000 3.580000 ( 3.579149)
2.551000 0.000000 2.551000 ( 2.551251)
2.615000 0.000000 2.615000 ( 2.614461)
2.505000 0.000000 2.505000 ( 2.505265)
2.715000 0.000000 2.715000 ( 2.715380)
Measure string appends (via normal Ruby)
0.290000 0.000000 0.290000 ( 0.289629)
0.247000 0.000000 0.247000 ( 0.246666)
0.259000 0.000000 0.259000 ( 0.259266)
0.250000 0.000000 0.250000 ( 0.250354)
0.253000 0.000000 0.253000 ( 0.253113)

Ouch. Ten times worse? Sure, I could see it being a couple times worse; after all, going from Ruby code into a Ruby type and back out to Ruby code should be faster than Ruby to Java to Ruby, since we're talking about leaving the controlled world of JRuby core and coming back. But not ten times worse.

Armed with this and a few other benchmarks, I started attacking the dispatch path for Java calls. Largely the optimizations made were the same ones we'd done over the past year for Ruby code: avoid boxing arguments in arrays when possible; clean up and simplify overloaded method selection; as much as possible eliminate constructing any objects not directly used in the eventual reflected call. And early returns started to look really good. Once the basics of the new call logic were in place, performance started to look a lot better.
JRuby trunk

Measure bytelist appends (via Java integration)
1.490000 0.000000 1.490000 ( 1.489711)
0.658000 0.000000 0.658000 ( 0.657639)
0.646000 0.000000 0.646000 ( 0.645717)
0.638000 0.000000 0.638000 ( 0.637849)
0.603000 0.000000 0.603000 ( 0.602439)
Measure string appends (via normal Ruby)
0.312000 0.000000 0.312000 ( 0.312046)
0.232000 0.000000 0.232000 ( 0.231591)
0.243000 0.000000 0.243000 ( 0.242401)
0.235000 0.000000 0.235000 ( 0.235499)
0.232000 0.000000 0.232000 ( 0.231688)

That's more like it...less than three times slower than one of our fastest Ruby-based calls. Other benchmarks showed similar improvement.
JRuby 1.1.3

Measure Integer.valueOf, overloaded call with a primitive
2.384000 0.000000 2.384000 ( 2.383484)
2.167000 0.000000 2.167000 ( 2.167232)
2.191000 0.000000 2.191000 ( 2.191187)
2.212000 0.000000 2.212000 ( 2.211901)
2.202000 0.000000 2.202000 ( 2.202460)

JRuby trunk

Measure Integer.valueOf, overloaded call with a primitive
0.635000 0.000000 0.635000 ( 0.635259)
0.470000 0.000000 0.470000 ( 0.470315)
0.471000 0.000000 0.471000 ( 0.471354)
0.468000 0.000000 0.468000 ( 0.467723)
0.468000 0.000000 0.468000 ( 0.467589)

Here's an example of where improving overload selection made a huge difference. Previously, every time Ruby code called an overloaded Java method, we built up an ArrayList of all argument types, used that to get an aggregate hashcode, used the hashcode to see whether there was a cached previous match, and otherwise went through a brute-force search to match incoming types to outgoing Java signatures.

Wait a second. We constructed an ArrayList just to get a hashcode based on its contents? That dog won't hunt, Monsignor.

So I replaced that logic with a five-line method that aggregates the type's hashcodes into an uber-hashcode, which is then used as the cache key. Combine that with specific-arity searches (avoiding argument boxing in arrays) and search logic that understands Ruby objects (avoiding pre-coercing each argument to potentially the wrong type), and hey, we're starting to see the light.

Keeping it Real

Once it became apparent that a refactoring was most definitely possible, even if it took some hard work and a lot of dedication, we decided to put out a 1.1.4 release, focusing primarily on Java integration, but as always including peripheral bug fixes and performance improvements. Having made that decision, the JI job suddenly became a lot more important. I vowed that 1.1.3 would be the last release to contain a JI layer we were silently afraid of.

Then there was the matter of existing users. Since the beginning of the year, more and more folks have been branching out from the core Rails world that had been JRuby's bread and butter into "Java scripting" sorts of applications. Probably the most prominent ones are the team at Happy Camper Studios, who not only built a real-world-practical Swing framework for JRuby (see MonkeyBars) and a library for packaging up JRuby-based Ruby apps as single-file executables (see Rawr), but who also were pushing the boundaries of what Ruby and JRuby are capable of (see RailGun, and probably see a lot more in the near future). And to top it off, they were releasing MonkeyBars-based apps commercially...making their living depending on JRuby's JI layer.

Would it be a good decision to leave them with the old code for six months while we do a rewrite? I'll let you think about that for a bit.

More Results

Another area that needed serious work was juggling Ruby and Java arrays. The logic for coercing a Ruby array into a Java array was implemented half in Ruby and half in Java, neither half being very efficient in themselves. Add to that the constant back and forth, and you have a recipe for disaster. With another multi-day effort, I managed to wrestle the code to one side of the fence, refactor it, and improve performance over twenty times.
Code

require 'java'
require 'benchmark'

TIMES = (ARGV[0] || 5).to_i

TIMES.times do
Benchmark.bm(30) do |bm|
bm.report("control") {a = [1,2,3,4]; 100_000.times {a}}
bm.report("ary.to_java") {a = [1,2,3,4]; 100_000.times {a.to_java}}
bm.report("ary.to_java :object") {a = [1,2,3,4]; 100_000.times {a.to_java :object}}
bm.report("ary.to_java :string") {a = [1,2,3,4]; 100_000.times {a.to_java :string}}
end
end

JRuby 1.1.3
user system total real
control 0.013000 0.000000 0.013000 ( 0.013130)
ary.to_java 7.523000 0.000000 7.523000 ( 7.522787)
ary.to_java :object 7.794000 0.000000 7.794000 ( 7.794777)
ary.to_java :string 9.905000 0.000000 9.905000 ( 9.905805)

JRuby trunk
user system total real
control 0.009000 0.000000 0.009000 ( 0.009548)
ary.to_java 0.240000 0.000000 0.240000 ( 0.239946)
ary.to_java :object 0.248000 0.000000 0.248000 ( 0.247385)
ary.to_java :string 0.418000 0.000000 0.418000 ( 0.418230)

You can find similar improvements on trunk for object construction, interface implementation, and several other areas. Work continues, but performance is starting to look way better.

Don't You Think About Anything But Performance?

Of course a side effect of simplifying the code for performance reasons is that fixing bugs and adding features becomes a lot easier. Check out a tiny bit of new logic that works now on JRuby trunk:
# "closure conversion" was only supported for instance methods before
thread = java.lang.Thread.new { puts 'Wahoo!' }
thread.start
thread.join
# output: 'Wahoo!'

Of course this is a somewhat contrived example, but there are some obviously useful examples too:
javax.swing.SwingUtilities.invoke_later { puts "Yay, Swing!" }
# script terminates, but the Swing event thread keeps running until it's fired our block

The ability to pass a block to "any method" that accepted an interface as its last parameter was only functional for instance methods in all previous releases of JRuby. After the refactoring, expanding it to constructors and static methods took about 5 minutes. With tests. We'll come back to that in a moment.

The simplification of the code also means we'll probably be able to fix a bunch of Java Integration bugs we've punted on for months. For example, it's been a long-standing bug that you can't implement a Java interface in Ruby by defining the underscored versions of that interface's method names. But now, with newly rewritten JI interface-implementation code, it should be a snap to add that feature. We're planning to do a JI bug audit for 1.1.4 and knock down as many long-standing issues as we can.

Proving It Works

So back to the tests for a moment.

Some months ago we managed to get a baseline suite of RSpec specs into the JRuby development process thanks to Nick Sieger. Initially, the tests were very sparse, only a few specific things Nick had a chance to put together. But as interested community members started sending in patches, we started to grow a nice little suite.

As I've been working on the refactoring, I've been trying to "test along" as I learn how bits of JRuby's JI layer function. And so I've added a number of new specs for type coercion, interface implementation, method dispatch and overload selection, and others. Ola Bini came out of hiding to contribute a pretty comprehensive set of Array specs, which were a great help during the slaying of the Array-coercion dragon. So we're finally getting that suite we'd always needed, and once the refactoring is done we'll be in a far better position to start taking JI to the next level.

What's Next?

At the moment the refactoring is maybe 25% along. I'm the only one working on it, and it's a crapload of code, so it's going to take a little time. But most key performance bottlenecks have been remedied at this point.

There are a few areas that remain to be tackled:
  • Refactoring the extensive logic governing how Ruby classes can extend abstract or concrete Java classes. Kresten Krab Thorup contributed this well over a year ago, and it's kinda been an island unto itself. It will take a considerable effort to rework.

  • Moving the remaining core JI logic from Ruby into Java. I know, turtles and all that...but I've seen enough projects try to do large-scale refactorings in Ruby to know that the tools and techniques simply aren't there yet. By moving this logic into Java, where it belongs, we'll probably be able to delete 90% of it. That means more room for performance and features, and a much higher likelihood that future enhancements can safely live in Ruby without incurring a severe performance penalty.

  • Eliminating the old "lower level" and "higher level" Java integration layers. Originally, JRuby's JI was implemented as a set of reflection-like Ruby classes wrapping Java's reflection classes (which comprised the "lower level") and a substantial amount of Ruby code that juggled these reflected bits to represent Java types and make Java calls (the so-called "higher level"). While conceptually this makes some sense, in practice it meant that any call from Ruby to Java actually ended up as dozens, maybe hundreds of Ruby invocations before the target Java method could be invoked. Performance improvements over the past four years were able to improve matters, but largely the only substantial gains have come from, and will continue to come from, eliminating the two separate levels entirely.

I intend for all of this to be in place for JRuby 1.1.4, which we want to release this month.

Next Time on Headius: Tune in for my next post, hopefully soon, about two Rubinius APIs we've added for 1.1.4: Multiple VMs (MVM) and Foreign Function Interface (FFI).

Tug-grall New cool tools that I am using: DabbleBoard & Balsamiq

by Tugdual Grall | 1 day ago | Read more

When working on software design, UI Mockups are quite important and Patrice, colleague of mine at eXo has pointed me to a very cool tool to use when you have to quickly do a mockup, and work with the dev team in an iterative fashion: This tool is "Balsamiq Mockup". Here an example of mockup realized with Balsamiq: Also if you read more about the tool, you can see that it has native integration


Tell us what you think of the new BlogSphere feature. We are continually looking to improve and update the functionality based on your feedback.

Job Board

Job Boards
Find your next Ruby on Rails project or job.
Exclusive content, regularly updated - onsite and tele-working positions listed.

View the opportunities

Latest from the Weblog

Recent Recommendation

Craig Webster:

Great article on couchdb + ubuntu

- Sbubble I.K, United Kingdom