Perhaps limbo scales extremely well to large projects
it *does* work well in large projects, because unlike many OO languages, it is completely type safe. this means that you *cannot* get type errors when the program is running.
the avoidance of name overloading (by type or by function arguments) means that it is always easy to find out where a name has come from, and find the code associated with it - just with a simple grep.
when browsing code, you don't have to have any understanding of an inheritance hierarchy to work out what's going on. i.e. the language is great for hiding complexity, which is exactly what you want when working on large pieces of code where you're not exactly sure what's going on.
limbo is careful to make promises only when it can give a cast iron guarantee that it can fulfil them. contrast that to something like java's "protected" attribute, where any class in the same package can modify - it means nothing when you're looking for that elusive heisenbug.
all that said, there are a couple of things i'd like to see in the language. generics for one, which could work really nicely, without any of the code bloat associated with them in, say C++, and without any runtime overhead either. we're working on it!
referencing counting can actually be slower, in general, than a decent tracing garbage collector. (every time a pointer is copied or unreferenced (worst case): a test for null, an arithmetic operation, and in the case of unreferencing, another test of the reference count against 0. This makes for bigger code, with slower execution than without (obviously), and can be slower than a tracing collector.) The gc in java early on was simply crummy; there *are* better garbage collectors.
i agree that in terms of arithmetic operations executed, ref counted garbage collection can be slower then other types of GC, BUT the big advantage that it has is space efficiency and time determinism. with ref counted GC i can write an algorithm that i know will run in the same time and space regardless of what other concurrent processes are doing with the memory subsystem. this is a big win when running on small devices; and i have to say it also helps even hosted on a larger system - less paging; it keeps to its working set better.
This makes for bigger code
don't forget that we're talking about a virtual machine here. so the code isn't actually bigger, because the operations are done below the level of the VM instructions.
You forgot the worse of ref-couning: cache trashing. There is a lot of memory-references for ref-count maintaining, and it is very costly.
actually, although i haven't got a reference, i would think that ref counting would be better than other GC methods with respect to cache trashing, because the ref count updating is only being done with the small set of objects that you're currently working with. a cache will work best when there's a relatively small subset of memory being worked with, and ref counting will help with that.
Okay, I'm thinking of it as code associated with a name space. However, when you have a function, you actually have a pointer to the memory where that code is, and a function call is simply a jump to those instructions. For example, In Linux: You call gethostbyname(). It calls a system trap which jumps to that code inside the kernel (or netoworking library or whatever.) That function then procedes to get the host name and return it.
that's almost exactly how it happens in Inferno too. the fact that the metaphor for the gethostbyname call looks like a file system really causes hardly any overhead. this is how it happens in inferno (and in plan 9 for that matter only there you need a trap to get out of user mode into supervisor mode):
first you open the file/net/cs. if the network device is local, which it usually is, then the entry in the file descriptor table is now a pointer to a kernel Chan that has been provided by the device serving/net. Inside this Chan is a set of function pointers, one for each of the basic file operations (i.e. open, read, write, stat, etc). when you do a write of, say tcp!slashdot.com!http, the kernel just has to do a single indirect function call to the write() function in the Chan and you're in the device driver. this is probably just as efficient as a Linux system call, especially since that in Inferno there's no distinction between user mode and supervisor mode (the language is safe), so you don't have the overhead of doing a processor trap.
In Inferno: You write something to a virtual file. The Inferno filesystem intercepts the write. It takes a look at what command you are trying to do, takes a look at the stuff you feed it (parameters) and then passes that info onto the networking code in the kernel via a function call. This step of having the kernel intercept the call and decode it is what introduces the overhead.
the kernel doesn't have to ``decode'' the call any more than a linux kernel does. yes, it has to verify that the file descriptor is valid (big deal, if (fd >=0 && fd <= fdgrp->maxfd)) it's the device driver itself that does the decoding of the request, and since in the case of gethostbyname() you're just mapping from a string anyway, there is no more overhead.
Also, since it is a virtual file, memory writes and reads have to be done than during a funciton call. All this is what introduces the overhead.
nope. inferno system calls do not make any copies of the data unless they have to. i just had a look at the relevant code, and the pathway between a user program doing write() and the device getting that call probably about 20 to 30 machine instructions executed. there is no real overhead compared to the traditional syscall interface.
BUT what you do get is consistency across all device interfaces. because gethostbyname() is not just a system call, but is part of the namespace, i can export that down any data connection. so, say i've got a little handheld device that has no tcp/ip stack, no DNS, nothing apart from some sort of serial driver and the Styx driver (which is very small), then i can connect it up to my desktop PC, import the network devices +/net/cs from it, and bingo i've got what looks like direct access to the net. yes, i've now got to send those requests over the serial link now, but i can do something that i couldn't do otherwise without inventing my own, use once, limited purpose protocol...
that applies to all inferno devices. the fact that the interface is an abstract one does not necessarily mean that it's inefficient. if you're interested, have a look at the plan 9 code (login 9fan, password glenda) that does the same thing. i think you'll find that the path from user program to system call implementation code compares favourably with most *NIXen.
the file abstraction in inferno is a wonderful thing - if you're using it, it means you don't have to write a specialised protocol for every new network service - if a service is running locally, it's efficient; if it's running remotely, the protocol work is done for you.
Besides, you can do incredible things with mere sh scripts in inferno, since everything is a file.
had to respond to this, as i've recently finished writing the inferno shell. (unless that's anonymous coward chris, ya bugger, in which case i've just been trolled, sorry folks)
where else can you make a distributed app in one line of shell script? file2chan/dev/shellctl {} {somecommand ${unquote ${rget data}}} that one line makes a file in the namespace - any write to that file runs somecommand with the arguments that have been written to the file. i.e. i can do: echo ${quote arg1 'arg 2'} >/dev/shellctl or even better: fn somecommand { echo ${quote $*} >/dev/shellctl } somecommand arg1 'arg 2' and it'll run somecommand arg1 'arg 2' in the original process. the properties of the inferno namespace mean that i can then export that across the network transparently, encrypted, etc. corba eat your heart out.:-)
yeah, leave it to the techies over at bell labs to ruin a great os by tying it to a ridiculous gui... how 'bout those smiley faces though:)
i dunno whether you're talking about plan 9 or inferno there. plan 9's got a great gui - it just doesn't fit into how our microsoft-warped brains think a GUI should look like.
inferno however... well, the GUI does need a bit of looking at. and i am looking at it! i'm currently working on the window manager, which was written a few years ago in a weekend and hasn't changed much since.
but it's not a big job. applications aren't heavily tied into the look and feel of the GUI, which makes for less bloated apps. the main GUI is based on a variant of tk which means that the underlying GUI code can be changed in one place, and the whole feel of the thing changes. inferno hasn't had any hardcore graphics designers let loose on it, but if it did, believe me, it could look beautiful!
inferno isn't great because of its GUI, but because of what's underneath. look at the lego brick demo for a flavour of what can be done with devices under inferno.
we've got all the manual pages on line, so if you're interested in techie details about the system, you can see them here.
well, it's only the core OS that's being charged for - most of the development environment is free (as in beer & liberty), unencumbered, open source, whatever you want to call it. that includes (at the last count) 225460 lines of Limbo source code doing all sorts of cool things outside the kernel.
you can do with that what you want. if you want to hack the kernel, port it to a new platform, whatever, then, yes you have to pay your $300 and become a subscriber. but once one person has done that, they can distribute the kernel binaries with no hinderance, and due to the portable nature of inferno, all worked under it will still work under the new version.
if i wasn't involved in inferno development and was stuck under Windows of some description, then i'd get a copy, just for the environment. unix-like shells under NT are ok, but they don't give you that "my whole environment is pliable under my fingers" feel that having a complete environment does.
the beauty of inferno includes the fact that once you've got something in your namespace (and everything, including network connections, is accessed through the namespace) you can transparently export it through any type of datalink, with whatever sort of encryption/authentication you want, and use it as if it was local. i don't know any other system that provides that much flexibility for so little protocol overhead.
well i don't think it's still "horridly slow"; i use it a lot of the time and it is slower than C, but not bad at all.
as far as performance goes, there's also the fact that there hasn't yet been a great deal of work done optimizing the compiler output or the JIT (i.e. currently the JIT does little registerisation, where the design of the DIS VM means that registerisation should be relatively easy to do - see this). i have a feeling that it's quite a lot faster than most java versions.
what's it good for? all sorts of things. it's a really clean environment to write programs in. where plan 9 is really clean in the namespace and the system interface, but still uses C as the application programming language, Inferno has all that, but uses Limbo as the language with Dis underneath.
the main advantage it gives you when writing programs is that your programs are unconditionally portable - if i've written a Limbo program to run on a screen phone (bare hardware, ARM SA1100) then, assuming enough memory, i have no doubts about it running perfectly on any other platform on which Inferno is supported.
that, coupled with the fact that limbo is a really, really nice language means that i don't want to develop for anything else. i started off as a C developer about 10 years ago, managed to escape Ingres (eugh) after a couple of years, hacked some Occam (which is a nice language, but somewhat limited in its type system), ended up in Objective-C under NeXTstep/Openstep/(macosX?). so i've hacked in a number of languages, and Limbo wins hands down.
why? it's difficult to say. it's a combination of many factors that all go to make up for a thoroughly enjoyable programming experience. i love C (not C++ though!) and it keeps the "power at your fingertips" feel that you get with C, but without pointers, with garbage collection, with complete type safety... perhaps the main feature is that when you read a Limbo program, you can actually tell what it's doing! (shock horror). all the names that are accessible to a fragment of code are easily findable. there's no overloading. the OO paradigm works entirely around aggregation - no inheritance whatsoever. the inbuilt types work really nicely - value types mean that in a multi-threaded environment, which Inferno/Limbo is, you are utterly certain that a value can't be changed underneath you).
what programs are for it? well, there's a web browser, but if you're running it hosted, then you'll probably have one anyway (that doesn't have to conform to the restriction of needing to run in 4MB). i've written what i think is a fairly cool programmable shell for it which is pretty small as well (main binary for it is 36K). i also wrote a passable version of Tetris (which is great 'cos now i can play the same version against people in the office running windows, linux, plan 9 and screenphones!), and i'm finishing off a pretty nice FIBS client. most of that stuff i did in my spare time. there's a version of Acme that's been ported, so you can see how the original compares to Wily.
how easily can you port programs from *NIX? (shouldn't that be *N[UI]X ?:-]) depends on what sort of program you're talking about. what inferno does *not* have (and this is the reason it's so small) is all the legacy stuff that *NIX has picked up over the years. this it has in common with plan 9. it does not have cursor addressing programs (although i wouldn't mind porting a decent vt100 emulator). it does not have termcap/terminfo/curses/ioctl/fcntl or sockets. so porting anything that relies on that stuff (e.g. emacs, slrn) won't be at all easy. BUT, straight C usually goes very nicely into Limbo. most of the standard unix command line programs (i.e. the ones that just munge stdin to stdout) go fine. The Limbo arithmetic expression syntax uses the same precedence rules as C, so all those nightmare mathematical equations are little problem (unless they've got dodgy type promotion going on, which you want to know about anyway).
the best thing about inferno is that it's a truly component oriented architecture. OO systems with inheritance don't give you that as there's too much interdependence between objects at different levels. Limbo modules under the dis VM really do work as plug & play s/w...
i was sad myself when i found out they were binning alef. i have a feeling though that it was due to underlying problems with the language design. phil winterbottom knows. (the other possibly more important reason that they give on the web site is that it's yet another compiler suite to maintain...)
the concurrent bits of alef (the nice bits) have been taken over by a C library, and Acme has been rewritten in C.
the real replacement for alef is Limbo, the language used in Inferno (itself an offshoot of plan 9); it takes many of the best ideas from alef, but the syntax isn't quite so C-like - it's much, much cleaner in lots of ways (e.g. garbage collection, no arbitrary pointers, very clean type system), built from the bottom up around dynamically loaded modules running on a virtual machine, but with all the power of plan 9-like namespaces underneath.
having been using almost exclusively for the last year or so, i'd hate to go back to anything else.
Inferno fits very nicely along with plan 9 - it's a highly lean machine that runs on really small systems (for instance, the executables are remarkably tiny - the binary for ls, for example is 2902 bytes, from 270 lines of source) and also runs hosted under NT, Linux, BSD, etc so at last you can get the power of acme, plumbing, plan 9 namespaces, and a unix-like command line from inside NT or w98, along with *genuinely* portable programs (unlike java, for instance, where everyone has their favourite incompatibility story)...
it's not available.... yet. but you can register if you're interested at wwww.vitanuova.com, and you never know what might happen...
depends whether you like C or pascal. limbo is C-like; oberon is pascal-like.
it *does* work well in large projects, because unlike many OO languages, it is completely type safe. this means that you *cannot* get type errors when the program is running.
the avoidance of name overloading (by type or by function arguments) means that it is always easy to find out where a name has come from, and find the code associated with it - just with a simple grep.
when browsing code, you don't have to have any understanding of an inheritance hierarchy to work out what's going on. i.e. the language is great for hiding complexity, which is exactly what you want when working on large pieces of code where you're not exactly sure what's going on.
limbo is careful to make promises only when it can give a cast iron guarantee that it can fulfil them. contrast that to something like java's "protected" attribute, where any class in the same package can modify - it means nothing when you're looking for that elusive heisenbug.
all that said, there are a couple of things i'd like to see in the language. generics for one, which could work really nicely, without any of the code bloat associated with them in, say C++, and without any runtime overhead either. we're working on it!
i agree that in terms of arithmetic operations executed, ref counted garbage collection can be slower then other types of GC, BUT the big advantage that it has is space efficiency and time determinism. with ref counted GC i can write an algorithm that i know will run in the same time and space regardless of what other concurrent processes are doing with the memory subsystem. this is a big win when running on small devices; and i have to say it also helps even hosted on a larger system - less paging; it keeps to its working set better.
This makes for bigger code
don't forget that we're talking about a virtual machine here. so the code isn't actually bigger, because the operations are done below the level of the VM instructions.
You forgot the worse of ref-couning: cache trashing. There is a lot of memory-references for ref-count maintaining, and it is very costly.
actually, although i haven't got a reference, i would think that ref counting would be better than other GC methods with respect to cache trashing, because the ref count updating is only being done with the small set of objects that you're currently working with. a cache will work best when there's a relatively small subset of memory being worked with, and ref counting will help with that.
that's almost exactly how it happens in Inferno too. the fact that the metaphor for the gethostbyname call looks like a file system really causes hardly any overhead. this is how it happens in inferno (and in plan 9 for that matter only there you need a trap to get out of user mode into supervisor mode):
first you open the file /net/cs. if the network device is local, which it usually is, then the entry in the file descriptor table is now a pointer to a kernel Chan that has been provided by the device serving /net. Inside this Chan is a set of function pointers, one for each of the basic file operations (i.e. open, read, write, stat, etc). when you do a write of, say tcp!slashdot.com!http, the kernel just has to do a single indirect function call to the write() function in the Chan and you're in the device driver. this is probably just as efficient as a Linux system call, especially since that in Inferno there's no distinction between user mode and supervisor mode (the language is safe), so you don't have the overhead of doing a processor trap.
In Inferno: You write something to a virtual file. The Inferno filesystem intercepts the write. It takes a look at what command you are trying to do, takes a look at the stuff you feed it (parameters) and then passes that info onto the networking code in the kernel via a function call. This step of having the kernel intercept the call and decode it is what introduces the overhead.
the kernel doesn't have to ``decode'' the call any more than a linux kernel does. yes, it has to verify that the file descriptor is valid (big deal, if (fd >=0 && fd <= fdgrp->maxfd)) it's the device driver itself that does the decoding of the request, and since in the case of gethostbyname() you're just mapping from a string anyway, there is no more overhead.
Also, since it is a virtual file, memory writes and reads have to be done than during a funciton call. All this is what introduces the overhead.
nope. inferno system calls do not make any copies of the data unless they have to. i just had a look at the relevant code, and the pathway between a user program doing write() and the device getting that call probably about 20 to 30 machine instructions executed. there is no real overhead compared to the traditional syscall interface.
BUT what you do get is consistency across all device interfaces. because gethostbyname() is not just a system call, but is part of the namespace, i can export that down any data connection. so, say i've got a little handheld device that has no tcp/ip stack, no DNS, nothing apart from some sort of serial driver and the Styx driver (which is very small), then i can connect it up to my desktop PC, import the network devices + /net/cs from it, and bingo i've got what looks like direct access to the net. yes, i've now got to send those requests over the serial link now, but i can do something that i couldn't do otherwise without inventing my own, use once, limited purpose protocol...
that applies to all inferno devices. the fact that the interface is an abstract one does not necessarily mean that it's inefficient. if you're interested, have a look at the plan 9 code (login 9fan, password glenda) that does the same thing. i think you'll find that the path from user program to system call implementation code compares favourably with most *NIXen.
the file abstraction in inferno is a wonderful thing - if you're using it, it means you don't have to write a specialised protocol for every new network service - if a service is running locally, it's efficient; if it's running remotely, the protocol work is done for you.
had to respond to this, as i've recently finished writing the inferno shell. (unless that's anonymous coward chris, ya bugger, in which case i've just been trolled, sorry folks)
where else can you make a distributed app in one line of shell script? /dev/shellctl {} {somecommand ${unquote ${rget data}}} /dev/shellctl /dev/shellctl :-)
file2chan
that one line makes a file in the namespace - any write to that file runs somecommand with the arguments that have been written to the file. i.e. i can do:
echo ${quote arg1 'arg 2'} >
or even better:
fn somecommand {
echo ${quote $*} >
}
somecommand arg1 'arg 2'
and it'll run
somecommand arg1 'arg 2'
in the original process. the properties of the inferno namespace mean that i can then export that across the network transparently, encrypted, etc. corba eat your heart out.
i dunno whether you're talking about plan 9 or inferno there. plan 9's got a great gui - it just doesn't fit into how our microsoft-warped brains think a GUI should look like.
inferno however... well, the GUI does need a bit of looking at. and i am looking at it! i'm currently working on the window manager, which was written a few years ago in a weekend and hasn't changed much since.
but it's not a big job. applications aren't heavily tied into the look and feel of the GUI, which makes for less bloated apps. the main GUI is based on a variant of tk which means that the underlying GUI code can be changed in one place, and the whole feel of the thing changes. inferno hasn't had any hardcore graphics designers let loose on it, but if it did, believe me, it could look beautiful!
inferno isn't great because of its GUI, but because of what's underneath. look at the lego brick demo for a flavour of what can be done with devices under inferno.
we've got all the manual pages on line, so if you're interested in techie details about the system, you can see them here.
you can do with that what you want. if you want to hack the kernel, port it to a new platform, whatever, then, yes you have to pay your $300 and become a subscriber. but once one person has done that, they can distribute the kernel binaries with no hinderance, and due to the portable nature of inferno, all worked under it will still work under the new version.
if i wasn't involved in inferno development and was stuck under Windows of some description, then i'd get a copy, just for the environment. unix-like shells under NT are ok, but they don't give you that "my whole environment is pliable under my fingers" feel that having a complete environment does.
the beauty of inferno includes the fact that once you've got something in your namespace (and everything, including network connections, is accessed through the namespace) you can transparently export it through any type of datalink, with whatever sort of encryption/authentication you want, and use it as if it was local. i don't know any other system that provides that much flexibility for so little protocol overhead.
as far as performance goes, there's also the fact that there hasn't yet been a great deal of work done optimizing the compiler output or the JIT (i.e. currently the JIT does little registerisation, where the design of the DIS VM means that registerisation should be relatively easy to do - see this). i have a feeling that it's quite a lot faster than most java versions.
what's it good for? all sorts of things. it's a really clean environment to write programs in. where plan 9 is really clean in the namespace and the system interface, but still uses C as the application programming language, Inferno has all that, but uses Limbo as the language with Dis underneath.
the main advantage it gives you when writing programs is that your programs are unconditionally portable - if i've written a Limbo program to run on a screen phone (bare hardware, ARM SA1100) then, assuming enough memory, i have no doubts about it running perfectly on any other platform on which Inferno is supported.
that, coupled with the fact that limbo is a really, really nice language means that i don't want to develop for anything else. i started off as a C developer about 10 years ago, managed to escape Ingres (eugh) after a couple of years, hacked some Occam (which is a nice language, but somewhat limited in its type system), ended up in Objective-C under NeXTstep/Openstep/(macosX?). so i've hacked in a number of languages, and Limbo wins hands down.
why? it's difficult to say. it's a combination of many factors that all go to make up for a thoroughly enjoyable programming experience. i love C (not C++ though!) and it keeps the "power at your fingertips" feel that you get with C, but without pointers, with garbage collection, with complete type safety... perhaps the main feature is that when you read a Limbo program, you can actually tell what it's doing! (shock horror). all the names that are accessible to a fragment of code are easily findable. there's no overloading. the OO paradigm works entirely around aggregation - no inheritance whatsoever. the inbuilt types work really nicely - value types mean that in a multi-threaded environment, which Inferno/Limbo is, you are utterly certain that a value can't be changed underneath you).
what programs are for it? well, there's a web browser, but if you're running it hosted, then you'll probably have one anyway (that doesn't have to conform to the restriction of needing to run in 4MB). i've written what i think is a fairly cool programmable shell for it which is pretty small as well (main binary for it is 36K). i also wrote a passable version of Tetris (which is great 'cos now i can play the same version against people in the office running windows, linux, plan 9 and screenphones!), and i'm finishing off a pretty nice FIBS client. most of that stuff i did in my spare time. there's a version of Acme that's been ported, so you can see how the original compares to Wily.
how easily can you port programs from *NIX? (shouldn't that be *N[UI]X ? :-]) depends on what sort of program you're talking about. what inferno does *not* have (and this is the reason it's so small) is all the legacy stuff that *NIX has picked up over the years. this it has in common with plan 9. it does not have cursor addressing programs (although i wouldn't mind porting a decent vt100 emulator). it does not have termcap/terminfo/curses/ioctl/fcntl or sockets. so porting anything that relies on that stuff (e.g. emacs, slrn) won't be at all easy. BUT, straight C usually goes very nicely into Limbo. most of the standard unix command line programs (i.e. the ones that just munge stdin to stdout) go fine. The Limbo arithmetic expression syntax uses the same precedence rules as C, so all those nightmare mathematical equations are little problem (unless they've got dodgy type promotion going on, which you want to know about anyway).
the best thing about inferno is that it's a truly component oriented architecture. OO systems with inheritance don't give you that as there's too much interdependence between objects at different levels. Limbo modules under the dis VM really do work as plug & play s/w...
hope this helps!
the concurrent bits of alef (the nice bits) have been taken over by a C library, and Acme has been rewritten in C.
the real replacement for alef is Limbo, the language used in Inferno (itself an offshoot of plan 9); it takes many of the best ideas from alef, but the syntax isn't quite so C-like - it's much, much cleaner in lots of ways (e.g. garbage collection, no arbitrary pointers, very clean type system), built from the bottom up around dynamically loaded modules running on a virtual machine, but with all the power of plan 9-like namespaces underneath.
having been using almost exclusively for the last year or so, i'd hate to go back to anything else.
Inferno fits very nicely along with plan 9 - it's a highly lean machine that runs on really small systems (for instance, the executables are remarkably tiny - the binary for ls, for example is 2902 bytes, from 270 lines of source) and also runs hosted under NT, Linux, BSD, etc so at last you can get the power of acme, plumbing, plan 9 namespaces, and a unix-like command line from inside NT or w98, along with *genuinely* portable programs (unlike java, for instance, where everyone has their favourite incompatibility story)...
it's not available.... yet. but you can register if you're interested at wwww.vitanuova.com, and you never know what might happen...