Virtualization and the Integrated Circuit: Looking ahead

November 3rd, 2007

This article is a written summary of a talk I gave at BarCamp LA #4, with some bugfixes. My presentation used a bunch of graphics swiped from google images since I was in a hurry, and I’d like to extend apologies/credit to my sources, all linked here: [highway barrier] [rc circuit] [resistor] [capacitor] [microcontroller] [grandparents] [moore’s law] [hanz/franz] [beos cortex]

Slideshow iconView the talk slides

Virtualization is a big deal these days; it’s in the news and there’s a lot of activity in the stock market surrounding the phenomenon. I want to briefly talk about ways I foresee virtualization being applied that are a bit more radical than how it’s generally being thought of today. In particular, I make the following claim:

Software applications are going to be increasingly built up from dozens of virtual machines per program.

To give some supporting evidence, I’ll relate an analogy with how problem-solving in electronics evolved over the past few decades.

A simple electronics problem

By degree, I’m an electrical engineer. And the kind of work that we used to be paid to do was that you’d have a mission like: “Make this highway construction barrier light blink every 3 seconds”:

A highway construction barrier with light.

How to solve it the E.E. way

To do this, you’re going to need a power source and a light. That’s a given. But electrical engineers can recognize the highway-barrier task as one of those problems that can be done with just 2 additional parts—a resistor and a capacitor. In fact, it’s a textbook case. So I’ll show you what that kind of problem looks like:

Textbook example of an RC circuit.

