For the last couple of weeks I've been fossicking around in the Ruby Interpreter code, looking for a clean fracture point or three. Ever since I first met Ruby back in 2001 I've had this dream of using it for embedded work, but the current implementations aren't suited to this and conventional wisdom would be that it's a mad idea in the first place.
It probably is.
Then again, real-time Ruby is no stranger an idea than real-time Lisp, and Minima proved that that's feasible way back in the 80s. Of course there are a lot of implementation details that would need to change to allow real-time performance and I've my doubts about minimising the memory footprint, but that's the reason for the extensive code exploration.
All the cool kids are playing with Ruby 1.9, which is the unstable development branch for testing out potential Ruby 2.0 features, but I'd rather stick with the 1.8.6 codebase for the time being as that's been extensively hammered over the years. Anyway none of the 1.9 features are compelling, with the possible exception of Fibres and YARV.
For those who don't know what YARV is, it's a stack-based bytecode virtual machine like Perl's Parrot or the JVM. I've followed it's progress over the last couple of years and it's a step in the right direction, but I'm not sure it's suited to a real-time environment.
To start with stack machines are efficient in terms of bytecode representation but are generally slower than competing register machine architectures although this isn't entirely clear cut as there are many other factors that affect the performance of virtual machines. Admittedly speed isn't everything unless you're working on math-intensive applications, but it's nice to have and helps cut down latency in a real-time setting. Anyway I think this is an area that could be fun to investigate further.
Because YARV plays nicely with existing C extensions it perpetuates the Global Interpreter Lock model which prevents more than one thread running at a given time. I've always thought this to be an odd choice given the move from green threads to native threads, especially since the JRuby project have ditched the Global Lock. There is experimental support for native threading in 1.8.6 and I'm interested in how that would need to be reworked if the Lock were to be abolished. Parallel execution isn't a hard requirement for real-time and in some circumstances can even have a negative impact, but it is useful to be able to run background tasks for handling watchdog timers, multiple I/O streams and other housekeeping chores.
Mind you, naive native threads may not be the best way to handle concurrency. A couple of years ago I spent some time studying the pi-calculus additions to KrOC Occam and building something similar into a VM might suggest new lightweight thread implementations. That's all speculative though.
There's a great performance opportunity offered by GCC for using computed goto statements to build a threaded despatcher. This breaks ANSI compatibility but with the GNU toolchain targeting so many platforms it's a small price to pay for avoiding the overhead of C's switch statement. It's also probably the easiest change to make.
Garbage collection is a key convenience of the Ruby runtime but this is another area that would need an overhaul. Mark and sweep is a popular method, but generational schemes can have lower performance overheads - especially when the host processor relies on caching. Also there's the question of whether or not to run a single concurrent or incremental garbage collector, or to run a separate collector for each thread.
I don't know if any of the experiments I have planned will pay off, but that's half the fun :)