Thursday, April 9, 2009

Portable Linux future using LLVM

Imagine a single Linux distribution that adapts to whatever hardware you run it on. When run on an Atom netbook, all the software shapes and optimizes to the feature set and processor characteristics of the specific version of Atom. Want to run it as a VM on a new Nehalem-based server? No problem, it re-shapes to fit the Nehalem (Core i7) architecture. And here, when I say "re-shape", I don't mean at the GUI level. Rather, I mean the software is effectively re-targeted for your processor's architecture, like it had been re-compiled.

Today, Linux vendors tend to make choices about which one or set of processor generations (and thus features) are targeted during compile-time, for the variety of apps included in the distro. This forces some least-common-denominator decisions, based on processor and compiler features, as known at the time of creation of a given distro version. In other words, decisions are made for you by the Linux distributor, and you're stuck with that. When you run a distro on new hardware, you may well not be able to access new features in the hardware you purchased. Or, a distro targeted for advanced hardware may not run on your older hardware. Such is the current state of affairs (or disarray as I like to think of it).

Enter LLVM, a compiler infrastructure which allows for compilation of programs to an intermediate representation (IR; think Java byte codes), optimizations during many phases (compile, link and run-times), and ultimately the transformation of IR to native machine code for your platform. I see the IR enabling powerful opportunities beyond the current usage -- one opportunity being, distributing Linux apps and libraries in IR format, rather than in machine code. And then having the infrastructure (including back-ends specific to your platform to transform the IR to native machine code), and potentially caching this translation for optimization's sake. The obvious benefit here is to enable much more adaptable/portable apps. But it also orthogonalizes compiler issues, such as which optimizations are used (and the stability of those optimizations), such that those can be updated in the back-end without touching the apps in IR form. Modularization is a good thing.

A resulting question is, how low-level could we push this in terms of software? At a LLVM talk I attended, there was mention that some folks played with compiling the Linux kernel using LLVM. I'd like to see that become a concerted effort from the processor vendors, as it would allow Linux to become more adaptive, perhaps more efficient, and show off features of new processors without having to adapt all the software. I have many related ideas on how to make this work out.

Especially given the trend towards some exciting convergence between CPU and GPU-like processing, and many available cores/threads, I think it's time we take a hard look at keeping distributed code in an IR-like form, and orthogonalizing the optimizations and conversion to native code. In a lot of ways, this will allow the processor vendors to innovate more rapidly without breaking existing code, while exposing the benefits of the innovations more rapidly without necessitating code updates.

Disclosure: no positions


cl333r said...

Good idea, but it must solve some issues either well or die.
-Whatever decision is taken, startup time may not get worse at all, "recompiling" every time and/or caching - is a thing Java already does so no need to reinvent the wheel even if it would seem a better implementation, the recompilation for your target machine should probably be done while/after application installation instead.
-Even if LLVM gets perfect it would still require a lot of energy to get the industry start using it which could prove more difficult than creating LLVM for different reasons.

krokas said...

Maybe use something more sofisticated, which has a thoughtful design, maybe something based on Common Intermediate Language and .NET? It is the basic idea of .NET design to be portable.

bnjammin said...

This is very interesting -- I wonder how using LLVM to build "portable" Linux OS's balances the need to do enough of the "compiling" such that subsequent system-level optimizations do not take so long that it'd be easier to just re-build the system in its entirety and the need to not compile so much as to retain sufficient flexibility to make a meaningful impact for hardware variations.

The answer to that question probably also determines to some degree the final performance of the OS -- which leads to a final question, how much system-specific adaptation can one milk out of LLVM and does it compensate for any performance hit that's necessitated by the need to do some of the compiling of the kernel in a least-common-denominator fashion to get to the intermediate representation.

Kevin Lawton said...

Ben et al, good thoughts. The good news is that LLVM can be "staged in" for use as a Linux distro. One could start with a native kernel, some native libs/apps, and some LLVM ones. As the technology/adoptions evolves, more things could be shifted to the LLVM camp. As was mentioned, caching is useful. Though one more simplistic way to go about it, is to do the translation from LLVM to native at install time. The user would only ever see native, but it would be tailored to their hardware.