(taken from http://www.physics.byu.edu/faculty/berrondo/su442/ac.pdf)

Picking a resistor R and a capacitor C can give you the desired effect of a certain brightness and a certain amount of time between blinks. But it’s not like there’s a specific value of C which corresponds to “3 seconds”. And there’s not a value of R which matches “12,000V”. If you picked two components that satisfied your specification, you’d have to work the equations out again and replace both pieces if anything changed.

How to solve it the C.S. way

If you’re familiar with computer science, and someone told you to make a light blink periodically, your mind would probably jump to something like this:

const VOLTAGE_MAX = 12000;
const BLINK_PERIOD_SECONDS = 3;
const FLASH_TIME_MILLISECONDS = 500;
const UPDATE_INTERVAL = 100;
var lamp = HighwayBarrier.getLamp(this);
 
forever () {
   lamp.setVoltage(0);
   sleep_msec(
         BLINK_PERIOD_SECONDS * 1000 -
         FLASH_TIME_MILLISECONDS);
   lamp.setVoltage(VOLTAGE_MAX);
   sleep_msec(FLASH_TIME_MILLISECONDS);
}

I’m hand-waving here to say that these are functionally equivalent. The reality is a little too tied up with light & power to make this a “good” example. But it’s a simple and visceral way to see how digital signal processing (CS way) differs from analog circuit design (EE way).

Cost comparisons of the approaches

For the CS approach you’d you’d need some kind of compiler or interpreter. And you’d need a CPU to run that program. Typing “microcontroller” on Google Images I found this fellow as the first hit:

A twenty dollar microcontroller

Then I looked for a price on it and got $20.61. That’s a heavyweight unit for this humble task, and crazy expensive—but I’m going to run with it. By contrast, the EE way uses two parts that probably cost a few pennies. Let’s estimate 10 cents for the capacitor and 10 cents for the resistor. So off the cuff we might guess that the EE way is approximately 100 times cheaper per Highway Light manufactured.

Furthermore, integrated circuits that can run arbitrary programs are not built out of 2 parts, but rather millions of individual electronic components. So we see how grotesquely wasteful the CS way is. But let’s look at the big picture.

Looking at the bigger picture

It’s pretty obvious how the CS code works—and I didn’t even comment it. If I asked your grandparents to change it so that it would go to 13,000 volts instead of 12,000 volts… or to blink over a 10 second period instead of 3 seconds, they’d probably be able to point to the right lines. But who thinks their grandparents could make the necessary changes to the circuit?

Plus there’s flexibility with the microcontroller—if you decide you want the light to ramp up and ramp down in brightness instead of blip on briefly, it’s easy code to write. If you want there to be a special case where during daylight hours the lights turn off to save power, you can do that with an “if” statement. Though computer science is a deep and complex field in its own right… for things like this it takes a relatively trivial amount of education to do than analog circuit design. And modifying the program after the fact, once written by a competent programmer, can be extremely easy.

So even assuming a factor of 100 manufacturing cost difference—with an overkill microcontroller that can dance and sing (should your project ever get new requirements)—the $20 could pale in comparison to the labor charge difference.

Virtual machines are like Integrated Circuits

In the years during my EE degree and afterward, I watched analog circuit engineering become a niche discipline. In the meantime, the norm for hardware solutions is to use millions of electronic components to do a job that two or three well placed ones could do. This makes perfect sense—we know that a human time and ability to manage complexity doesn’t scale, but Moore’s Law has so far:

Moore's Law Graph

So now let’s start thinking of microprocessors as being like virtual machines. Then the parallel to resistors, capacitors, and inductors—the building blocks of analog circuits—would be lines of code. Just how a chip with a layout of components rivaling a large city was once seen as an overkill way of making a highway light blink… there are a lot of problems today that people wouldn’t even think of using a Virtual Machine for. It would be “crazy” and “wasteful”.

But I’m going to tell you my bet: software applications are going to be increasingly built up out of dozens of virtual machines per program. This will be due to a similar economy of scale to what happened with integrated circuits. So here are some radical ideas about those trends.

1. Porting and cross-platform libraries will die out

My hatred for porting comes partially from a deep-seated psychological issue of playing games like Pac-Man in the arcade as a kid, and then you’d buy the version for the Atari and it would look nothing like Pac-Man. So porting and I started out on the wrong foot, and my experiences with porting code have only reaffirmed my belief that you shouldn’t do it. Here’s a picture that makes me sad, a few of the first 60,000 google image hits for “Tetris Screenshot”:

Tetris Ports Screenshot

I really believe application developers are going to pick a platform, make their program really work on that particular platform, and ship it out to users with the expectation that they are going to run it in a virtual machine. When you run the application the details of the underlying OS will be hidden from you; it will already be configured.

I expect we’ll see virtual machine versions of programs catch on and replace the idea of installing the native versions within the next couple of years. An implication here is that we’ll be saying goodbye to things like the Windows and MacOS versions of the GIMP. People will learn and accept the idea that different applications have different “skins”, so if the program doesn’t look and act like their host OS they won’t be terribly concerned.

2. Operating systems that just do interfaces

We’re already seeing that some operating systems are succeeding based on their ability to have a nice user interface presentation. People are doing serious work on MacOS — using it basically as a glorified terminal. I can imagine that applications of the future will have a virtual machine in them which is for an OS specifically suited to the user interface needs of the application, while that OS may not actually run any of the program logic.

In other words, rather than using a GUI library and interfacing with a client, you’ll have a full blown OS whose sole purpose is to look snazzy. I think it will be a great place to see OSes that haven’t been gaining traction otherwise, perhaps a resurgence of things like BeOS and OS/2.

3. Libraries running in their own virtual machines

I’ve pushed the idea that many applications you install on your desktop will be running in virtual machines. That’s not outlandishly far off of what’s actually happening. But how about something crazier: would you ever use a string library that had its own daemons and filesystem? Perhaps even something esoteric, like QNX?

Where we once used libraries, or even a few lines of custom code…we will see a rise in the usage of whole entire operating systems. You might laugh at that, but as Hanz and Franz would say: “hear me now and believe me later”.

When performance and memory usage are less of a concern than security and the leveraging of human effort—you really might want to use heavily debugged and peer-reviewed systems that are maintained by a group that has standardized on a completely different platform from your project. It will be typical, if not expected, that your project will wire together virtual machines with all the casualness that people pipe together commands in the unix toolkit paradigm.

This is similar to how people are thinking with web services…taken to an extreme. There are already web apps that do their image manipulation, spell checking, or other bits of functionality by sending requests over TCP/IP to a web server and getting XML back. Web standards have been one force for untying people from using any particular operating system, and I think this will keep pushing on that. But you don’t need to invoke a network—and I think the most common case will be VM components that are run on the local machine as active libraries with access to the WAN disabled.

(Though if you wanted to, you’d sometimes log into it, and let it connect to the internet to update itself—all in its own sandbox.)

Further thoughts

These ideas push away from goals that we consider important today, like user interface consistency standards. We could have “Night of the Living Dead Operating Systems”, where a virtual machine running BeOS on the front end uses an OS/2 codebase to do its computational work, and packages it all up as if it were a “normal” application. This sounds really scary to some people—am I actually advocating this?

Well I’m not even saying that this is the way I think development should be done (besides the part about not wasting effort porting things!). One engineer I talked to sheepishly admitted he’d used a whole chip where basically a flip-flop would have sufficed… but it was easier to plug the part in, especially since he couldn’t predict what he might want that subsystem to do later. Similarly, with VMs, I think this convenience of using hardened elaborate components is going to pop up in all kinds of places we’d use two or three lines of carefully chosen code today.

Valid XHTML 1.0 Transitional

Day One of Mixing the “Ext-js” and “Yui” frameworks

October 30th, 2007

Note: most visitors to this page seem to be searching to find out why Firebug with the break all errors option detects an exception on obj.type. If that’s why you’re here, see the end of the article for edits that fix this problem.

I have seen the occasional attempt to build full windowing environments inside of a browser, and been only semi-impressed. After all, we do have mature remote desktop solutions like VNC. Why deal with the nightmare of browser inconsistencies when you can just set up a virtual machine of your choice, program to whatever hardened widget API you like, and let users control its screen through a terminal??

(That makes sense to me, and it will only make more sense as virtualization expands. For more on my thoughts, see the article “Virtualization and the Integrated Circuit”)

Putting this bias aside, I was somewhat inspired today by the Extjs Web Desktop Demonstration. Reading about the history of Extjs, I saw that it was conceived as an extension to the Yahoo User Interface Library. In fact, it could run on top of it and use its event model somehow. To test this claim, I got the idea to integrate the Yui Drag and Drop Groups Demo into the Extjs Web Desktop:

extjs_yui_combination

Despite my general ignorance from being on day one of meeting both of these frameworks, it sort of worked first try. I simply took the global variables out of the drag and drop demo page (slots, players, Event, DDM) and made them members of the created window object. I then substituted the HTML of the drag and drop space:

<div id="workarea">..blahblah...</div>

for the HTML that was in the default for blank windows in the Web Desktop sample:

<p>something useful would be in here</p>

The drag and drop worked as expected. But I use Firebug with the “Break on all Errors” option. And after gluing these two things together, clicking in the Extjs grid window causes a temporary halt in YUI’s connection-debug.js on line 240. It’s a little snip of code in _hasSubmitListener enclosed within a try/catch block, like so:

237
238
239
240
241
242
243
244
try
   {
   var obj = YAHOO.util.Event.getTarget(e);
   if(obj.type.toLowerCase() == 'submit') {
      YAHOO.util.Connect._submitElementValue = encodeURIComponent(obj.name) + "=" + encodeURIComponent(obj.value);
   }
}
catch(e) {}

What’s happening is that obj is div.x-grid3-cell-inner, which is an entity used by Extjs inside its grid. Yui somehow gets ahold of the click (how?), and finds the .type is undefined. This leads to an exception when toLowerCase() is called. Looking at the snippet I was puzzled… is the exception handling intentionally glossing over cases where the type isn’t defined? If that is the case, it would be much better to use a direct comparison with “undefined”:

if (obj.type != undefined)
   if (obj.type.toLowerCase() == 'submit') ...

If this situation isn’t supposed to happen, then the dereference of obj.type should be outside the try/catch block so that people who aren’t using Firebug with “Break on all Errors” will know they have a problem.

I posted about this to the YUI forum, and Thomas Sha (who works in the Yahoo platforms department) agreed that my change would be a good way to deal with it, at least until YUI 2.4.0 is released. So I made the following changes to yui / build / connection / connection-debug.js and yui / build / connection / connection.js :

237
238
239
240
241
242
243
244
/*try
   {*/
   var obj = YAHOO.util.Event.getTarget(e);
   if((obj.type != undefined) && (obj.type.toLowerCase() == 'submit')) {
      YAHOO.util.Connect._submitElementValue = encodeURIComponent(obj.name) + "=" + encodeURIComponent(obj.value);
   }
   /*}
   catch(e){}*/

In yui / build / connection-min.js, you should just replace the string:

try{var S=YAHOO.util.Event.getTarget(q);if(S.type.toLowerCase()=="submit"){YAHOO.util.Connect._submitElementValue=encodeURIComponent(S.name)+"="+encodeURIComponent(S.value);}}catch(q){}

with:

/*try{*/var S=YAHOO.util.Event.getTarget(q);if((S.type!=undefined)&&(S.type.toLowerCase()=="submit")){YAHOO.util.Connect._submitElementValue=encodeURIComponent(S.name)+"="+encodeURIComponent(S.value);}/*}catch(q){}*/

That seemed to take care of it, and the system no longer generates spurious breaks in Firebug. I had a working demo. Though there were issues with the scroll bars bleeding through the windows in Firefox on Mac, but that’s due to a Firefox bug:

extjs_firefox_scrollbar_bug

I’m sympathetic to the nastiness of the quirk but I feel like this is what such frameworks must have workarounds for—as they exist precisely to help us not worry about all the bugs in commonly deployed browsers. I managed to work around it using theming—which might give Firefox OS/X users some peace of mind.)

