A comparison of Inferno and Java

Journalists are drawing comparisons between Inferno and Java. For this reason, we offer this note to present our perspective on how the two technologies interact.

Java is a programming language, while Inferno is a full network operating system including a kernel, programming language, communications protocols, libraries, security and authentication, naming protocols, APIs, and so on. Inferno is therefore a more comprehensive offering, one that addresses more of the problems of building networked applications. Although Inferno includes a programming language, called Limbo, it will support others, and Java is an obvious candidate.

A programming language, even with its libraries, is not enough, nor is it always the right place to solve all the problems of the network. Therefore Limbo is supported by the full Inferno environment that includes security and authentication, naming protocols, directory services, network interfaces, and so on. When a Limbo program begins execution, it has a fixed interface to these services and is therefore inherently more portable than any language-only solution. One example is the network API, which is identical in all Inferno systems, independent of the hosting operating system or the network itself. Another example is security: features such as digesting and encryption are done in the lowest levels of the system, allowing an application to use them uniformly, or even remain unaware of their presence, such as when a remote application wishes to establish a secure connection to a local one. Moreover, Inferno was designed to manage the network, servers, and other network elements, not just client applications. Inferno provides the means to configure the execution of programs from pieces anywhere in the network, not just on the client.

This difference of depth is the real distinction between Inferno and Java.

Looking at just the language component, however, Java and Limbo can be directly compared. The languages have some common ideas and are similar in many ways: both use C-like syntax, both compile to a virtual machine that can be interpreted or compiled on-the-fly for portable execution, both use garbage collection to manage memory, and both support the Unicode character set. Java is derived from C++ and uses the object model to provide interfaces to system services. Limbo avoids the complex object-oriented features of C++ but has more basic types - lists, strings, tuples, etc. - and programming concepts - threads, communication channels - built into the language.

Limbo differs from Java in several important ways. For Limbo, concurrency and communication are an intrinsic part of the language and the virtual machine, and are used extensively in the programming model. Limbo has more general pointers, without sacrificing safety. Limbo's garbage collector has constant overhead, so its operation does not conflict with real-time constraints. Also, the collector reclaims memory as soon as the last reference is released, to minimize the memory needed for execution. Limbo completely manages the lifetime of system resources by tying windows, network connections, and file descriptors to the garbage collector. Coupled with Limbo's `instant free' property, this eliminates the need even to write special free routines, let alone call them.

Limbo programs are built as sets of modules that export interfaces whose implementation may be selected at run time. An application can configure dynamically, loading only those modules needed at any moment; it may load and even unload modules as its environment or execution dictates. The ease of exporting interfaces across the network allows modules to be run remotely; for example, a client can use the DNS facilities of a server without the need to run DNS on the local machine.

Limbo has numerous libraries, packaged as modules. While the current set covers some of the same ground as Java's libraries, there are differences. For example, Limbo's floating point package provides control of exceptions and the graphics toolkit is based on the familiar model of Ousterhout's Tk toolkit.

Diving down a level, Limbo's virtual machine, Dis, is well suited to on-the-fly (just-in-time) compilation. The machine is a memory-to-memory architecture, not a stack machine, that translates easily to native instruction sets. In fact, many Dis instructions translate to a single Pentium instruction. The on-the-fly compilers are small - the implementation for Intel 386 architectures is only about 1300 lines of C - and result in code that performs within about a factor of two of compiled C. For the same reason, the Dis interpreter is considerably smaller than the implementation of the Java virtual machine.

The combination of programs composed as modules and efficient compilation makes plug-ins unnecessary: codecs for playing things like AVI and QuickTime clips are written as Limbo modules. Although this means existing C-language implementations have been rewritten, it also means the modules are completely portable. As a related point, the multithreading in the language simplifies the implementation of scheduling in real-time codecs.

Perhaps most important, Limbo and Dis, like all of Inferno, were designed from the ground up specifically for the job of providing an environment for networked applications. Inferno has properties that address the problems of building and deploying networked applications.

Again, since many of the issues of programming in a networked environment are addressed by other parts of the system, it makes sense for Java programs to run in the Inferno environment, where they can gain many of the advantages of uniform access to system services. Since we plan to provide Java support, Inferno is more a complement to Java than a competitor with it.

Copyright © 1996 Lucent Technologies Inc. All rights reserved.