Coding Horror

programming and human factors

Speed Hashing

Hashes are a bit like fingerprints for data.

Fingerprint-as-hash

A given hash uniquely represents a file, or any arbitrary collection of data. At least in theory. This is a 128-bit MD5 hash you're looking at above, so it can represent at most 2128 unique items, or 340 trillion trillion trillion. In reality the usable space is substantially less; you can start seeing significant collisions once you've filled half the square root of the space, but the square root of an impossibly large number is still impossibly large.

Back in 2005, I wondered about the difference between a checksum and a hash. You can think of a checksum as a person's full name: Eubediah Q. Horsefeathers. It's a shortcut to uniqueness that's fast and simple, but easy to forge, because security isn't really the point of naming. You don't walk up to someone and demand their fingerprints to prove they are who they say they are. Names are just convenient disambiguators, a way of quickly determining who you're talking to for social reasons, not absolute proof of identity. There can certainly be multiple people in the world with the same name, and it wouldn't be too much trouble to legally change your name to match someone else's. But changing your fingerprint to match Eubediah's is another matter entirely; that should be impossible except in the movies.

Secure hashes are designed to be tamper-proof

A properly designed secure hash function changes its output radically with tiny single bit changes to the input data, even if those changes are malicious and intended to cheat the hash. Unfortunately, not all hashes were designed properly, and some, like MD5, are outright broken and should probably be reverted to checksums.

As we will explain below, the algorithm of Wang and Yu can be used to create files of arbitrary length that have identical MD5 hashes, and that differ only in 128 bytes somewhere in the middle of the file. Several people have used this technique to create pairs of interesting files with identical MD5 hashes:

  • Magnus Daum and Stefan Lucks have created two PostScript files with identical MD5 hash, of which one is a letter of recommendation, and the other is a security clearance.
  • Eduardo Diaz has described a scheme by which two programs could be packed into two archives with identical MD5 hash. A special "extractor" program turn one archive into a "good" program and the other into an "evil" one.
  • In 2007, Marc Stevens, Arjen K. Lenstra, and Benne de Weger used an improved version of Wang and Yu's attack known as the chosen prefix collision method to produce two executable files with the same MD5 hash, but different behaviors. Unlike the old method, where the two files could only differ in a few carefully chosen bits, the chosen prefix method allows two completely arbitrary files to have the same MD5 hash, by appending a few thousand bytes at the end of each file.
  • Didier Stevens used the evilize program (below) to create two different programs with the same Authenticode digital signature. Authenticode is Microsoft's code signing mechanism, and although it uses SHA1 by default, it still supports MD5.

If you could mimic another person's fingerprint or DNA at will, you could do some seriously evil stuff. MD5 is clearly compromised, and SHA-1 is not looking too great these days.