Valid XHTML 1.0 Transitional

Bribing developers to make their work free

October 20th, 2007

Some developers of closed-source/commercial software are holding onto the idea that a program they have written is going to make them a lot of money in the future. Yet by and large, many small software projects—even very good ones—will not ever make money if they are held on to tightly. Some do make a few hundred dollars a month, but it’s usually a fantasy to believe that it will make the developer rich and famous. This fantasy keeps them from sharing their source and possibly merging ideas with other similar codebases and generating something even better for the public.

One possibility would be to convince the developer of a piece of good software to hand over their work by giving them a lump sum. This sum may be less than the hoped-for long-term revenue in the dreams of the recipient, but sufficient to fund the hours of their hobby, and offset the loss of the residual income. This has happened on at least one instance I know about. For 100,000 euros, the makers of Blender were willing to transfer ownership of their project to the free software community rather than let the project disappear when the company went out of business.

Can more people be paid off? If so, one helpful tool would be a project called Fundable. It lets you pledge funds to a pool for a specific purpose—and then the funds you donate are only billed in the event that the total donation goal is reached.

Something that might help people be more willing to offer money would be if developers presented a reasoned rationale for why they needed it. Discussing one’s budget in an open way and putting it under the scrutiny of investors may not appeal to most independent developers. But the experiment has been conducted by at least one individual—Jason Rohrer—who has disclosed his personal expenses and concluded that it would take less than $1000 a month to allow him to pursue free software development full time.

