Coding Horror

programming and human factors

Hazmat Placards and Icons

It's good to know that others share my weird fascination with signs. Ian Albert has a page dedicated to hazmat placards:

Hazmat placards

Ian created high quality, hand-traced PDFs for each placard. Now that's dedication. But he also offers this amusing warning:

Don't use these decoratively in a public place. When emergency workers see a hazmat placard they react accordingly. That is, after all, the purpose of hazmat placards. You could get in some real trouble if your house is burning down and they have to call in the bomb squad because you've got an "explosives" sign hanging somewhere.

I still think the software industry can learn a lot from studying pre-digital iconography.

Discussion

The Day Performance Didn't Matter Any More

OSNews published a nine-language performance roundup in early 2004. The results are summarized here:

intlongdoubletrigI/O
Visual C++9.618.86.43.510.548.8
Visual C#9.723.917.74.19.965.3
gcc C9.828.89.514.910.073.0
Visual Basic9.823.717.74.130.785.9
Visual J#9.623.917.54.235.190.4
Java 1.3.114.529.619.022.112.397.6
Java 1.4.29.320.26.557.110.1103.1
Python/Psyco29.7615.4100.413.110.5769.1
Python322.4891.9405.747.111.91679.0

It's not a very practical benchmark, but it does tell us a few things. It's no surprise that C++ is at the head of the pack. But the others aren't terribly far behind. What I find really interesting, though, is how most of the languages clump together in the middle. There's no significant performance difference between Java and .NET if you throw out the weirdly anomalous trig results.

However, there is one language definitely bringing up the rear – Python. That's because it's an interpreted language. This is explained in Code Complete:

Interpreted languages tend to exact significant performance penalties because they must process each programming-language instruction before creating and executing machine code. In the performance benchmarking I performed for this chapter and chapter 26, I observed these approximate relationships in performance among different languages:
Language Type of Language Execution Time Relative to C++
C++ Compiled 1:1
Visual Basic Compiled 1:1
C# Compiled 1:1
Java Byte code 1.5:1
PHP Interpreted > 100:1
Python Interpreted > 100:1

Clearly, the performance penalty for interpreted languages is extreme. How extreme? If you have to ask, you probably can't afford it.

One of the biggest stigmas for early Visual Basic developers was that our code wasn't compiled. It was interpreted. Interpreted executables were yet another reason so-called
"professional" developers didn't take VB seriously. It was too slow. This finally changed when we got compiled executables in 1997 with VB 5.

The most commonly used interpreted language today, however, is JavaScript. And JavaScript is the very backbone of Web 2.0. How is this feasible if JavaScript is a hundred times slower than Java? Consider this ancient 1996 JavaScript benchmark page
:

1996 2006
primes 0.15 0.02 8x
pgap 3.13 0.06 52x
sieve 5.05 0.02 252x
fib(20) 2.15 0.03 72x
tak 10.44 0.08 131x
mb100 8.4 0.2 42x

In ten years, JavaScript performance has improved a hundredfold. But so what, right? Computers get faster every year. Well, our computers are now so fast that – with very few exceptions – we don't care how much interpreted code costs any more.

What many pundits don't realize is that the viability of interpreted JavaScript for mainstream applications is a relatively recent development. Consider this JavaScript benchmark of "ridiculously long algorithms and looping statements". The top three results are all of 2003 vintage:

AMD 1900+ 1.6 GHz 12.25 sec
P4 Mobile 2.2 GHz 15.48 sec
P4 Celeron 1.4 GHz 17.43 sec

The slowest computer I own, a 1.2 GHz Pentium M laptop purchased in 2003, completes this test in 13.64 seconds. The one I'm currently typing on completes it in around 7 seconds. So even in the last three years, we've almost doubled the speed of JavaScript.

I don't expect this trend of doubling performance to continue. I think JavaScript is about as fast as it can get now without some kind of really advanced dynamic compilation scheme. If you browse the results of BenchJS, a more recent JavaScript test suite, I think you'll agree that they've plateaued. We might reduce that from 6 seconds to 4 seconds over the next two years, but that's minor compared to the 100x speedup we've already had.

Discussion

.NET Pet Shop 4

Vertigo Software's .NET Pet Shop 4.0 article just went live on MSDN.

It's Pet Shop! You know... our old pal, Pet Shop:

.NET versus J2EE Pet Store performance graph

However, unlike previous versions of Pet Shop, this version is not a benchmark comparison with Java. It's purely a showcase for ASP.NET 2.0 features and best practices when porting a site from ASP.NET 1.1.

The lineage of Pet Shop is a little hard to trace, but it goes something like this:

1.x ASP.NET 1.0 Direct port of Java Pet Store reference application.
2.x ASP.NET 1.1 Minor update for new ASP.NET 1.1 release.
3.x ASP.NET 1.1 Incorporates community feedback; improved architecture to better align with Microsoft Patterns & Practices recommendations.
4.x ASP.NET 2.0 Complete rewrite; no longer functionally equivalent to Java reference application.

Although Pet Shop was developed here at Vertigo over the last 8 months, I wasn't personally involved with Pet Shop in any capacity. We are definitely interested in your feedback, however. Dialog with the community is what drove Pet Shop 3.0 development. Alan created a public blog entry on the Vertigo Pet Shop blog soliciting comments; feel free to drop by and comment any time.

Discussion

