The new owners of (one of the branches of) RISC OS has actually released it as shared source, available here if you're interested.
I'll agree that the overall design is very elegant, and the module system is nice, if rather primitive (relocatable code with no fixups! Aaaah!). But we know more about operating systems now, and a lot of Acorn's design decisions are no longer valid: for example, you actually get better performance from a preempting kernel than a cooperative one (because you can do work while other tasks are blocked on I/O).
Some of the misfeatures I found include:
OS_Heap is vastly more complex than it needs to be because it contains lots of code that scans through your stack looking to see whether you're calling OS_Heap reentrantly. Ew. Why? Because on RISC OS you're allowed to allocate memory inside interrupt handlers. Ew ew!
Virtual location 0x00000000 has to contain a mapped page. Why? Because there is one user accessible byte of kernel private data there, which most of Acorn's modules insist on referencing. This means you can't detect null pointer dereferences. (And the byte is specific to Acorn's RISC OS kernel. R2 doesn't use it, but it's still got to be there.)
There are about four different heaps available to modules --- all of which are used for much the same task, and all of which have different APIs. (Historical reasons.)
Two of the standard modules --- FileCore and MessageTrans, I think --- are mutually dependent. FileCore's startup calls MessageTrans, which calls back to FileCore. It only ever worked at all because both modules were preloaded in ROM. If, like R2, you build your module list dynamically at boot time you're in a world of pain.
A number of the APIs require you to pass in an address to a buffer, where the top 8 bits of the address contain flag bits. The kernel is at perfect liberty to hand you a buffer at an address greater than 0x00ffffff, and indeed, sometimes does.
That's off the top of my head, and that's omitting some of the plain style issues, such as APIs where the user has to pop a word from the stack before returning to invoke certain behaviour; the merry mixing of supervisor-mode and user-mode code (usually in the same code path. Did you know that supervisor-mode instructions on ARM are not guaranteed to be the same from one architecture to the next?); the bizarre maze of callbacks, service handlers, vectors, system control handlers, and environment handlers by which you get information back from the kernel...
Although, as you say, it did all work very well, although I did find my share of programs that would hang/crash/put the computer into some weird state. And it was impressive what it could do; this was all before the 386 had really hit the market.
But I don't think it's at all useful in today's world --- the big killer is that not having threads or processes or Posix it can't run any modern software. So no Chrome, although I note that some hero has managed to get Firefox 2.0.0.12 working on it.
Last year I put together a basic kernel reimplementation in portable C (as much as possible); interested parties may want to check it out. It was a pretty unpleasant job. While RISC OS looks elegant on the surface, inside it's a nasty maze of inconsistent APIs, duplicated APIs, APIs that require certain (unfriendly) implementations, APIs that should have been deprecated and haven't been, APIs that don't exist and should to avoid having to read the kernel private workspace, and most terrible of all, APIs that expose kernel implementation details. And, just to add insult to injury, most of RISC OS is written in hard-to-maintain machine code. (And the APIs are very unfriendly to C.)
Not to mention the fact that RISC OS is missing certain bits of functionality that everyone nowadays takes for granted: threads, preemptive multitasking, memory protection between processes, a GUI that can be driven from the keyboard...
Given how much of an overhaul it would need to be meet modern standards of functionality, it'd probably be easier just to start again from scratch with a proper OS design. I find myself rather intrigued by Prex, for example, which is a minimalist embedded operating system with hypervisor-like functionality and a Unixish system call interface. And, unlike RISC OS, it's BSD licensed.
Napster was awesome, and I regret its passing. There is nothing like it today.
The great thing about Napster was that it let me find new music that I liked. I'd see a reference to a song in, say, a book; I'd search for it on Napster, download the track, and play it; and then, if I liked it, I could go back to the same place and see what else the guy had. I discovered They Might Be Giants that way; I downloaded Rock To Wind A String Around from a recommendation, then went back and dug out more of their tracks, then ordered the Apollo 18 CD.
Okay, Napster was pretty slow and BitTorrent has it beat technically in pretty much every way, but no other music sharing service had the same sense of exploration and community. You could explore people's music collections, find interesting new rare stuff, and then actually talk to them about it (if they were on). It was, in fact, all social networking and Web 2.0-y before the terms had even been invented. I wish something like it existed today.
However, I'm not sure I agree that a language forcing you to structure your program in a certain way is a bad thing. If anything, the improved consistency helps the maintainability of a project. It also helps you keep a uniform mental model of the abstractions working in a program, and helps you compose distinct pieces with very little glue. It just takes some getting used to.
It's more than structure. It completely prevents you (subject to hacky workarounds) from using certain commonly-used design patterns.
What I was actually trying to implement was a DOM-like tree data structure, where the overall document object contains factory methods for creating nodes and manipulating the tree. However, for the factory to be able to refer to a node I need to define the node class before the factory class... but nodes also have to be able to refer to the factory, and to do that I have to define the factory before the node!
There are ways around this, the simplest of which is to abandon type safety and treat a node as a generic bag of properties which is only ever manipulated by the factory. But I don't want to do that, because it's a bad abstraction for my problem.
A while back I tried implementing a project in OCaml, because it looked awesome, and I wanted to explore it.
I found a lot to like about it; it's fast, reasonably clear, has got lots of awesome functional programming features that I actually found myself using while also having a powerful set of imperative programming features for the rest of the logic, and in general worked rather well.
However, I kept finding myself running again and again into problems caused by the same conceptual design issue, which eventually led to me giving up in frustration.
The problem was this: an OCaml program is structured as a series of statements, each of which mutates the program in some manner (usually by adding a definition to it). The last statement in the program typically invokes something (such as a 'main' function). The compiler ensures that your program is consistent after every statement. This means that you can't do forward declarations.
There is an and construct that allows you to define several items of the same kind in a single statement, which is typically used to implement mutually recursive functions, but that doesn't help if you need to items of different kinds to be mutually recursive: for example, a class and an algebraic data type (which I needed to do lots, in order to implement 'object or None' semantics).
I found this issue everywhere I looked in OCaml; the language semantics require your code dependency graph to be a tree with no cycles, and you have to structure your program strictly in bottom-up form. So not only can you not have two mutually dependent modules, you can't even put your 'main' at the top of the file for clarity.
Now, my OCaml skills aren't particularly great, so there may be a way round this, but I spent a lot of time looking for a solution to this and didn't find one. This, and other lesser issues to do with code style and namespacing, smell unpleasantly like an academic language that hasn't really learnt to scale gracefully, and I wonder whether it would be a comfortable choice for implementing large projects. These days I'd be inclined to consider Haskell or Clean instead.
Wow, thank you for that informative reply! I didn't realize the thing about the two chips with two different operating systems. So is there no open-source competitor for an OS like Nucleus? Since you say that it is deeply regulated, I assume not.
A lot of phones are like that. The G1 actually has between three and five processors (the documentation is unclear) --- an ARM11, an ARM9, either one or two OMAP DSPs, and a GPU that may or may not be programmable. The reason why it's done like that is the GSM or CDMA stack has really hard realtime requirements, and operating systems that are good at running application code (such as Linux or Windows Mobile) typically aren't as real time as is needed.
Lower end phones usually just have two processors: an ARM, usually, plus a DSP for audio handling. They usually run some embedded real-time operating system; I've seen Nucleus and L4, but I've also seen the most incredibly badly designed home-grown junk. (Misconfigured watchdog timers that watch the idle task! Threading functions that free() the stack you're currently running off! Semaphores with a hard-coded maximum number of blocked threads that's less than the number of threads on the system!)
There are open source real-time operating systems; eCos, FreeRTOS, Prex, various L4 variants... but given that the licensing fees alone are staggering, most people just license one that's known to work with whatever third party radio stack they're using and have done with it.
I was looking at a Chinese iphone knockoff, thinking that the hardware seems decent, but I wouldn't trust the knockoff operating system. With Android, though, the cheap knockoff can legally have the very same operating system, since they don't have to pay license fees.
Indeed; a lot of the Chinese family-industry phones are technically fascinating (and quite cheap). Having a real OS would make them much more attractive.
Unfortunately, it's not quite that easy --- remember that Android is designed for a two-chip system, where one processor runs the user apps (and is the one running Android), and another processor running a quite different operating system handles the GSM stack. On the G1, for example, there's a massive 20MB-or-so operating system image for the radio processor. This usually runs some embedded OS like Nucleus, and is highly proprietary, signed to be tamper-proof, and is deeply regulated; in most countries, tinkering with the radio image will cause your local telecommunications regulator to slap you round the face with lawsuits before you can blink.
I don't know where the Chinese knockoffs get their GSM stack but it's probably ripped off from a commercial product --- copyright doesn't mean much there. Which means they're probably not properly licensed by the GSM people, which means that it's very unlikely you'll be able to legally operate them in other countries. They may work, but that doesn't guarantee anything --- and if the device has a bug in its GSM stack which causes a local outage, you'll be in a world of legal pain.
I don't know if it's a holdover from my days as a boy scout or what, but I almost always have a backup, and a backup of the backup of anything critical to my survival. And if I ever get rich enough to own my own ocean-going vessel, *I* sure wouldn't put to sea without a sextant and the training to use it. And I'm just some not-a-professional-ship's-navigator schmuck.
Hell yeah. You never know when you're going to drop it / run the batteries down / lose it / sail into a mountain shadow and lose signal / get too close to a nuclear explosion and get EMPd.
Interestingly, recently sailing in my father's new yacht (a Hunter Liberty 23 twin masted ketch, lovely boat), when I wanted to know where we were in a hurry, my immediate reaction was to grab the hand-bearing compass and take a couple of bearings off nearby rocks. The whole process took about 20 seconds. I'd completely failed to notice the GPS hanging next to the compass.
A loud clatter of gunk music flooded through the Heart of Gold cabin as Zaphod searched the sub-etha radio wavebands for news of himself. The machine was rather difficult to operate. For years radios had been operated by means of pressing buttons and turning dials; then as the technology became more sophisticated the controls were made touch-sensitive --- you merely had to brush the panels with your fingers. Now all you had to do was wave your hand in the general direction of the components and hope. It saved a lot of muscular expenditure, of course, but meant that you had to sit infuriatingly still if you wanted to keep listening to the same programme.
Ninjas don't leave evidence nor any other trace...
But if Ninjas cannot be detected, then their existence can be neither proven nor disproven, right? Therefore whether Ninjas exist or not is purely an article of faith; there is no actual evidence (by definition, since the Ninjas removed it all).
...although --- the presence of Ninjas do form a intriguing hypothesis for the Dark Matter puzzle. Matter that is so undetectable that it can only be detected by its absence... it's all beginning to make sense now...
By His Noodly Appendage! The LHC --- they're trying to find the Ninja Particle! We must stop them, or else it'll flip out and kill everyone!
Just in case you're actually serious, I'd like to point out that those modern cars that get the same gas mileage as your 80s dream machines are much, much safer and have much, much better emissions.
My father's just bought a new car --- a diesel Nissan Note hatchback. He lives in Scotland and is two hours drive away from the nearest city; on his first trip there and back he got 76 mpg. He reckons that with care he should get above 80.
(That's not quite as good as it sounds; UK gallons are bigger than US gallons. That's 63 miles per US gallon.)
Our diesel prices are currently 4.68 pounds per UK gallon (5.74 dollars per US gallon), so he's getting about 6 pence per mile (9 cents). US diesel prices are around 2.30 dollars per US gallon (1.87 pounds per UK gallon). Our theoretical 35 miles per US gallon car engine therefore gets about 7 cents per mile (5 pence).
In other words, even though our fuel prices are two and a half times yours, his car stills costs about the same to drive as yours do...
(Assuming my arithmetic is correct, which it might not be. I'm horribly jet lagged and not tracking well.)
Also, I've been a Ford Fiesta owner for years. They're decent small cars. The hatchback shape is very convenient, the parts are easy to come by, they're cheap to run, and they're decent to drive.
Whoops! Indeed you're right. I misread it. (360 mph test run, 320 kph production runs.)
I wish we'd just hurry up and metricise...
It's still pretty damned fast though.
Also when I take the TGV to Paris from my hometown (2h5m), I need no check-in whatsoever, I just board the train a couple of seconds before it starts.
For me, the checkin is all at the Eurostar end in London. Presumably it's passport control, with a certain amount of that uniquely British talent for pointless beaurocracy.
These are routes where air travel is wasteful (2 hours in the airport waiting for a one hour flight) and rail competes very well.
I've just booked a rail ticket from London to Avignon for precisely this reason. That's about 700 miles, and involves about five hours of actual travel (plus an hour change in Paris; the direct trains start later in the year).
That's an average speed of 140 miles per hour. The slowest leg is the Eurostar, which has to go on the crappy British rail network, and the restricted-speed Channel Tunnel; the fast leg is on the French TGV, which can achieve 320 miles per hour in normal runs. Yes. You read that correctly. That's 3/4 the speed of a jet airliner.
Advantages include:
I can check in 30 to 45 minutes before flight. No need to spend all day at the frickin' airport.
Sane timetabling. I leave at about 1230 and get there at about 1800.
Sane security.
It goes from city centre to city centre. No need to travel to out-of-town airports.
Vastly more comfortable. Bigger seats, the ability to get up and walk around, proper food...
A decent view.
It's also about the same price: 144 UKP, return. The cheapest flight I found was Easyjet at about 100 UKP --- but that goes to Marseilles Airport, which is fifty miles away from Avignon!
The only reason for flying is that it is marginly faster. But only marginally. To me, that extra speed simply isn't worth the trouble.
I mean, come on, Beowulf ripped Grendel's arm off and nailed it above the door to the hall as a trophy.
Yes, but the whole effect was rather spoilt when Grendel's mother stormed down to the hall later to complain. I mean, his mother. What is this, kindergarten?
The only thing notable that a fawn ever did was watch its mom get killed by hunters.
The book's worth reading. Prior to disneyfication, Bambi kicks righteous ass when he grows up.
The bean-counters decided it was better to operate off a relatively fixed cost like fuel and have a dependable schedule. The whole story of the 20th century has been "Yeah, you could do this or that but it's just simpler and cheaper to use fossil fuels." Environmentalism won't drive alternative fuels, economics will. If it becomes cheaper to use sail, we'll go back to sail. The cost of fuel will only rise from this point, peak oil is here, so the economics we need for sail should be here now.
Go read Eric Newby's The Last Grain Race. It's a great book, but it's also relevant: it's the story of the author's trip round the world as a sailhand on the last commercial sailing fleet, in 1938.
His ship, the Moshulu, was one of a fleet of grain freighters that sailed from Europe to Australia, loaded grain there, and then sailed back again. They occupied a particular peculiar economic niche; being specialised sailing ships and technically quite simple, they had very fixed costs. As a result, it was feasible for them to stay in port in Australia for several months while small loads of grain trickled in from the farmers. Steamers were unable to do this, as they needed to be constantly trading to offset the fixed costs. Instead, they'd have to rely on warehousing, which would eat into profits.
It also helped that the Moshulu's owners didn't spend much on maintenance; some of Newby's descriptions are terrifying.
On Newby's trip, she made the voyage from Belfast, Ireland to Port Lincoln, Australia in 82 days, which is pretty good. She could do about 17 knots. Apparently she's now a restaurant ship in New York.
I've actually thought of that, and I want to look into LLVM anyway. Once I'd sorted out the actual concept, the actual code generator part of the project was very easy.
Generating good is rather harder. There are techniques for decomposing a basic block graph into conditionals and loops, but they don't work in all cases (and I think can be proved to not work in all cases); and without that you're still stuck with emulated goto in most languages, which is going to do horrible things to performance.
Unfortunately it wouldn't help the Flash/.NET situation because most of the work there is in the libraries. There are already perfectly decent Actionscript and.NET open source engines. It's just the stuff they need to plug into that's tricky...
Militant atheist Sam Harris, according to "The End of Faith" apparently wants to see humanity exterminated, religious and atheist alike, rather than allow religion to continue to exist, which comes over as "nutjob" to me.
Well, yeah; atheism is a religion. It's a religion based around belief in the absence of a god, rather than belief in the existence of a god, but it's still just a belief like any other. And as such, it's going to attract its fair share of fanatics and nutjobs just like any other religion.
"Dear persecution in the name of ideology, you are a pain in the ass. Please go away soon."
Personally, I quite like the fact that I live in a country that needs a four-colour diagram to adequately describe. It neatly fits in with my concept of how the world actually works.
May I assume that asking you "Have you tried compiling gotos into tail calls?" would make a stupid question?
Not at all, and I've done some benchmarks to see what sort of performance penalties there'd be doing that (see the Lua mailing list for details). The answer: not much, and Sparse' code generator framework actually lends itself quite well to that kind of structure.
However, it would need a custom code generator, and currently the Lua code generator shares code with the Perl5, Javascript, Java etc code generators, so it's rather more work than I'm willing to do right now. And it wouldn't be useful on any other language --- none of the other languages support tail calls, damn them.
It's a shame goto is so unfashionable; it's very rarely the right tool for the job, but on the few occasions when you need it you really need it...
Obviously good coding helps too but there is going to be some inherent latency because of the fact the Java code isn't compiled to machine code.
Actually, these days it is, especially on enterprise systems. The latest Java JITs are very, very good, and will emit machine code that rivals C and C++ for most tasks.
The biggest performance hit between Java and C is that Java programming styles involve more dynamic memory allocation than C does --- it's very common to allocate objects that will only be used a few times and then discarded. C doesn't, of course, but at the expense of significantly more complex code.
I have a pet project, Clue, which is a C compiler that will compile mostly standard C89 code into source code for dynamic languages like Javascript, Lua, Java, Perl5, etc. The code it produces is crap, but it's still an interesting toy. One of the backend targets is Java. When I do the benchmarks and compare my program, compiled from C into Java and then run on a decent JIT, I see that the Java version runs at 40% of the speed of a native version compiled with gcc.
Given the huge amount of overhead and the fact that Clue itself produces awful code --- Java doesn't support goto, so clue has to emulate them with a while loop around a switch statement! --- that is scarily good.
One day I want to replace Clue's compiler front end (currently based on Sparse) with a better one that generates Java bytecode directly and see what that does to the benchmarks.
One favourite is to add finally everywhere, making the code very rigid, believing this makes it faster.
I think you mean final here, no? finally does something else.
Don't.
Don't yet (experts only).
Very true.
I'd also add the additional rule: You don't know it's slow until you've benchmarked it. All too often I have seen, and I should add that I've perpetrated this myself, people spend ages painstakingly optimising parts of a system that felt like they were cause speed problems, when actually they weren't.
I once spent about two or three months designing and implementing a clever caching system for properties in a UI framework. It was subtle and complex, and I was very proud of it, and it was a total waste of time. We eventually threw it all away and stored the properties in an AVL tree. Yes, this involved looking up the properties in the inner loops of all the UI component redraw methods, but compared to the amount of work of touching every pixel on the screen, this was trivial. And it increased flexibility, reduced complexity and code size, and vastly improved maintainability.
The new owners of (one of the branches of) RISC OS has actually released it as shared source, available here if you're interested.
I'll agree that the overall design is very elegant, and the module system is nice, if rather primitive (relocatable code with no fixups! Aaaah!). But we know more about operating systems now, and a lot of Acorn's design decisions are no longer valid: for example, you actually get better performance from a preempting kernel than a cooperative one (because you can do work while other tasks are blocked on I/O).
Some of the misfeatures I found include:
That's off the top of my head, and that's omitting some of the plain style issues, such as APIs where the user has to pop a word from the stack before returning to invoke certain behaviour; the merry mixing of supervisor-mode and user-mode code (usually in the same code path. Did you know that supervisor-mode instructions on ARM are not guaranteed to be the same from one architecture to the next?); the bizarre maze of callbacks, service handlers, vectors, system control handlers, and environment handlers by which you get information back from the kernel...
Although, as you say, it did all work very well, although I did find my share of programs that would hang/crash/put the computer into some weird state. And it was impressive what it could do; this was all before the 386 had really hit the market.
But I don't think it's at all useful in today's world --- the big killer is that not having threads or processes or Posix it can't run any modern software. So no Chrome, although I note that some hero has managed to get Firefox 2.0.0.12 working on it.
Last year I put together a basic kernel reimplementation in portable C (as much as possible); interested parties may want to check it out. It was a pretty unpleasant job. While RISC OS looks elegant on the surface, inside it's a nasty maze of inconsistent APIs, duplicated APIs, APIs that require certain (unfriendly) implementations, APIs that should have been deprecated and haven't been, APIs that don't exist and should to avoid having to read the kernel private workspace, and most terrible of all, APIs that expose kernel implementation details. And, just to add insult to injury, most of RISC OS is written in hard-to-maintain machine code. (And the APIs are very unfriendly to C.)
Not to mention the fact that RISC OS is missing certain bits of functionality that everyone nowadays takes for granted: threads, preemptive multitasking, memory protection between processes, a GUI that can be driven from the keyboard...
Given how much of an overhaul it would need to be meet modern standards of functionality, it'd probably be easier just to start again from scratch with a proper OS design. I find myself rather intrigued by Prex, for example, which is a minimalist embedded operating system with hypervisor-like functionality and a Unixish system call interface. And, unlike RISC OS, it's BSD licensed.
Napster was awesome, and I regret its passing. There is nothing like it today.
The great thing about Napster was that it let me find new music that I liked. I'd see a reference to a song in, say, a book; I'd search for it on Napster, download the track, and play it; and then, if I liked it, I could go back to the same place and see what else the guy had. I discovered They Might Be Giants that way; I downloaded Rock To Wind A String Around from a recommendation, then went back and dug out more of their tracks, then ordered the Apollo 18 CD.
Okay, Napster was pretty slow and BitTorrent has it beat technically in pretty much every way, but no other music sharing service had the same sense of exploration and community. You could explore people's music collections, find interesting new rare stuff, and then actually talk to them about it (if they were on). It was, in fact, all social networking and Web 2.0-y before the terms had even been invented. I wish something like it existed today.
Your discussion of classes is confusing, as OCaml doesn't have them.
The OCaml documentation says otherwise...
However, I'm not sure I agree that a language forcing you to structure your program in a certain way is a bad thing. If anything, the improved consistency helps the maintainability of a project. It also helps you keep a uniform mental model of the abstractions working in a program, and helps you compose distinct pieces with very little glue. It just takes some getting used to.
It's more than structure. It completely prevents you (subject to hacky workarounds) from using certain commonly-used design patterns.
What I was actually trying to implement was a DOM-like tree data structure, where the overall document object contains factory methods for creating nodes and manipulating the tree. However, for the factory to be able to refer to a node I need to define the node class before the factory class... but nodes also have to be able to refer to the factory, and to do that I have to define the factory before the node!
There are ways around this, the simplest of which is to abandon type safety and treat a node as a generic bag of properties which is only ever manipulated by the factory. But I don't want to do that, because it's a bad abstraction for my problem.
A while back I tried implementing a project in OCaml, because it looked awesome, and I wanted to explore it.
I found a lot to like about it; it's fast, reasonably clear, has got lots of awesome functional programming features that I actually found myself using while also having a powerful set of imperative programming features for the rest of the logic, and in general worked rather well.
However, I kept finding myself running again and again into problems caused by the same conceptual design issue, which eventually led to me giving up in frustration.
The problem was this: an OCaml program is structured as a series of statements, each of which mutates the program in some manner (usually by adding a definition to it). The last statement in the program typically invokes something (such as a 'main' function). The compiler ensures that your program is consistent after every statement. This means that you can't do forward declarations.
There is an and construct that allows you to define several items of the same kind in a single statement, which is typically used to implement mutually recursive functions, but that doesn't help if you need to items of different kinds to be mutually recursive: for example, a class and an algebraic data type (which I needed to do lots, in order to implement 'object or None' semantics).
I found this issue everywhere I looked in OCaml; the language semantics require your code dependency graph to be a tree with no cycles, and you have to structure your program strictly in bottom-up form. So not only can you not have two mutually dependent modules, you can't even put your 'main' at the top of the file for clarity.
Now, my OCaml skills aren't particularly great, so there may be a way round this, but I spent a lot of time looking for a solution to this and didn't find one. This, and other lesser issues to do with code style and namespacing, smell unpleasantly like an academic language that hasn't really learnt to scale gracefully, and I wonder whether it would be a comfortable choice for implementing large projects. These days I'd be inclined to consider Haskell or Clean instead.
Wow, thank you for that informative reply! I didn't realize the thing about the two chips with two different operating systems. So is there no open-source competitor for an OS like Nucleus? Since you say that it is deeply regulated, I assume not.
A lot of phones are like that. The G1 actually has between three and five processors (the documentation is unclear) --- an ARM11, an ARM9, either one or two OMAP DSPs, and a GPU that may or may not be programmable. The reason why it's done like that is the GSM or CDMA stack has really hard realtime requirements, and operating systems that are good at running application code (such as Linux or Windows Mobile) typically aren't as real time as is needed.
Lower end phones usually just have two processors: an ARM, usually, plus a DSP for audio handling. They usually run some embedded real-time operating system; I've seen Nucleus and L4, but I've also seen the most incredibly badly designed home-grown junk. (Misconfigured watchdog timers that watch the idle task! Threading functions that free() the stack you're currently running off! Semaphores with a hard-coded maximum number of blocked threads that's less than the number of threads on the system!)
There are open source real-time operating systems; eCos, FreeRTOS, Prex, various L4 variants... but given that the licensing fees alone are staggering, most people just license one that's known to work with whatever third party radio stack they're using and have done with it.
I was looking at a Chinese iphone knockoff, thinking that the hardware seems decent, but I wouldn't trust the knockoff operating system. With Android, though, the cheap knockoff can legally have the very same operating system, since they don't have to pay license fees.
Indeed; a lot of the Chinese family-industry phones are technically fascinating (and quite cheap). Having a real OS would make them much more attractive.
Unfortunately, it's not quite that easy --- remember that Android is designed for a two-chip system, where one processor runs the user apps (and is the one running Android), and another processor running a quite different operating system handles the GSM stack. On the G1, for example, there's a massive 20MB-or-so operating system image for the radio processor. This usually runs some embedded OS like Nucleus, and is highly proprietary, signed to be tamper-proof, and is deeply regulated; in most countries, tinkering with the radio image will cause your local telecommunications regulator to slap you round the face with lawsuits before you can blink.
I don't know where the Chinese knockoffs get their GSM stack but it's probably ripped off from a commercial product --- copyright doesn't mean much there. Which means they're probably not properly licensed by the GSM people, which means that it's very unlikely you'll be able to legally operate them in other countries. They may work, but that doesn't guarantee anything --- and if the device has a bug in its GSM stack which causes a local outage, you'll be in a world of legal pain.
Hell yeah. You never know when you're going to drop it / run the batteries down / lose it / sail into a mountain shadow and lose signal / get too close to a nuclear explosion and get EMPd.
Interestingly, recently sailing in my father's new yacht (a Hunter Liberty 23 twin masted ketch, lovely boat), when I wanted to know where we were in a hurry, my immediate reaction was to grab the hand-bearing compass and take a couple of bearings off nearby rocks. The whole process took about 20 seconds. I'd completely failed to notice the GPS hanging next to the compass.
The compass, BTW, floats. The GPS doesn't.
The master said it first:
But if Ninjas cannot be detected, then their existence can be neither proven nor disproven, right? Therefore whether Ninjas exist or not is purely an article of faith; there is no actual evidence (by definition, since the Ninjas removed it all).
...although --- the presence of Ninjas do form a intriguing hypothesis for the Dark Matter puzzle. Matter that is so undetectable that it can only be detected by its absence... it's all beginning to make sense now...
By His Noodly Appendage! The LHC --- they're trying to find the Ninja Particle! We must stop them, or else it'll flip out and kill everyone!
Have you ever read any Greek mythology?
My father's just bought a new car --- a diesel Nissan Note hatchback. He lives in Scotland and is two hours drive away from the nearest city; on his first trip there and back he got 76 mpg. He reckons that with care he should get above 80.
(That's not quite as good as it sounds; UK gallons are bigger than US gallons. That's 63 miles per US gallon.)
Our diesel prices are currently 4.68 pounds per UK gallon (5.74 dollars per US gallon), so he's getting about 6 pence per mile (9 cents). US diesel prices are around 2.30 dollars per US gallon (1.87 pounds per UK gallon). Our theoretical 35 miles per US gallon car engine therefore gets about 7 cents per mile (5 pence).
In other words, even though our fuel prices are two and a half times yours, his car stills costs about the same to drive as yours do...
(Assuming my arithmetic is correct, which it might not be. I'm horribly jet lagged and not tracking well.)
Also, I've been a Ford Fiesta owner for years. They're decent small cars. The hatchback shape is very convenient, the parts are easy to come by, they're cheap to run, and they're decent to drive.
Whoops! Indeed you're right. I misread it. (360 mph test run, 320 kph production runs.) I wish we'd just hurry up and metricise...
It's still pretty damned fast though.
For me, the checkin is all at the Eurostar end in London. Presumably it's passport control, with a certain amount of that uniquely British talent for pointless beaurocracy.
These are routes where air travel is wasteful (2 hours in the airport waiting for a one hour flight) and rail competes very well.
I've just booked a rail ticket from London to Avignon for precisely this reason. That's about 700 miles, and involves about five hours of actual travel (plus an hour change in Paris; the direct trains start later in the year).
That's an average speed of 140 miles per hour. The slowest leg is the Eurostar, which has to go on the crappy British rail network, and the restricted-speed Channel Tunnel; the fast leg is on the French TGV, which can achieve 320 miles per hour in normal runs. Yes. You read that correctly. That's 3/4 the speed of a jet airliner.
Advantages include:
It's also about the same price: 144 UKP, return. The cheapest flight I found was Easyjet at about 100 UKP --- but that goes to Marseilles Airport, which is fifty miles away from Avignon!
The only reason for flying is that it is marginly faster. But only marginally. To me, that extra speed simply isn't worth the trouble.
Plus, of course, the TGV is just so cool...
I mean, come on, Beowulf ripped Grendel's arm off and nailed it above the door to the hall as a trophy.
Yes, but the whole effect was rather spoilt when Grendel's mother stormed down to the hall later to complain. I mean, his mother. What is this, kindergarten?
The only thing notable that a fawn ever did was watch its mom get killed by hunters.
The book's worth reading. Prior to disneyfication, Bambi kicks righteous ass when he grows up.
It's not hard to come up with acronyms.
You mean, a contrived reduction of nomenclature, yielding mnemonics?
The bean-counters decided it was better to operate off a relatively fixed cost like fuel and have a dependable schedule. The whole story of the 20th century has been "Yeah, you could do this or that but it's just simpler and cheaper to use fossil fuels." Environmentalism won't drive alternative fuels, economics will. If it becomes cheaper to use sail, we'll go back to sail. The cost of fuel will only rise from this point, peak oil is here, so the economics we need for sail should be here now.
Go read Eric Newby's The Last Grain Race. It's a great book, but it's also relevant: it's the story of the author's trip round the world as a sailhand on the last commercial sailing fleet, in 1938.
His ship, the Moshulu , was one of a fleet of grain freighters that sailed from Europe to Australia, loaded grain there, and then sailed back again. They occupied a particular peculiar economic niche; being specialised sailing ships and technically quite simple, they had very fixed costs. As a result, it was feasible for them to stay in port in Australia for several months while small loads of grain trickled in from the farmers. Steamers were unable to do this, as they needed to be constantly trading to offset the fixed costs. Instead, they'd have to rely on warehousing, which would eat into profits.
It also helped that the Moshulu's owners didn't spend much on maintenance; some of Newby's descriptions are terrifying.
On Newby's trip, she made the voyage from Belfast, Ireland to Port Lincoln, Australia in 82 days, which is pretty good. She could do about 17 knots. Apparently she's now a restaurant ship in New York.
Read his book --- it's fantastic.
I've actually thought of that, and I want to look into LLVM anyway. Once I'd sorted out the actual concept, the actual code generator part of the project was very easy.
Generating good is rather harder. There are techniques for decomposing a basic block graph into conditionals and loops, but they don't work in all cases (and I think can be proved to not work in all cases); and without that you're still stuck with emulated goto in most languages, which is going to do horrible things to performance.
Unfortunately it wouldn't help the Flash/.NET situation because most of the work there is in the libraries. There are already perfectly decent Actionscript and .NET open source engines. It's just the stuff they need to plug into that's tricky...
Militant atheist Sam Harris, according to "The End of Faith" apparently wants to see humanity exterminated, religious and atheist alike, rather than allow religion to continue to exist, which comes over as "nutjob" to me.
Well, yeah; atheism is a religion. It's a religion based around belief in the absence of a god, rather than belief in the existence of a god, but it's still just a belief like any other. And as such, it's going to attract its fair share of fanatics and nutjobs just like any other religion.
"Dear persecution in the name of ideology, you are a pain in the ass. Please go away soon."
Hear, hear.
The Great British Venn Diagram
Personally, I quite like the fact that I live in a country that needs a four-colour diagram to adequately describe. It neatly fits in with my concept of how the world actually works.
Of course. This is why the Scottish, the Irish and the Welsh are slowly but surely taking control of the United Kingdom.
Don't believe me? The last two prime ministers were Scottish.
May I assume that asking you "Have you tried compiling gotos into tail calls?" would make a stupid question?
Not at all, and I've done some benchmarks to see what sort of performance penalties there'd be doing that (see the Lua mailing list for details). The answer: not much, and Sparse' code generator framework actually lends itself quite well to that kind of structure.
However, it would need a custom code generator, and currently the Lua code generator shares code with the Perl5, Javascript, Java etc code generators, so it's rather more work than I'm willing to do right now. And it wouldn't be useful on any other language --- none of the other languages support tail calls, damn them.
It's a shame goto is so unfashionable; it's very rarely the right tool for the job, but on the few occasions when you need it you really need it...
Actually, these days it is, especially on enterprise systems. The latest Java JITs are very, very good, and will emit machine code that rivals C and C++ for most tasks.
The biggest performance hit between Java and C is that Java programming styles involve more dynamic memory allocation than C does --- it's very common to allocate objects that will only be used a few times and then discarded. C doesn't, of course, but at the expense of significantly more complex code.
I have a pet project, Clue, which is a C compiler that will compile mostly standard C89 code into source code for dynamic languages like Javascript, Lua, Java, Perl5, etc. The code it produces is crap, but it's still an interesting toy. One of the backend targets is Java. When I do the benchmarks and compare my program, compiled from C into Java and then run on a decent JIT, I see that the Java version runs at 40% of the speed of a native version compiled with gcc.
Given the huge amount of overhead and the fact that Clue itself produces awful code --- Java doesn't support goto, so clue has to emulate them with a while loop around a switch statement! --- that is scarily good.
One day I want to replace Clue's compiler front end (currently based on Sparse) with a better one that generates Java bytecode directly and see what that does to the benchmarks.
I think you mean final here, no? finally does something else.
Very true.
I'd also add the additional rule: You don't know it's slow until you've benchmarked it. All too often I have seen, and I should add that I've perpetrated this myself, people spend ages painstakingly optimising parts of a system that felt like they were cause speed problems, when actually they weren't.
I once spent about two or three months designing and implementing a clever caching system for properties in a UI framework. It was subtle and complex, and I was very proud of it, and it was a total waste of time. We eventually threw it all away and stored the properties in an AVL tree. Yes, this involved looking up the properties in the inner loops of all the UI component redraw methods, but compared to the amount of work of touching every pixel on the screen, this was trivial. And it increased flexibility, reduced complexity and code size, and vastly improved maintainability.