It’s not clear that he has been successful in this, but it’s a brave idea. I do not personally use the software he develops and so I am hard pressed to determine if this represents a good value proposition compared to other efforts. But it’s a fascinating precedent that might make people more willing to donate to buy public rights to the code of a particular developer (especially if it’s on an ongoing basis where their commitment to doing further work can be assessed).

A database of “A is better than B” relationships

February 22nd, 2006

One of the key things that needs to be able to happen in order for open source projects to be aware of each other is some kind of database which the community can edit, linking related items together. The goal should be to help prevent someone from accidentally (or intentionally) obscuring the awareness of a competing effort. It could also be a tool for mitigating the effects of web scraping, by pointing to canonical versions of content direct from the author.

Wikipedia is actually serving this fairly well, and it’s one of the reasons why I tend to link to the Wikipedia page about products rather than (for instance) the download site or the corporate page. It may be true today that Ableton Live is the most outstanding audio software package on the market—but Ableton Inc. is unlikely to be linking to a formidable competitor’s homepage if that ever ceases to be the case. Users of Wikipedia have the opportunity to put in a “See Also” link.

Of course, search engines and review sites can do this—but often reviews are more stagnant than the corporate site. Still, something I tend to do when I’m investigating a new product or service is to type into a search engine the simple string “better than [PROGRAMNAME]”. This generates some possibilities to check out. But when I’m done, that information is lost, unless I write another review page.

This gave me the idea of creating something relatively simple—a small application which lets users express “A is better than B” relationships and upload those into a central database. Moreover, it would be able to track who holds those opinions and allow them to be lobbied to change their allegiances if new information comes to light. The concept is to create community pressure on the efforts that everyone thinks is inferior to (at minimum) place a notice on their web page informing visitors that there is another more popular option which is favored for particular reasons.