Revisiting Edit and Continue

Edit and Continue, which shipped in Visual Studio 2005, is generally regarded as A Good Thing. It's pretty difficult to argue against the benefits of immediacy when debugging, but that isn't about to stop some people:

  • Frans Bouma
    People who grew up with assemblers, the gnu commandline C debugger and other terrible tools, know that debugging using a debugger is a last resort and also learned that debugging is not about using a debugger, but about understanding the difference between the sourcecode which should have been written and the sourcecode that is written. Edit and Continue doesn't help you with finding more bugs at a faster rate. You know what does? Design by contract like Eiffel has, pre/post conditions in the code and proper design by designing algorithms first on paper or in a design tool, not behind a keyboard with a code editor in front of you.
  • John Robbins
    Edit and continue is a bug-introducing machine. Why? Because you get to focusing on that one bug and twiddle the code to fix that one bug and introduce six more. When you're debugging, you're debugging, not editing. When you start editing, you need to stop to think and plan for the ramifications of those changes. To paraphase Dykstra: "Use of a debugger is an indication of sloppy thinking. Use of edit and continue is an indication of insanity!"
  • Sam Gentile
    Program logic should not be tested in the debugger. You are wasting your time and your company's time if you do so. The debugger is for intractable problems. It was John who taught me that lesson in his seminal Windows Debugging book - you shouldn't be in the debugger unless you have to be. Unit tests are the place to verify, refector and edit as you go; not the debugger.

While they raise some valid points, the underlying argument is essentially the same in all three cases: Edit and Continue should be removed because it's dangerous. And we're clearly too stupid to be trusted with a dangerous tool like edit and continue!

This reminds me of a similar scenario in video games. There are two types of video games:

  1. games that allow you to save your progress anywhere you like.
  2. games that only allow you to save your progress at specific points placed in the game by the developers.

If you are killed between saves, you have to go back to the last save.

Certain groups of hard-core gamers think "save anywhere" games are fatally flawed. Real men, they say, work their way through a level and earn the save point. They believe that games should remove the "save anywhere" option, lest we all become a bunch of spoiled, lazy gamers who can barely lift our thumbs.

But here's what drives me crazy: the hard-core gamers don't have to use save anywhere! If they're so hard-core, they should easily be able to resist the temptation to save their game. They can simply save at the beginning of a level, or confine themselves a few saves per level, or whatever. So when they say the "save anywhere" option should be removed, what they're really saying is, "everyone should play games the same way we do," and veiling it in some macho rhetoric to intimidate people into agreeing with them.

The comparison between game saves and edit and continue is fairly apt; either you can edit a program whenever you want-- even at a breakpoint in a debugger-- or you can only do it when the program is stopped. Clearly, offering both options is more flexible and inhibits no one.

However, there's a big difference between encouraging people to take challenges and forcing them to take challenges by removing flexibility from the product. Not everyone plays games for the same reasons you do. And not everyone writes code for the same reasons you do, either.

Discussion

Keeping Private Keys Private

After I posted the CodeProject article .NET Encryption Simplified, a reader asked this question in the comments:

I would like to know what your thoughts are on private key storage in applications. I believe the recommended practice is to use the DPAPI, but I have found this to be too cumbersome for practical use. I would like to encrypt certain aspects of my apps and even parts of my database, but without secure key storage it is pointless. Thoughts?

The class in that article is suitable for most encryption scenarios, but I was using it in a web service. That meant I had the luxury of keeping my private key on a different physical server. I had never even considered the problem of private key storage on the same machine!

At the risk of belaboring the obvious, asymmetric encryption hinges on keeping the public key public, and the private key private. This is a snap if you're doing cross-machine calls. You slap the private key on your server, and freely distribute the public key to clients. The private key is never transmitted over the network, so unless a disgruntled user manages to battle his way into your data center and physically access your server, you're secure. But if all the encryption work you're doing is on the local machine, then the private key and the public key are both stored somewhere on the local machine. How in the world do you keep the private key away from the prying eyes of the local user?

It seems like an insoluble problem to me, since users have complete physical control over their own machines. However, a user named "bigals" posted this helpful response in the comments:

First of all, convert your private key to a PKCS12 file, which is a nice little container for private keys. Then you have a few options for storing the private key:

  1. In your machine's key store.
    This is not as safe as the user store, as it can be accessed by any user if they have enough permissions.
  2. In the current user's key store.
    This is more secure than the machine store, because it's protected by windows ACL's. But it can play havok on you if passwords and permissions are changed for that particular user.
  3. In the registry.
    You can use ACL's to protect the registry key.
  4. On a smart card.
    • The CryptoAPI has native support for this.
    • Smart cards can be removed and secured.
    • The keys are never stored on the machine, so it is a very secure solution.

Remember, never store an instance of your keys or passwords in a string! The .NET GC does not clear these values very well, and they are visible in the string table memory for anyone to steal! .NET 2.0 has a new object called SecureString, which keeps strings in encrypted memory.

This is another reason why the user comments are the best part of a blog. A two-way dialog between author and reader is often the difference between good content and great content.

The only way to keep a private key truly private is to store it on a completely different machine. If you must store the private key on the same machine, some vulnerability is inevitable. You can only make it inconvenient for a user to find the private key through software protection. If you want to make it really difficult, you have to embed the private key in specialized hardware, like the Xbox 360 does.

Discussion