The good news is that hashing algorithms (assuming you didn't roll your own, God forbid) were designed by professional mathematicians and cryptographers who knew what they were doing. Just pick a hash of a newer vintage than MD5 (1991) and SHA-1 (1995), and you'll be fine – at least as far as collisions and uniqueness are concerned. But keep reading.

Secure hashes are designed to be slow

Speed of a checksum calculation is important, as checksums are generally working on data as it is being transmitted. If the checksum takes too long, it can affect your transfer speeds. If the checksum incurs significant CPU overhead, that means transferring data will also slow down or overload your PC. For example, imagine the sort of checksums that are used on video standards like DisplayPort, which can peak at 17.28 Gbit/sec.

But hashes aren't designed for speed. In fact, quite the opposite: hashes, when used for security, need to be slow. The faster you can calculate the hash, the more viable it is to use brute force to mount attacks. Unfortunately, "slow" in 1990 and 2000 terms may not be enough. The hashing algorithm designers may have anticipated predicted increases in CPU power via Moore's Law, but they almost certainly did not see the radical increases in GPU computing power coming.

How radical? Well, compare the results of CPU powered hashcat with the GPU powered oclHashcat when calculating MD5 hashes:

Radeon 79708213.6 M c/s
6-core AMD CPU52.9 M c/s

The GPU on a single modern video card produces over 150 times the number of hash calculations per second compared to a modern CPU. If Moore's Law anticipates a doubling of computing power every 18 months, that's like peeking 10 years into the future. Pretty amazing stuff, isn't it?

Hashes and passwords

Let's talk about passwords, since hashing and passwords are intimately related. Unless you're storing passwords incorrectly, you always store a user's password as a salted hash, never as plain text. Right? Right? This means if your database containing all those hashes is compromised or leaked, the users are still protected – nobody can figure out what their password actually is based on the hash stored in the database. Yes, there are of course dictionary attacks that can be surprisingly effective, but we can't protect users dead-set on using "monkey1" for their password from themselves. And anyway, the real solution to users choosing crappy passwords is not to make users remember ever more complicated and longer passwords, but to do away with passwords altogether.

This has one unfortunate ramification for password hashes: very few of them were designed with such massive and commonly available GPU horsepower in mind. Here are my results on my current PC, which has two ATI Radeon 7970 cards generating nearly 16000 M c/s with MD5. I used oclHashcat-lite with the full range of a common US keyboard – that is, including uppercase, lowercase, numbers, and all possible symbols:

all 6 character password MD5s47 seconds
all 7 character password MD5s1 hour, 14 minutes
all 8 character password MD5s~465 days
all 9 character password MD5sfuggedaboudit

The process scales nearly perfectly as you add GPUs, so you can cut the time in half by putting four video cards in one machine. It may sound crazy, but enthusiasts have been doing it since 2008. And you could cut it in half again by building another PC with four more video cards, splitting the attack space. (Keep going if you're either crazy, or working for the NSA.) Now we're down to a semi-reasonable 117 days to generate all 8 character MD5s. But perhaps this is a worst-case scenario, as a lot of passwords have no special characters. How about if we try the same thing using just uppercase, lowercase, and numbers?

all 6 character password MD5s3 seconds
all 7 character password MD5s4 minutes
all 8 character password MD5s4 hours
all 9 character password MD5s10 days
all 10 character password MD5s~625 days
all 11 character password MD5sfuggedaboudit

If you're curious about the worst case scenario, a 12 character all lowercase password is attainable in about 75 days on this PC. Try it yourself; here's the script I used:

set BIN=oclHashcat-lite64
set OPTS=--gpu-accel 200 --gpu-watchdog 0 --outfile-watch 0 --restore-timer 0 --pw-min 6 --pw-max 6 --custom-charset1 ?l?d?s?u
%BIN% %OPTS% --hash-type 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ?1?1?1?1?1?1?1?1?1?1?1?1?1

Just modify the pw-min, pw-max and the custom-charset as appropriate. Or, if you're too lazy to try it yourself, browse through the existing oclHashcat benchmarks others have run. This will also give you some idea how computationally expensive various known hashes are on GPUs relative to each other, such as:

MD523070.7 M/s
SHA-17973.8 M/s
SHA-2563110.2 M/s
SHA-512267.1 M/s
NTLM44035.3 M/s
DES185.1 M/s
WPA/WPA2348.0 k/s

What about rainbow tables?

Rainbow tables are huge pre-computed lists of hashes, trading off table lookups to massive amounts of disk space (and potentially memory) for raw calculation speed. They are now utterly and completely obsolete. Nobody who knows what they're doing would bother. They'd be wasting their time. I'll let Coda Hale explain:

Rainbow tables, despite their recent popularity as a subject of blog posts, have not aged gracefully. Implementations of password crackers can leverage the massive amount of parallelism available in GPUs, peaking at billions of candidate passwords a second. You can literally test all lowercase, alphabetic passwords which are ≤7 characters in less than 2 seconds. And you can now rent the hardware which makes this possible to the tune of less than $3/hour. For about $300/hour, you could crack around 500,000,000,000 candidate passwords a second.

Given this massive shift in the economics of cryptographic attacks, it simply doesn’t make sense for anyone to waste terabytes of disk space in the hope that their victim didn’t use a salt. It’s a lot easier to just crack the passwords. Even a “good” hashing scheme of SHA256(salt + password) is still completely vulnerable to these cheap and effective attacks.

But when I store passwords I use salts so none of this applies to me!

Hey, awesome, you're smart enough to not just use a hash, but also to salt the hash. Congratulations.

$saltedpassword = sha1(SALT . $password);

I know what you're thinking. "I can hide the salt, so the attacker won't know it!" You can certainly try. You could put the salt somewhere else, like in a different database, or put it in a configuration file, or in some hypothetically secure hardware that has additional layers of protection. In the event that an attacker obtains your database with the password hashes, but somehow has no access to or knowledge of the salt it's theoretically possible.

This will provide the illusion of security more than any actual security. Since you need both the salt and the choice of hash algorithm to generate the hash, and to check the hash, it's unlikely an attacker would have one but not the other. If you've been compromised to the point that an attacker has your password database, it's reasonable to assume they either have or can get your secret, hidden salt.

The first rule of security is to always assume and plan for the worst. Should you use a salt, ideally a random salt for each user? Sure, it's definitely a good practice, and at the very least it lets you disambiguate two users who have the same password. But these days, salts alone can no longer save you from a person willing to spend a few thousand dollars on video card hardware, and if you think they can, you're in trouble.

I'm too busy to read all this.

If you are a user:

Make sure all your passwords are 12 characters or more, ideally a lot more. I recommend adopting pass phrases, which are not only a lot easier to remember than passwords (if not type) but also ridiculously secure against brute forcing purely due to their length.

If you are a developer:

Use bcrypt or PBKDF2 exclusively to hash anything you need to be secure. These new hashes were specifically designed to be difficult to implement on GPUs. Do not use any other form of hash. Almost every other popular hashing scheme is vulnerable to brute forcing by arrays of commodity GPUs, which only get faster and more parallel and easier to program for every year.

[advertisement] Hiring developers? Post your open positions with Stack Overflow Careers and reach over 20MM awesome devs already on Stack Overflow. Create your satisfaction-guaranteed job listing today!
Discussion

Preserving The Internet... and Everything Else

In Preserving Our Digital Pre-History I nominated Jason Scott to be our generation's digital historian in residence. It looks like a few people must have agreed with me, because in March 2011, he officially became an archivist at the Internet Archive.

The-internet-archive

Jason recently invited me to visit the Internet Archive office in nearby San Francisco. The building alone is amazing; when you imagine the place where they store the entire freaking Internet, this enormous former Christian Science church seems … well, about right.

It's got a built in evangelical aura of mission, with new and old computer equipment strewn like religious totems throughout.

Internet-archive-and-jason-scott

Doesn't it look a bit like the place where we worship servers, with Jason Scott presiding over the invisible, omnipresent online flock? It's all that and so much more. Maybe the religious context is appropriate, because I always thought the Internet Archive's mission – to create a permanent copy of every Internet page ever created, as it existed at the time – was audacious bordering on impossible. You'd need to be a true believer to even consider the possibility.

The Internet Archive is about the only ally we have in the fight against pernicious and pervasive linkrot all over the Internet. When I go back and review old Coding Horror blog entries I wrote in 2007, it's astonishing just how many of the links in those posts are now, after five years, gone. I've lost count of all the times I've used the Wayback Machine to retrieve historical Internet pages I once linked to that are now permanently offline – pages that would have otherwise been lost forever.

The Internet Archive is a service so essential that its founding is bound to be looked back on with the fondness and respect that people now have for the public libraries seeded by Andrew Carnegie a century ago … Digitized information, especially on the Internet, has such rapid turnover these days that total loss is the norm. Civilization is developing severe amnesia as a result; indeed it may have become too amnesiac already to notice the problem properly. The Internet Archive is the beginning of a cure – the beginning of complete, detailed, accessible, searchable memory for society, and not just scholars this time, but everyone.

Stewart Brand

Without the Internet Archive, the Internet would have no memory. As the world's foremost expert on backups I cannot emphasize enough how significant the Internet Archive is to the world, to any average citizen of the Internet who needs to source an old hyperlink. Yes, maybe it is just the world's largest and most open hard drive, but nobody else is doing this important work that I know of.

Let's Archive Atoms, Too

While what I wrote above is in no way untrue, it is only a small part of the Internet Archive's mission today. Where I always thought of the Internet Archive as, well, an archive of the bits on the Internet, they have long since broadened the scope of their efforts to include stuff made of filthy, dirty, nasty atoms. Stuff that was never on the Internet in the first place.

The Internet Archive isn't merely archiving the Internet any more, they are attempting to archive everything.

All of this, in addition to boring mundane stuff like taking snapshots of the entire Internet every so often. That's going to take, uh … a lot of hard drives. I snapped a picture of a giant pile of 3 TB drives waiting to be installed in one of the storage rooms.

Lots-of-hard-drives

The Internet Archive is a big organization now, with 30 employees in the main San Francisco office you're seeing above, and 200 staff all over the world. With a mission of such overwhelming scope and scale, they're going to need all the help they can get.

The Internet Archive Needs You

The Internet Archive is a non-profit organization, so you could certainly donate money. If your company does charitable donations and cares at all about the Internet, or free online access to human knowledge, I'd strongly encourage them to donate to the Internet Archive as well. I made sure that Stack Exchange donated every year.

But more than money, what the Internet Archive needs these days is … your stuff. I'll let Jason explain exactly what he's looking for:

I'm trying to acquire as much in the way of obscure video, obscure magazines, unusual pamphlets and printed items of a computer nature or even of things like sci-fi, zines – anything that wouldn't normally find itself inside most libraries. Hence my computer magazines collection – tens of thousands of issues in there. I'd love to get my hands on more.

Also as mentioned, I love, love, love shareware CDs. Those are the most bang for the buck with regards to data and history that I want to get my hands on.

Being the obsessiveconscientious geeks that I know you are, I bet you have a collection of geeky stuff exactly like that somewhere in your home. If so, the best way you can help is to send it in as a contribution! Email jscott@archive.org about what you have, and if you're worried about rejection, don't be:

There's seriously nothing we don't want. I don't question. I take it in, I put it in items. I am voracious. Omnivorous. I don't say no.

The Internet Archive has an impossible mission on an immense scale. It is an unprecedented kind of open source archiving, not driven by Google or Microsoft or some other commercial entity with ulterior motives, but a non-profit organization motivated by nothing more than the obvious common good of building a massive digital Library of Alexandria to preserve our history for future generations. Let's do our part to help support the important work of the Internet Archive in whatever way we can.

[advertisement] Stack Overflow Careers matches the best developers (you!) with the best employers. You can search our job listings or create a profile and even let employers find you.
Discussion

Visualizing Code to Fail Faster

In What You Can't See You Can't Get I mentioned in passing how frustrated I was that the state of the art in code editors and IDE has advanced so little since 2003. A number of commenters pointed out the amazing Bret Victor talk Inventing on Principle. I hadn't seen this, but thanks for mentioning it, because I definitely should have. Maybe you haven't seen it either?

Bret Victor - Inventing on Principle from CUSEC on Vimeo.

It's a bit long at 54 minutes, but worth viewing in its entirety. What Bret shows here is indeed exactly the sort of thing we should be doing, but aren't.

In some ways we've actually regressed from my ancient Visual Basic 6.0 days, when you'd get dynamically notified about errors as you typed, not just when you compiled or ran unit tests. The idea that you should be able to type (or gesture, or speak) and immediately see the result of that change is simple, but extremely powerful. It's speed of iteration in the small. That's essentially the basis for my argument that showing markup and rendered output side-by-side, and dynamically updating them as you type, is vastly superior for learning and experimentation compared to any attempt at WYSIWYG.

But Bret goes further than that – why not show the effects of predicted changes, and change over time? Time is the missing element in a static display of code and rendered output; how do we show that?

Braid-jump-code

Again, watch the video because it's easier to see in action than it is to explain. But maybe you'd like to play with it yourself? That's sort of the point, isn't it? As I wrote in 2007:

I yearn for the day when web pages are regularly illustrated with the kind of beautiful, dynamic visualizations that Ben Fry creates.

That day, I'm happy to report, seems to have arrived. Bret's article, Up and Down the Ladder of Abstraction is extremely interactive in plain old boring HTML 5.

Interactive-ladder-abstraction

Yes, it's artsy, yes these are mostly toy projects, but this isn't entirely abstract art house visualization nonsense. Designing tools that let you make rapid changes, and see the effects of those changes as soon as possible can be transformative.

Paul realized that what we needed to be solved was not, in fact, human powered flight. That was a red-herring. The problem was the process itself, and along with it the blind pursuit of a goal without a deeper understanding how to tackle deeply difficult challenges. He came up with a new problem that he set out to solve: how can you build a plane that could be rebuilt in hours not months. And he did. He built a plane with Mylar, aluminum tubing, and wire.

The first airplane didn't work. It was too flimsy. But, because the problem he set out to solve was creating a plane he could fix in hours, he was able to quickly iterate. Sometimes he would fly three or four different planes in a single day. The rebuild, retest, relearn cycle went from months and years to hours and days.

Eighteen years had passed since Henry Kremer opened his wallet for his vision. Nobody could turn that vision into an airplane. Paul MacCready got involved and changed the understanding of the problem to be solved. Half a year later later, MacCready's Gossamer Condor flew 2,172 meters to win the prize. A bit over a year after that, the Gossamer Albatross flew across the channel.

Don't get me wrong, we're failing plenty fast with our existing tools. But I can't shake the feeling that we could we fail even faster if we optimized our IDEs and code editors to better visualize the effects of our changes in real time as we make them.

[advertisement] How are you showing off your awesome? Create a Stack Overflow Careers profile and show off all of your hard work from Stack Overflow, Github, and virtually every other coding site. Who knows, you might even get recruited for a great new position!
Discussion

The End of Pagination

What do you do when you have a lot of things to display to the user, far more than can possibly fit on the screen? Paginate, naturally.

Pagination-examples

There are plenty of other real world examples in this 2007 article, but I wouldn't bother. If you've seen one pagination scheme, you've seen them all. The state of art in pagination hasn't exactly changed much – or at all, really – in the last 5 years.

I can understand paginating when you have 10, 50, 100, maybe even a few hundred items. But once you have thousands of items to paginate, who the heck is visiting page 964 of 3810? What's the point of paginating so much information when there's a hard practical limit on how many items a human being can view and process in any reasonable amount of time?

Once you have thousands of items, you don't have a pagination problem. You have a search and filtering problem. Why are we presenting hundreds or thousands of items to the user? What does that achieve? In a perfect world, every search would result in a page with a single item: exactly the thing you were looking for.

U2-google

But perhaps you don't know exactly what you're looking for: maybe you want a variety of viewpoints and resources, or to compare a number of similar items. Fair enough. I have a difficult time imagining any scenario where presenting a hundred or so items wouldn't meet that goal. Even so, the items would naturally be presented in some logical order so the most suitable items are near the top.

Once we've chosen a suitable order and a subset of relevant items … do we really need pagination at all? What if we did some kind of endless pagination scheme, where we loaded more items into the view dynamically as the user reaches the bottom? Like so:

It isn't just oddball disemvowelled companies, either. Twitter's timeline and Google's image search use a similar endless pagination approach. Either the page loads more items automatically when you scroll down to the bottom, or there's an explicit "show more results" button.

Pagination is also friction. Ever been on a forum where you wished like hell the other people responding to the thread had read all four pages of it before typing their response? Well, maybe some of them would have if the next page buttons weren't so impossibly small, or better yet, not there at all because pagination was automatic and seamless. We should be actively removing friction where we want users to do more of something.

I'm not necessarily proposing that all traditional pagination be replaced with endless pagination. But we, as software developers, should avoid mindlessly generating a list of thousands upon thousands of possible items and paginating it as a lazy one-size-fits-all solution. This puts all the burden on the user to make sense of the items. Remember, we invented computers to make the user's life easier, not more difficult.

Once you've done that, there's a balance to be struck, as Google's research tells us:

User testing has taught us that searchers much prefer the view-all, single-page version of content over a component page containing only a portion of the same information with arbitrary page breaks.

Interestingly, the cases when users didn’t prefer the view-all page were correlated with high latency (e.g., when the view-all page took a while to load, say, because it contained many images). This makes sense because we know users are less satisfied with slow results. So while a view-all page is commonly desired, as a webmaster it’s important to balance this preference with the page’s load time and overall user experience.

Traditional pagination is not particularly user friendly, but endless pagination isn't without its own faults and pitfalls, either:

  • The scroll bar, the user's moral compass of "how much more is there?" doesn't work in endless pagination because it is effectively infinite. You'll need an alternate method of providing that crucial feedback, perhaps as a simple percent loaded text docked at the bottom of the page.
  • Endless pagination should not break deep linking. Even without the concept of a "page", users should be able to clearly and obviously link to any specific item in the list.
  • Clicking the browser forward or back button should preserve the user's position in the endless scrolling stream, perhaps using pushState.
  • Pagination may be a bad user experience, but it's essential for web spiders. Don't neglect to accommodate web search engines with a traditional paging scheme, too, or perhaps a Sitemap.
  • Provide visible feedback when you're dynamically loading new items in the list, so the user can tell that new items are coming, and their browser isn't hung – and that they haven't reached the bottom yet.
  • Remember that the user won't be able to reach the footer (or the header) any more, because items keep appearing as they scroll down in the river of endless content. So either move to static headers and footers, or perhaps use the explicit "load more" button instead of loading new content automatically.

For further reading, there's some excellent Q&A on the topic of pagination at ux.stackexchange.

Above all else, you should strive to make pagination irrelevant because the user never has to look at more than a few items to find what they need. That's why I suspect Google hasn't done much with this technique in their core search result pages; if they aren't providing great results on page 1, it doesn't really matter what kind of pagination they use because they're not going to be in business much longer. Take that lesson to heart: you should be worried most of all about presenting a relevant list of items to the user in a sensible order. Once you've got that licked, then and only then should you think about your pagination scheme.

[advertisement] What's your next career move? Stack Overflow Careers has the best job listings from great companies, whether you're looking for opportunities at a startup or Fortune 500. You can search our job listings or create a profile and let employers find you.
Discussion

What You Can't See You Can't Get

I suppose What You See Is What You Get has its place, but as an OCD addled programmer, I have a problem with WYSIWYG as a one size fits all solution. Whether it's invisible white space, or invisible formatting tags, it's been my experience that forcing people to work with invisible things they cannot directly control … inevitably backfires. A lot.

I have a distinctly Ghostbusters attitude to this problem.

Ghostbusters-logo

I need to see these invisible things, so that I can zap them with my proton pack. I mean, er, control them. And more importantly, understand them; perhaps even master them.

I recently had the great privilege of meeting Ted Nelson, who gave me an in-person demo of his ZigZag project and his perpetually in-progress since 1960 Xanadu project, currently known as Xanadu Space. But one thing he mentioned as he gave the demo particularly intrigued me. Being Ted Nelson, of course he went much further than my natural aversion to invisible, hidden markup in content – he insisted that markup and content should never be in the same document. Far more radical.

I want to discuss what I consider one of the worst mistakes of the current software world, embedded markup; which is, regrettably, the heart of such current standards as SGML and HTML. (There are many other embedded markup systems; an interesting one is RTF. But I will concentrate on the SGML-HTML theology because of its claims and fervor.)

There is no one reason this approach is wrong; I believe it is wrong in almost every respect.

I propose a three-layer model:

  1. A content layer to facilitate editing, content linking, and transclusion management.
  2. A structure layer, declarable separately. Users should be able to specify entities, connections and co-presence logic, defined independently of appearance or size or contents; as well as overlay correspondence, links, transclusions, and "hoses" for movable content.
  3. A special-effects-and-primping layer should allow the declaration of ever-so-many fonts, format blocks, fanfares, and whizbangs, and their assignment to what's in the content and structure layers.

It's an interesting, albeit extremely hand-wavy and complex, alternative. I'm unclear how you would keep the structure layer in sync with the content layer if someone is editing the content. I don't even know if there are any real world examples of this three layer approach in action. (And as usual, feel free to correct me in the comments if I've missed anything!)

Instead, what we do have are existing, traditional methods of intermixing content and markup ala HTML or TeX.

PDF vs. TeX

When editing, there are two possible interfaces:

  1. WYSIWYG where the markup layer is magically hidden so, at least in theory, the user doesn't ever have to know about markup and can focus entirely on the content. It is an illusion, but it is simple enough when it's working. The downside is that the abstraction – this idea that the markup is truly "invisible" – is rarely achieved in practice and often breaks down for anything except the most basic of documents. But it can be good enough in a lot of circumstances.

  2. Two windows where the markup is fully visible in one window, and shown as a live rendered preview in the other window, updated as you type, either side-by-side or top-and-bottom. Users have a dynamic sandbox where they can experiment and learn how markup and content interact in the real world, rather than having it all swept under the rug. Ultimately, this results in less confusion for intermediate and advanced users. That's why I'm particularly fond of this approach, and it is what we use on Stack Exchange. The downside is that it's a bit more complex, depending on whether or not you use humane markup, and it certainly takes a bit more screen space and thinking to process what's going on.

What I didn't realize is that there's actually a third editing option: keep the markup visible, and switch rapidly back and forth between the markup and rendered view with a single keystroke. That's what the Gliimpse project reveals:

Please watch the video. The nearly instantaneous and smooth transition that Gliimpse demonstrates between markup and preview has to be seen to be appreciated. The effect is a bit like Expose on the Mac, or Switcher on PC. I'm not sure how I feel about this, mainly because I don't know of any existing IDEs that even attempt to do anything remotely like it.

But I'd sure like to try it. As a software developer, it's incredibly frustrating to me that we have generational improvements in games like Skyrim and Battlefield 3 that render vastly detailed, dynamic worlds at 60 frames per second, yet our source code editors are advancing only in tiny incremental steps, year after year.

Discussion