On 25 Jan 2010, at 19:12, Mike D. wrote:
Complicated? Yes. I’ve summed it all up in a nice matrix here:
I personally think these choices all suck, and I refuse to paint a happy
face on any of them.
I have to agree, which is why I mostly seem to end up describing how to
break things via dynamic loading - although I’ll admit it’s also a lot
Frankly though there is no general case solution which can satisfy all
of the needs of both the Java/Enterprise world and C hackers. Every time
we make the choice to use a third-party library written in anything
other than Ruby as a core dependency of our projects we tie ourselves to
a specific runtime environment as surely as if we were relying on some
custom assembler code and that’s just something to accept and move on.
It’s maddening, but it’s a fact that programmers the world over already
live with on a daily basis.
Last year I spent a fair chunk of time giving lightweight lectures about
Unix abuse from Ruby for those new to the hobby. Many of the techniques
I was keen to demonstrate either won’t work on other platforms or do so
unstably, but so what? If I’m writing for a Windows box I already know
that and I’ll design things differently.
The same principle applies to JRuby. It can run arbitrary C libraries
via FFI if they’re present on the target platform but if they’re not
it’s exactly as stymied as MRI or Rubinius or MacRuby would be in the
same situation. Runtime environment is more than just processor
architecture or operating system and not to take account of that in
deployed code is the fault of the programmer concerned not the team who
developed the runtime implementation.
Now I’ve often facetiously suggested in this list that all our code
should be developed in Ruby. The main reason I suggest that is that we
often rush to utilise code in other languages without considering its
real as opposed to perceived cost, not only in terms of development
effort and runtime performance but also of longterm maintenance.
Synthetic benchmarks tell us sweet FA about real world performance of
code, architecture being a much more significant consideration than the
proportion of raw MIPS a given language will deliver on a given
platform. The average netbook could happily run all of Teller’s fusion
bomb models along with the full telemetry analysis of all the Apollo
missions in the pauses between loading XKCD comics and binning junk mail
without the user being any the wiser.
But architecture is also the primary determinant of how maintainable a
given application will be and whether it’ll scale to suit future needs.
The main reason we’re not using Ruby for everything is that the
architecture of the reference implementation is a relatively poor match
for the underlying hardware on which our programs run and so a lot of
translation work is being handled automagically (and inefficiently).
Rather than wasting our time arguing over defects we can’t fix (such as
not all platforms having access to a given native library) we should be
fixing that core deficit and developing Ruby runtimes that unlock the
level of performance we want from our language. Then more and more
libraries will deliver high performance in pure Ruby and runtime library
issues should become irrelevant.
So far I see most of the work capable of delivering this (such as a
decent abstract Intermediate Language for peep-hole optimisation) coming
from the JRuby team. If the rest of us poured a fraction of the effort
into similar efforts for MRI and other implementations that’s expended
on making [FFI|DL|C] API wrappers of existing C libraries then Ruby may
stop being the slow relative of Python and start to compete as what it’s
fully capable of being - a systems language.
I have several long rants on this subject that I’ll spare anyone who’s
not stuck in a bar with me (and is willing to keep the beer flowing, you
know who you are lol) but at the very least Ruby needs: a parallelised
library implementation to seamlessly (i.e. without programmer
intervention) exploit multicore hardware and multithreaded operating
systems; ‘unsafe’ access to raw memory and kernel event mechanisms for
higher-performance data structures and IO; and a register-based and
JIT-friendly virtual machine so runtime code can be translated to
efficient machine code.
These are the basic architectural building blocks that would make the
need to rely on libraries in C, Java or any other language much rarer.
raise ArgumentError unless @reality.responds_to? :reason