Monday, September 28, 2009

Jikes RVM

Turtles all the way down.

Chapter 10 of our mainstay, Beautiful Architecture, describes another to me somewhat surprising use of Java. The Jikes RVM is a so-called metacircular virtual machine or runtime. It hosts Java byte code, but what makes it metacircular is that it is also implemented in Java. My first thought was how this could be because somewhere something must be running on the actual hardware. Surely it can't be turtles all the way down. I started to dream about fancy bootstrapping tricks, but the answer turned out to be straightforward which I admit disappointed me a bit. Even though the Jikes RVM is written in Java, a language that is usually compiled to bytecode, in this case they compile it down to machine code.

The authors spend quite a bit of text-space arguing the virtues of metacircularity. I thought that most of these argument was actually for using Java at all and not for using Java for implementing a JVM in particular. The case of metacircularity, from what I could distill, boiled down to two arguments. The first is that this means that the runtime/VM and the code being run will use the same conventions (calling, etc.) which removes some need for converting. The second is that using the VM's JIT compiler to compile itself (there were some bootstrapping in there after all!) creates a virtuous cycle where good thing happens and I can definitely see the benefits with this. However, writing a compiler is an art of tradeoffs (or so I'm told) and surely some of the tradeoffs must be different for regular JIT code and a compiler being compiled offline? I wonder whether they have situations where they must choose between bloating the compiler, making it less suitable as a JIT, or leaving out some costly optimizations thereby making it less suitable for offline compilation of itself and the JVM. However, the project seems to be fairly successful so I guess they managed to navigate these tradeoffs satisfactorily.

If I were to point out any disadvantages with the concept of metacircularity itself then I would argue that every tool has a job and every job has a tool. Not all languages are equally good at implementing all software so a language that is, for example, highly productive in creating enterprise applications is not necessarily the most effective one for creating a compiler. On the contrary a different language with different design decisions will often be more suited for this job. Note that I do not here consider wether Java is best suitable for creating a VM in general. That is another discussion (of which, based on JPC I would say the answer is probably no in most cases). In this paragraph I only considered whether the target language is inherently the best choice for implementing its runtime.

Marcus Strautman posed an interesting question of whether a JVM rolling its own threading model is a good idea today. According to the chapter Jikes RVM did this because of lacking multithreading support in the previous century. Although OS support for multithreading is much better now I would not necessarily throw away green treads completely as there are other benefits to them. The number of cores in processor is expected to be the main beneficiary of Moore's law in the years to come (as a side note Moore's law is falsely, or at least prematurely, proclaimed dead as the law is about transistors per CPU and not about speed). As we must expect cores to increase in the future we should at least try to create as many independent threads of execution as we can in software that needs to be scalable. However, native thread switching comes at a cost which means that our software will be slower today! Green threads are usually cheaper and in environment with cheap threads the application programmer can afford to create more of them (programming time not considered). This means that an implementation with green threads on a dual-core processor could, for example, use two-three native threads in a thread-pool fashion to execute them while on a quad-core it could use four-six threads and so on with no change to the application. Furthermore, with more application threads available the runtime is freer to schedule them in clever ways to hide latency by exploiting techniques such as simultaneous multithreading (aka. hyperthreading), etc.

No comments:

Post a Comment