I imagine that the “better than” relationships could apply to nearly anything, though the intention is to compare things that are direct competitors. For instance, an MP3 file with a skip in it can be considered surpassed by an MP3 file that does not have a skip in it. By storing the Cryptographic Hashes of the items being compared (whether they be names of things or entire giant binary files) it would be possible to efficiently store these relationships in the database. A browser plugin would constantly hash downloaded content and URLs and give you tips when you were looking at something that had a better version.

The basics of this program is not necessarily difficult to write—but there are many details to be thought through in regards to the management of vandalous contributions or blatant falsehoods. A similar set of issues was brought up by the Mindpixel project—which was similarly trying to build up a repository of consensus knowledge using lots of tiny facts contributed and rated by various people.

In Defense of Hungarian Notation (with caveats)

September 24th, 2005

Anyone who has programmed directly to the Windows API knows about the existence of Hungarian Notation. It is a way of making the name of a variable or procedure flow automatically from its data type. Like other conventions that have been rejected by the general programming community, it would be foolish to use it today on any public API or code example. Despite this, I do still borrow from some of the “spirit” of the notation when I code.

I’d like to explain why.

Some critics (and adherents) of Hungarian Notation think its goal is to encode useful type information into names. The truth is, coming up with useful names is not the point. It is much more about avoiding the encoding of useless information!

Names—like indentation, spacing, and comments—do not affect the executable code. For instance, look at this code:

void DestroyTheWindow(HWND TheWindowIWillDestroy)
   // This function should only be called on windows which
   // have no parents; if you would like to destroy a
   // window which has a parent, then you must destroy 
   // the window through the parent. Failure to do so
   // will skip essential window layer cleanup routines
   // and a later crash may ensue.
   {
   ...
   }

No matter how nice the prose, that programmer spent their finite allocation of time on earth unwisely. Given the 30 seconds (at least!) it took them to write that comment, I’d rather they had written:

void DestroyWindow(HWND hwnd)
   {
   assert(GetParent(hwnd) == NULL);
   ...
   }

…or even better, invested that time in creating subclasses of HWND (like HWND_TOPLEVEL and HWND_CHILD) so that the error could be caught at compile-time:

void DestroyToplevel(HWND_TOPLEVEL hwnd)
   {
   ...
   }

Even if HWND_TOPLEVEL and HWND_CHILD are merely typedefs for HWND, I think this is better documentation than a comment in the long run. It conveys all the same information and can easily grow into a compiler-checked solution, if you were to upgrade the definitions from typedefs into distinct classes.

Before anyone revokes my programming license, I’m not saying people shouldn’t comment. Yet a programmer only has twenty-four hours in a day (disregarding sleep, of course)… and therefore any time invested in comments is energy that was not put into fixing the code so that comment wasn’t necessary. Naming is the same way—a creative name is something a user will not be able to appreciate in terms of runtime features.

So to bring our discussion back to the core of Hungarian Notation’s value for your programming mind, let’s look at the situation of someone naming a function parameter:

void DestroyWindow(HWND /*[name goes here]*/)
   {
   ...
   }

I could sit around all day debating whether to call it Input or ToBeDestroyedWindow or TheWindowIWillDestroy or cryptically x. Yet what this variable represents is obvious from the context—after all, it is the sole parameter to a routine called DestroyWindow. It’s the window to destroy (Duh!)

One way of avoiding a meaningless name would be to give the variable some unique number:

void DestroyWindow(HWND noname1231 /* hope this is unique! */)
   {
   ...
   }

In the future, our integrated development environments might be able to manage such numeric identities for declarations “behind the scenes”. This would be a lot like how databases invisibly manage table relationships through primary keys. But so long as we’re directly modifying textual code, humans can’t really match up these numbers while reading. So this is a bad idea.

But what if you made all your type names in capital letters? Then you could turn the type into lowercase letters to produce an available symbol:

void DestroyWindow(HWND hwnd)
   {
   ...
   }

Assuming that turning your type into lowercase doesn’t produce a language keyword, then you’ll always get a legal identifier. Moreover, the name isn’t completely useless: anywhere you see a reference to this “nameless” variable you know at least one thing about it: its type.

Naturally, this method of producing a unique symbol breaks down once you have more than one variable of a specific type in a scope:

HWND hwnd; // topmost window in the Z order
HWND hwnd; // parent window (**ERROR, NAME ALREADY USED**)

Yet if there’s more than one variable of the same type in a scope, that means that context alone is by definition insufficient to explain your variable’s purpose. Hungarian Notation prescribes adding a disambiguating mixed-case phrase to the end of the name. It is especially efficient, because the disambiguation always tacks onto the end of names—which is easy to add and remove in the editor if you ever run up against a collision:

HWND hwndTopmostInZOrder;
HWND hwndParent;

This only works if you create lots of new types. If you have an integer value, and you prefix a variable with the letter “i”, context is probably not sufficient to know what the variable is for. So that begs the question: why are you using an integer and not a higher level abstraction like “line number” (LINE), “count of employees” (CEMP), or a “stack depth counter” (SDC)?

If the Y2K problem taught us anything, it’s that you should be very liberal in creating new types which capture your ideas—even if it’s just a measly preprocessor macro. Compare:

BYTE todays_date_in_MM_DD_YY[3];

with:

#define DATE BYTE[3]
DATE date;

Even though the implementations are isomorphic, the second pattern is far better. There is no automatic way to find all the dates in the first example…you have to do manual inspection of all the names of BYTE arrays to figure out which are dates and which are not. This is why I don’t hesitate to create new types while I program, even wrappers for basic types like int or long. Once you’ve done that, you can feel good about variable declarations like LINE lineFirst; or CEMP cempHiredLastMonth; or just SDC sdc;.

If you aren’t making tons of types, and just sticking “i” or “l” in front of everything, forget about Hungarian. It will be useless, and makes what Linus Torvalds says absolutely true:

“Encoding the type of a function into the name (so-called Hungarian notation) is brain damaged - the compiler knows the types anyway and can check those, and it only confuses the programmer.”

I’m not surprised Hungarian Notation has a terrible reputation, because I’ve never seen published code that used it right. Microsoft even screwed it up in their most public APIs! Just look at the definition for window procedures:

long FAR PASCAL WndProc(
   HWND hwnd,
   UINT msg,
   UINT wParam,
   LONG lParam);

The only part they did right is the HWND. The rest is a complete mess. A more genuine attempt would probably look like:

typedef UINT WPARAM;
typedef LONG LPARAM;
typedef LONG LRESULT;
typedef UINT WM; // (W)indows (M)essage
 
LRESULT FAR PASCAL LresultWndproc(
   HWND hwnd,
   WM wm,
   WPARAM wparam,
   LPARAM lparam);

Some very reasonable people suggest that since so few programmers have grasped the “true” spirit of Hungarian Notation, something must be inherently confusing about it. Therefore nearly everyone should avoid it.

I mostly agree.

Yet I simply can’t stand being forced to give a meaningless name to something which is obvious from its context. That’s why I came up with a compromise. I simply make a mental association of a shorthand for each data type that I’m using (such as “WND” for System.Window) without changing the definition. This means code starts to look like:

void DestroyWindow(System.Window wnd)
   {
   System.Window wndParent = wnd.GetParent();
   System.Window wndTemp;
   foreach (wndTemp in wndParent.Children())
      {
      if (wndTemp == wnd)
         ...
      }
   }

This gives me what I desire, and avoids the taboo of data types that are in all capital letters. (I don’t know why, but people have reserved all caps for naming constants. It’s a convention that never made sense to me—mixed case constants are more readable. Oh well.)

One quirk I have adopted is to use “is” as the prefix for booleans. I still think it’s in the spirit of Hungarian, and boolean isTheUserOnline reads a bit better than boolean boolUserOnline. Here’s another example demonstrating my naming technique:

void KickUserOffline(UserObject userKick, UserObject userAdministrator)
   {
   assert(userAdministrator.HasPrivilege(PRIVILEGE_KICK));
   if (userKick.isTheUserOnline)
      {
      userKick.Message("You've been kicked off.");
      userKick.Logout();
      }
   }

I hope I’ve presented this clearly. The code examples that appear on HostileFork.com will use this technique where possible, and I welcome feedback if someone has a better way.


Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported