tag:blogger.com,1999:blog-78986152024-03-07T10:56:10.283-05:00Recording ArtistDrew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.comBlogger53125tag:blogger.com,1999:blog-7898615.post-64855222509952619032011-04-20T16:48:00.001-04:002011-04-20T16:50:15.762-04:00Optimization Goals<p>In my day job, I've worked with many different teams of programmers. Game engine, game tools, OS, SDK, middleware, test engineers, you name it. Many of the people I work with are the best in the industry, true world-class programmers. And others, well, aren't... and that's okay too. :-)</p>
<p>Personally, I find that I've learned a ton from interacting with all of these different groups.</p>
<p>One of the most important lessons I've learned — and I'm frankly surprised this isn't more widely talked about — is that there are many different <b>and equally valid</b> possible optimization goals in programming.</p>
<p>When I talk to a new team, that's often the first thing I try to find out: what are your primary goals? What are you looking for?</p>
<p>The most common definition of optimization involves improving the <b>runtime speed</b> of the code. For example, game engine programmers are often very focused on this, because they have to cram as much work as they can into one frame — generally either 1/30th of a second (33.3ms) or 1/60th of a second (16.6ms). Naturally, this leads to a lot of counting cycles and downcoding inner loops into assembly.</p>
<p>However, game tool programmers tend to be a little more willing to sacrifice speed in favor of optimizing for other goals: <b>development time</b>, <b>correctness</b>, and <b>ease-of-use</b>. For example, it's often OK to use an unoptimized implementation of some algorithm in a tool, since a high-end PC will run it "fast enough". In other cases a tool might only run infrequently or overnight. Or it might be feasible to simply throw more hardware at the problem.</p>
<p>You also see it among different teams: a studio making a AAA game might be very focused on optimizing <b>runtime speed</b>, while a small indie team might be focused on optimizing for <b>development cost</b> — doing the work as cheaply as possible. These teams will have very different optimization goals, to the point that what the AAA game has downcoded to assembly might be C++ objects and STL in the other.</p>
<p>Then there are the sports games — which live in a fascinating alternate world all their own. These guys have to iterate and ship a new version once a year, every single year! Slipping is simply not an option, so they tend to optimize first for <b>reliability</b>, <b>upgradeability</b>, and <b>ease-of-maintenance</b>.</p>
<p>This got me thinking: what are all the possible optimization goals you might have?</p>
<h3>Possible Optimization Goals</h3>
<p>Here are some things that you may choose to optimize for in your development. It's impossible to optimize for <i>all</i> of these things simultaneously, but it's common to target more than one.</p>
<ul>
<li><b>runtime speed</b> - <i>Run as fast as possible on your target system.</i> Most of the optimization literature focuses on this. It involves choosing algorithms carefully, choosing your data layout carefully, looking for early exit opportunities, hand-optimizing inner loops, and so on.<br/><br/></li>
<li><b>development time</b> - <i>Complete the engineering work as <b>quickly</b> as possible.</i> In other words, finish the job in a day or a week, rather than a month. Optimizing for development time may mean that you use the highest-level language available that will do the job, along with whatever third-party frameworks you can pull in to solve the problems you need solved. C#, Python, Ruby, etc.<br/><br/></li>
<li><b>development cost</b> - <i>Complete the engineering work as <b>cheaply</b> as possible.</i> This is closely related to development time, but slightly different! The primary difference is the choice of who is doing the work: it might be cheaper (and a better investment) to have an intern use a task as a learning project and work on it for three months, than to have a senior programmer crank it out in three weeks.<br/><br/></li>
<li><b>correctness</b> - <i>Be absolutely sure there are no mistakes or bugs.</i> Bug-free code is always a goal, of course, but sometimes it's even more important than usual. There are two common situations I can think of where correctness is your primary goal: (1) when creating a reference implementation of an algorithm, for possible later optimization. (2) when you're making important architectural decisions based on the results of some investigation or other; you'll generally double- and triple-check the investigation, if you're smart.<br/><br/></li>
<li><b>ease-of-use</b> - <i>Make sure users can grasp your interface quickly and achieve what they need to do.</i> Funnily enough, this applies to both applications (user interfaces) and to middleware (developer interfaces). In both cases, you need to understand how people will expect to use the product. The fastest or easiest way to do things might not be the most understandable.<br/><br/></li>
<li><b>ease-of-maintenance</b> - <i>Make the code so straightforward a monkey could maintain it.</i> Or you, in a few years. ;-) If you've ever had to go back and bug-fix some code that you (or god help you, someone else) wrote more than five years ago, you'll appreciate the value of this. Code that is well-written, easy to read, well-commented, and shaped well to fit the problem is code that is optimized for ease of maintenance. To some extent, this goal can be a cause of "not-invented-here" syndrome; the preference for in-house code is often born from a perfectly rational and reasonable desire to know how to maintain that code.<br/><br/></li>
<li><b>reliability</b> - <i>Never fail.</i> Keep on going in the face of problems. At runtime, if the program gets unexpected input, don't crash: flag it, log it, and continue on with a sensible fallback behavior. At development time, always have a reference implementation to fall back to if the optimized version isn't working. In the extreme, reliability might require a reduction (hopefully small) in average-case performance just to ensure that the code can reliably handle uncommon edge cases. (LibC's <tt>memset</tt> and <tt>memcpy</tt> are examples of that.)<br/><br/></li>
<li><b>upgradeability</b> - <i>Make sure every subsystem can be upgraded.</i> This is most commonly achieved with modularity. Good module separation should mean that individual pieces can be swapped out without too much trouble. If you remove modularity in order to run faster with today's situation, then you may be unable to upgrade to handle tomorrow's situation without a full rewrite.<br/><br/></li>
<li><b>iteration time</b> - <i>Minimize the time difference between when you make a change and when you are able to view and test the result.</i> This covers a lot of ground and may include things like build time reduction, file loading, dynamic loading of updated assets, console boot time, and more. This is surprisingly important: the people who write the best software will almost always tell you that rapid iteration is king.</i>
</ul>
<p>Did I miss any? What are <i>you</i> optimizing for?</p>
Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com4tag:blogger.com,1999:blog-7898615.post-34480268125665676732010-03-16T16:19:00.001-04:002010-03-16T16:46:48.063-04:00Variants of CompareAndSwap<!-- Generated by Markdown to HTML in MarsEdit --><p>I ran across an interesting issue the other day while trying to make a cross-platform atomics header work on Mac OS X.</p><p>Compare-and-Swap (hereafter, CAS) is one of the fundamental atomic primitives: given a working CAS you can implement any other atomic operation.</p><p>But there are in fact two common variants of CAS:</p> <pre><code> // Returns the old value from *ptr
int ValueCAS(volatile int *ptr, int compare, int swap);
// Returns true if a swap occurred
bool BoolCAS(volatile int *ptr, int compare, int swap);
</code></pre><p>That's OK, though, because it's theoretically possible to convert either one into the other.</p><p>It's trivial to implement BoolCAS in terms of ValueCAS. Here's how you do it:</p> <pre><code> // GOOD: this works correctly.
bool BoolCAS(volatile int *ptr, int compare, int swap) {
return compare == ValueCAS(ptr,compare,swap);
}
</code></pre><p>But for what I was doing, I needed to go the other way around. Mac OS X provides BoolCAS functions in <libkern/OSAtomic.h>, and I needed to convert those to ValueCAS functions.</p><p>It turns out to be subtly difficult to go the other way around, and I thought I'd share the reasons why.</p><h3>First attempt</h3><p>My first attempt was fairly simple, using just an extra load and branch:</p> <pre><code> // BAD: do not use! Broken!
int ValueCAS(volatile int *ptr, int compare, int swap) {
if (BoolCAS(ptr,compare,swap))
return compare;
else
return *ptr;
}
</code></pre><p>The idea is that if the CAS worked, then the old value of <code>*ptr</code> must have been the same as <code>compare</code>, so we can just return that. That's absolutely correct.</p><p>However, if the CAS failed, what was the previous value? I was naïvely re-reading <code>*ptr</code>. But my unit tests (oh yes, this is the kind of thing you unit-test thoroughly) showed that very rarely — once per several million iterations — it would fail to do the right thing. </p><p>What was going wrong? </p><p>The problem comes down to how callers detect success and failure from ValueCAS. If ValueCAS returns <code>compare</code>, the CAS is assumed to have succeeded. If ValueCAS returns any other value, the CAS is assumed to have failed. </p><p>Once we recognize this, we can see that the naïve implementation above has not one, but two failure cases:</p><ol><li><strong>Spurious CAS failure</strong>. This can happen on nearly any system, for a variety of reasons. I'd rather not get too deep into explanations of CPU behavior here, but the typical example might be if an interrupt occurred at exactly the wrong moment. Even if <code>*ptr == compare</code> when the CAS runs, a spurious failure might exit the CAS without changing the value of <code>*ptr</code>. This would cause ValueCAS to incorrectly report success!</li><li><strong>Race between CAS and reload.</strong> If more than one thread is atomically modifying <code>*ptr</code>, then there's a window between the CAS and the reload where <code>*ptr</code> could be changed to anything at all — including getting set back to <code>compare</code>. Again, this would cause ValueCAS to incorrectly report success!</li></ol><h3>Another approach</h3><p>One tempting way to fix it is to simply lie about the old value of <code>*ptr</code>. I didn't actually try this, but I'll admit I considered it for a moment:</p> <pre><code> // BAD: do not use! Semantically incorrect!
int ValueCAS(volatile int *ptr, int compare, int swap) {
if (BoolCAS(ptr,compare,swap))
return compare;
else
return (compare-1); // or any value other than compare
}
</code></pre><p>But this is wrong! It breaks the semantics of the CAS. CAS is supposed to return the old value. But the value this function returns is totally bogus, and may <em>never</em> have existed at <code>*ptr</code>. To help imagine why this is bad, consider what might happen if the caller is using the value as a bitmask. We might wind up returning an illegal mask with bits that had never been set. This could have unintended, ugly, subtle side-effects.</p><h3>Third time's the charm</h3><p>As far as I can tell, the best way to fix it is by adding both an extra load and <em>two</em> branches:</p> <pre><code> // GOOD: works correctly
int ValueCAS(volatile int *ptr, int compare, int swap) {
int old;
do {
if (BoolCAS(ptr,compare,swap))
return compare;
old = *ptr;
} while (old == compare); // never return compare if CAS failed
return old;
}
</code></pre><p>And sure enough, it's a little heavy-handed, but it works. Proper branch hinting will help, but I'm still a bit surprised that it's so expensive (relatively speaking) to do this conversion.</p><p>Can anyone come up with a better way?</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com3tag:blogger.com,1999:blog-7898615.post-50298561727990505092009-12-19T15:12:00.001-05:002009-12-20T12:37:25.835-05:00A Christmas Present to Myself: My New Office<!-- Generated by Markdown to HTML in MarsEdit --><p>I've moved my home office from one room of the basement to another.</p><p>I know, how boring, but this has given me a much-appreciated chance to completely rip out <em>everything</em> and get rid of the mess and abandoned stuff that I don't really use any more. (Heck, back when I moved into my former office, I was still working for Apple.)</p><p>As part of the move, I'm making an effort to make everything as wireless and high-speed as I can.</p><p>Upgrades include:</p><ul><li><strong>Tons of electrical outlets</strong>. Spent several days with an electrician to get this all done. 3 drops, each three feet apart, and each drop has 4 outlets above the desk and 4 outlets below the desk. Plus we put a bonus 4-outlet drop on the side. Grand total: 28. Yes, twenty-eight! I'm <em>incredibly</em> happy with the result... you have no idea how much I hate power strips. :-)</li><li><strong>Clean wired network</strong>. I still had some older Cat-5 cables which kept me from getting maximum throughput. Now all hubs are 1Gb Ethernet and cables are Cat-6 or Cat-5e. This should scale up to 10Gb Ethernet when the time comes.</li><li><strong>Wireless speakers</strong>.<a href="http://www.rogueamoeba.com/airfoil/"><img src="http://homepage.mac.com/drewthaler/images/blog-airfoil396.png" width="64" height="64" align="right"></a><a href="http://www.amazon.com/exec/obidos/ASIN/B0015YJOK2/drewthaler-20"><img src="http://homepage.mac.com/drewthaler/images/amazon/B0015YJOK2.jpg" width="64" height="64" align="right"></a><a href="http://www.amazon.com/exec/obidos/ASIN/B0001DBEM4/drewthaler-20"><img src="http://homepage.mac.com/drewthaler/images/amazon/B0001DBEM4.jpg" width="64" height="64" align="right"></a> Specifically, <a href="http://www.amazon.com/exec/obidos/ASIN/B0001DBEM4/drewthaler-20">Harman-Kardon SoundSticks II</a> attached to an <a href="http://www.amazon.com/exec/obidos/ASIN/B0015YJOK2/drewthaler-20">AirPort Express</a>, driven with iTunes and <a href="http://www.rogueamoeba.com/airfoil/">Airfoil</a>. Yes, I poked fun at AirTunes when it first came out, but it's become surprisingly useful. I do virtually all of my work on a laptop these days, and when I'm in my office I want good sound without having a cable plugged in.<div style="clear: right" /></li><li><a href="http://www.amazon.com/exec/obidos/ASIN/B002TLTG9E/drewthaler-20"><strong>AirPort Base Station with simultaneous dual-band</strong><img src="http://homepage.mac.com/drewthaler/images/amazon/B002TLTG9E.jpg" width="64" height="64" align="right"></a>. I'm getting a little tired of upgrading base stations, honestly. But since I have a ton of devices on my wireless network, and use it to access other machines on my local net, having 802.11n actually run at 802.11n speed is worth it.<div style="clear: right" /></li><li><a href="http://www.amazon.com/exec/obidos/ASIN/B000J2XZ1K/drewthaler-20"><strong>WiEx zBoost YX510-PCS-CEL cellular booster</strong><img src="http://homepage.mac.com/drewthaler/images/amazon/B000J2XZ1K.jpg" width="64" height="64" align="right"></a>. Properly installed with an antenna on the roof, this has given me 5 bars — in the <em>basement</em>, with <em>AT&T</em>. Infinity percent better than what I could get before! Love it!<div style="clear: right" /></li><li><a href="http://www.amazon.com/exec/obidos/ASIN/B0009PLO0Q/drewthaler-20"><strong>Hawking HBB1 broadband booster</strong><img src="http://homepage.mac.com/drewthaler/images/amazon/B0009PLO0Q.jpg" width="64" height="64" align="right"></a>. OK, this provides almost no feedback so I'm not actually sure how I'm supposed to measure its effectiveness. But it's cheap, dead simple to set up, and the network <em>feels</em> more responsive with it enabled. With so many wireless devices and no QoS in Apple's AirPort, I figured that having some traffic shaping was better than none.<div style="clear: right" /></li><li><strong>Wall-mounted shelf</strong> to hold all the networking gear (DSL modem, base station, cell booster, broadband booster). I prefer to keep things off the desk since (ideally) there should be no need to touch this stuff once it's running. Individual wall mounts are out since the walls are concrete. A simple black shelf from Home Depot did the trick nicely — now everything is elevated and out of the way. </li></ul><p>I'm also asking Santa for these extras:</p><ul><li><a href="http://www.amazon.com/exec/obidos/ASIN/B0002WZRJK/drewthaler-20"><strong>Atomic wall clock</strong><img src="http://homepage.mac.com/drewthaler/images/amazon/B0002WZRJK.jpg" width="64" height="64" align="right"></a>, because I enjoy having an analog clock around. And once you've had a clock that automatically sets itself from the <a href="http://tf.nist.gov/stations/wwvb.htm">WWVB atomic time broadcast</a>, you can't go back. <div style="clear: right" /></li><li><a href="http://www.amazon.com/exec/obidos/ASIN/B000KKV16C/drewthaler-20"><strong>Indoor/outdoor thermometer</strong><img src="http://homepage.mac.com/drewthaler/images/amazon/B000KKV16C.jpg" width="64" height="64" align="right"></a>. My new desk is right next to a window, so this is easy. I want one with a wired probe, not wireless, because I prefer it to be reliable and low-maintenance. <div style="clear: right" /></li></ul><p>(FYI, some of the above are affiliate links. I only ever do that for products that I use myself and that I'm very happy with.)</p><p>Removed, and recycled or craigslisted:</p><ul><li><strong>Several 40' runs of cable</strong> that are no longer needed, since my desk is now much closer to where the services come into the house.</li><li><strong>Three power strips</strong> and <strong>two extension cords</strong>. Yay!</li><li><strong>Quite a few mystery DC power adapters</strong>. Often something like a FireWire hub or USB DVD burner that I used to use and now don't, or a charger for something. I'm not a big gadget freak, but after five years in one place these definitely accumulate. (Seriously, wireless power can't get here fast enough.)</li><li><strong>Last year's AirPort 802.11n base station</strong>. Sigh.</li><li><strong>An old 32-bit Gateway PC</strong> that doesn't meet my needs any more.</li><li><strong>PowerMac G5</strong> that I no longer use.</li><li><strong>2 Cinema Displays</strong> with ADC connections. These were really a great investment and they lasted an incredibly long time. But sorry ADC, you're dead, and converting you to DVI is an expensive pain in the ass.</li><li><strong>Apple DVI to ADC adapter</strong> with broken plastic. Huge by modern standards - about the size of a Mac mini.</li><li><strong>Ancient software</strong> and <strong>unread books</strong> that had piled up on my bookshelf. Yeah, I'm pretty sure that copy of DiskWarrior from 2002 isn't going to do me any good any more. </li><li><strong>My home server</strong>. I used to maintain a web and file server at home. (It was a PowerMac G4, nearly ten years old now.) I didn't derive a huge benefit from it, but most of the time the cost was minimal too — just a constant-but-small amount of maintenance. But over time, I found that periodically it created an <em>enormous</em> amount of trouble and expense when a hard drive failed or I needed to upgrade something. I've realized that there's just no value in my messing around with that stuff any more, so I've switched to offsite hosting and online backup.</li></ul><p>I've also ordered some new iMacs for work - to use both as a local distributed build cluster, and for local testing. I'm going to put Windows 7 x64 on one, and the other will have OSX 10.6 running a couple of Linux VMs. </p><p>One of the nice side benefits is that moving has really given me a chance to clean up the cabling. Every single cable I've installed so far is neat and tidy, either cut to length or neatly bundled with a cable tie — so everything is tangle-free. I'm sure this will only last right up until I need to reconfigure everything in a hurry for some new task, but it's pretty sweet for now. :-)</p><p>Done anything nice for <em>your</em> office lately?</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com2tag:blogger.com,1999:blog-7898615.post-56856865223092952982009-12-03T11:02:00.001-05:002009-12-03T12:08:34.066-05:00The Economics of School Supplies<!-- Generated by Markdown to HTML in MarsEdit --><p>I'm interested in economics for one particular reason: incentives are fascinating.</p><p>There's the psychology aspect: how can you influence people's behavior? To really do this well you need to understand how people think. </p><p>There's the engineering aspect: human society is an enormously complex system, even more complex than the systems we work with in technology today. We can do things to nudge a complex system in one direction or another, but we can't always predict what will happen to it.</p><p>And then there are the results: you provide incentives in order to get people to do what you want. And that's a powerful thing! I don't mean this in a cold-blooded way; everybody does this every day of their lives.</p><h2>Incentives in the Classroom</h2><p>My wife is a high school teacher, and we had an interesting talk the other day. It was about how she handles providing a classroom supply of extra paper, extra pens, and all that for kids to use when they forget their own.</p><p>In years past, she had a system for this. She kept a supply closet, and early in September would give the kids extra credit for bringing in up to two items for the supply closet. Since she did this at the beginning of the year, kids quickly donated all kinds of stuff to get the easy points, and the closet filled up. Before the year had even started she had a year's worth of supplies.</p><p>This year, for the first time, she consciously tried <em>not</em> to do that, because she reasoned that it's not really an academic thing — so it wasn't a good idea to give out points for it. Makes sense, right? And besides, the school provides a certain amount of supplies for the teachers which she might be able to use.</p><p>But I'm sure you can guess what happened. With almost 200 kids in and out of her classroom each day, all it takes is a few percent each day to need paper and it'll add up fast. So she very quickly ran through her school-provided allotment, and by November, she was bringing in supplies from home to make up the difference.</p><p>And thus the dilemma: should she offer extra credit again? Or stick to her principles and not give out points?</p><h2>Three approaches</h2><p>As we talked, we came up with basically three approaches to the problem.</p><ol><li><p><strong>Do nothing</strong>. This is what she had been doing, and she wasn't really happy with it. The kids could borrow from each other — and some did. Or she could provide her own supplies — which she had started to do. Or kids would just fail the day's assignment when they didn't have the supplies for it... but that's very hard on a public school teacher who wants every kid to succeed. </p></li><li><p><strong>Positive incentives</strong>. This is the extra-credit approach. She had mixed feelings about this at first, until I pointed out that the extra credit was just a tiny fraction of their grade — something like 1% of a single quarter. That isn't going to turn a failing student into a passing one; it might turn a B into a B+, and so on, but that's all. And then she raised the excellent point that roughly 20% (!!) of their grade is class participation anyway. Providing supplies really helps the community of the classroom, just like class participation does, so that's a fine place to apply the extra credit.</p></li><li><p><strong>Negative incentives</strong>. I suggested that another approach would be to penalize the students for coming to class unprepared. Charge kids 1 point (or even just 1/10th of a point) each day that they borrow paper or a pen. The size of the incentive doesn't matter, it just matters that it's negative. </p></li></ol><p>Now, different people will have different feelings about each of these. And you can do different variations on them — charging a penny instead of a point for paper, etc. But those are the basic choices.</p><h2>Creating an Atmosphere</h2><p>In practice, both the positive and negative incentives should work. But I pointed out that the main difference between these two is not the first-order results of the incentive ... the main difference is how she will be perceived after applying each one.</p><p>Why? Well, even as you incentivize the students with one of these actions, they in turn give you an incentive back with how they react.</p><p>If you're the teacher who is chintzy about paper and deducts fractions of points for every little thing, you'll be a Scrooge and the students won't like you. Negative reinforcement yields negative emotions.</p><p>But on the other hand, what if you're the teacher who provides extra-credit and then free paper? Why, then you're the wonderfully generous and nice teacher whom they love. Positive reinforcement yields positive emotions.</p><p>It's almost Machiavellian: do you want to be feared or loved?</p><p>Knowing my wife as I do, in her classroom she works best when she's loved. And so I told her to go back to what she had been doing — give out extra credit to fill up the supply closet. It's funny that after actually dissecting the problem and analyzing it, we came up with the same solution that she'd done more or less instinctively in the first place.</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com1tag:blogger.com,1999:blog-7898615.post-76976101990487332462009-07-20T01:51:00.001-04:002009-07-20T01:51:31.997-04:00Remembering Apollo 11<!-- Generated by Markdown to HTML in MarsEdit --><p>Today marks the 40th anniversary of the Apollo 11 moon landing.</p><p>I hope you're listening to the <a href="http://www.nasa.gov/externalflash/apollo11_radio/">mission audio</a>, or following the JFK Presidential Library's <a href="http://wechoosethemoon.com/">webcast</a>. The landing itself will be replayed at 4:17pm EDT, and Neil Armstrong's first steps should be at 10:56pm EDT. NASA has been doing a <a href="http://www.nasa.gov/mission_pages/apollo/40th/">number of things</a> for the occasion, including releasing some very cool <a href="http://www.nasa.gov/mission_pages/LRO/multimedia/lroimages/apollosites.html">photos</a> from orbiters which show the Apollo landing sites as they exist today.</p><p>The anniversary is getting a lot of attention this year. It's on magazine covers, it's on TV, and there's an undercurrent of buzz among my geek friends about it.</p><p>So I figured I'd take a break from my usual hectic schedule of "not blogging" to share some thoughts.</p><h3>The first-time cost</h3><p>Going to the moon was fantastically expensive.</p><p>Just think: landing on the moon required an absolutely <strong><em>unparalleled</strong></em> effort. It required the US to bring together technology, manufacturing, research, money, management, a boatload of sciences (psychology, physiology, physics, chemistry, materials, culinary, more), training, politics, leadership, public relations, the military, hard work, and a bottomless amount of determination. </p><p>The men who walked on the moon did so at the pinnacle of an enormous pyramid of marshaled resources — virtually the entire resources of a nation, bent to a single purpose. And they did it all with 1960's technology, in a spacecraft that had less computational power than your phone does today. (Heck, probably less than your <em>refrigerator</em>.) This is the stuff of which legends are made.</p><p>That pyramid of resources was amazing — and fragile.</p><p>We got to the moon and it was pretty freakin' cool. But it wasn't cool enough.</p><h3>Snapping back</h3><p>After getting there the first time, we just kind of stopped. The last mission that landed on the moon was Apollo 17 in 1972, just a few short years after the first one. </p><p>Why? Well, the moon just wasn't that interesting.</p><p>Hang on, I'd like to clarify that. In fact there's a <em>ton</em> of interesting stuff on the moon. But it's probably fair to say the cost of that vast, overreaching pyramid of resources was greater than the return we were getting back.</p><p>The truth is that the moon really didn't have anything that 1970's America really needed; no useful minerals, no water, no oil, and we can't even live there. So it makes sense that after briefly overreaching ourselves just to get there, that there would be a period of time where the pendulum swung back: where we'd stop going entirely.</p><p>But there is one key thing to remember. It's not 1970 any more.</p><h3>What a difference 40 years makes</h3><p>The cost of everything trends downward over time. Or you can put it another way: our civilization gets comparatively wealthier over time, so that a constant cost eventually becomes much more affordable. It doesn't really matter which way you want to look at it, since they're two sides of the same coin.</p><p>In the 1960's the cost of putting a man into space — not just the raw materials and rockets, but the entire infrastructure — was so large that it could only be attempted by the world's largest industrial powers.</p><p>In the 2000's we've seen the cost fall to the point where it just takes the resources of a single large corporation. In the next <a href="http://news.bbc.co.uk/2/hi/science/nature/8111243.stm"><em>two years</em></a> we should see commercial sub-orbital space travel offered by Virgin Galactic. And you can bet Virgin will have competitors before long. </p><p>Space travel isn't quite "cheap", but it's getting surprisingly affordable. It won't be long before we're back at the moon. In fact, I'll go so far as to make a few easy predictions:</p><p><em>A man will walk on the moon again by 2019</em>. That's less than ten years, so on or before the 50th anniversary of Apollo 11. NASA has a plan to do it, and so do the Chinese. Barring bureaucratic screwups, another Great Depression, or the singularity, it seems very likely.</p><p><em>A <strong>woman</strong> will walk on the moon by 2019</em>. The title of "first woman on the moon" is still wide open, and there's no shortage of talented female astronauts. It's an easy bet that the first return mission will include one.</p><h3>What can the moon offer us now?</h3><p>Why would we go back, anyway? Science-fiction fans will have no shortage of ideas about the long-term future, but I find it more interesting to consider the short term — because that's really where the rubber meets the road.</p><p>What are the <strong><em>realistic, short-term benefits</strong></em> that we might get from the moon when we go back?</p><p>A few thoughts:</p><ul><li><p><em>Tourism</em>. We already have space tourism, where rich people pay millions of dollars simply to go into space. Once commercial spaceflight takes off — and Virgin Galactic plans its inaugural flight within just <a href="http://news.bbc.co.uk/2/hi/science/nature/8111243.stm">two years</a> — how long do you think it'll be until someone wants a tour of the moon?</p></li><li><p><em>An outpost</em>. Rather like <a href="http://en.wikipedia.org/wiki/McMurdo_Station">McMurdo Station</a> in Antarctica, an outpost on the moon would be a center for scientific research and exploration, as well as a central base for other activities.</p></li><li><p><em>Mining</em>, and ultimately <em>manufacturing</em>. Silicon, aluminum, and iron are probably the most useful and easily-extracted resources in the short term. (Many people talk about <a href="http://www.wired.com/science/space/news/2006/12/72276">Helium-3</a>, but it's not currently exploitable so I'm leaving it off.) But why would we mine the moon for this stuff instead of getting it from Earth? It's useful, but not exceptionally scarce.</p><p>The answer is really that it's about <em>relative</em> scarcity. These raw materials are not exceptionally scarce here on Earth, but they sure are hard to come by up in orbit!</p><p>It's a question of cost again. It's expensive to get things out of the earth's gravity well. If you want something even moderately large on the moon or in space — habitats, satellites, ships, mirrors, radiation shields — it may be cheaper to build it in place, with materials from the moon instead of from Earth. </p></li></ul><p>I'd guess that these things are likely to happen in roughly that order: Tourism first, because there is a huge pent-up demand. This will be followed soon afterward by a small outpost — mostly for research, but also supporting (and partially funded by) tourism. And finally the mining and manufacturing, which can then can be used to build up the outpost even more.</p><p>Even though we've gotten used to space travel as a NASA thing, it's possible these may not be governmental projects at all, or they may be hybrid ventures which are part commercial and part subsidized. Either way, the feeling that the pendulum is finally swinging back is terrific. I can't wait!</p><p>Now it's your turn. What do <em>you</em> think the moon will have to offer us during the 2020's?</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com1tag:blogger.com,1999:blog-7898615.post-5431194167179177312007-12-02T02:36:00.001-05:002007-12-02T02:47:09.988-05:00The Case Against Insensitivity<!-- Generated by Markdown to HTML in MarsEdit --><p>One of the most controversial parts of my earlier post, <a href="http://drewthaler.blogspot.com/2007/10/don-be-zfs-hater.html">Don't Be a ZFS Hater</a>, was when I mentioned off-handedly in the comments that I don't like case-insensitivity in filesystems.</p><p>Boy, did that spur a storm of replies.</p><p>I resolved to not pollute the ZFS discussion with a discussion of case-insensitivity and promised to make a separate blog post about it. It took a while, but this is that post. I blame a busy work schedule and an even busier travel schedule. (Recently in the span of two weeks I was in California, Ohio, London, Liverpool, London, Bristol, London, Amsterdam, London, then back to Ohio. Phew!)</p><h4>Here's Why Case-Insensitive Filesystems Are Bad</h4><p>I've worked in and around filesystems for most of my career; if not in the filesystem itself then usually a layer just above or below it. I'm speaking from experience when I tell you:</p><p><em>Case-insensitivity is a bad idea in filesystems</em>.</p><p>And here's why:</p><ol><li>It's poorly defined.</li><li>Every filesystem does it differently.</li><li>Case-insensitivity is a layering violation.</li><li>Case-insensitivity forces layering violations upon other code.</li><li>Case-insensitivity is contagious.</li><li>Case-insensitivity adds complexity and provides no actual benefit.</li></ol><p>I'll expand on each of these below.</p><h4>It's poorly defined</h4><p>When I say "case-insensitive", what does that mean to you?</p><p>If you only speak one language and that language is English, it probably seems perfectly reasonable: map the letter <em>a</em> to <em>A</em>, <em>b</em> to <em>B</em>, and so on through <em>z</em> to <em>Z</em>. There, you're done. What was so hard about that?</p><p>But that's <a href="http://en.wikipedia.org/wiki/ASCII">ASCII</a> thinking; the world left that behind a long time ago. Modern systems are expected to deal with case differences in all sorts of languages. Instead of a simple 26-letter transformation, "case insensitivity" really means handling all the other alphabets too.</p><p>The problem with doing that, however, is that it brings language and orthography into the picture. And <strong>human languages are inherently vague, large, messy, and constantly evolving</strong>.</p><p>Can you make a strict definition of "case insensitivity" without any hand-waving?</p><p>One way to do it is with an equivalence table: start listing all the characters that are equal to other characters. We can go through all the variants of Latin alphabets, including a huge list of <a href="http://www.everything2.com/index.pl?node=Accent%20marks%20used%20with%20the%20Latin%20alphabet">accents</a>: acute, grave, circumflex, umlaut, tilde, cedilla, macron, breve, dot, ring, ogonek, hacek, and bar. Don't forget to find all the special ligatures and other letters, too, such as <em>Æ</em> vs <em>æ</em> and <em>Ø</em> vs <em>ø</em>.</p><p>Okay, our table is pretty big so far. Now let's start adding in other alphabets with case: <a href="http://en.wikipedia.org/wiki/Greek_alphabet">Greek</a>, <a href="http://en.wikipedia.org/wiki/Armenian_alphabet">Armenian</a>, and the <a href="http://en.wikipedia.org/wiki/Cyrillic_alphabet">Cyrillic alphabets</a>. And don't forget the more obscure ones, like <a href="http://en.wikipedia.org/wiki/Coptic_alphabet">Coptic</a>. Phew. It's getting pretty big.</p><p>Did we miss any? Well, for any given version of the Unicode standard it's always possible to enumerate all letters, so it's certainly possible to do all the legwork and prove that we've got all the case mappings for, say, <a href="http://www.unicode.org/versions/Unicode5.0.0/">Unicode 5.0.0</a> which is the <a href="http://www.unicode.org/versions/latest/">latest</a> at the time of this writing. But Unicode is an evolving standard and new characters are added frequently. Every time a new script with case is added we'll need to update our table.</p><p>There are also some other hard questions for case insensitivity:</p><ul><li><p><a href="http://en.wikipedia.org/wiki/Digraph_%28orthography%29">Digraph</a> characters may have three equivalent mappings, depending on how they are being written: all-lowercase, all-uppercase, or title-case. (For example: <em>dz</em>, <em>DZ</em>, or <em>Dz</em>.) But this breaks some case-mapping tables which didn't anticipate the need for an N-way equivalence.</p></li><li><p>The German <a href="http://en.wikipedia.org/wiki/ß">letter <em>ß</em></a> is considered equal to lowercase <em>ss</em>. Should "Straße" and "STRASSE" be considered equivalent? They are in German. But this breaks some case-mapping tables which didn't anticipate the need for an N-to-M character translation (1:2, in this case).</p></li><li><p>Capital letters can significantly alter the meaning of a word or phrase. In German, capital letters indicate nouns, so the word <em>Essen</em> means "food", while the word <em>essen</em> means "to eat". We make similar distinctions in English between proper nouns and regular nouns: <em>God</em> vs <em>god</em>, <em>China</em> vs <em>china</em>, <em>Turkey</em> vs <em>turkey</em>, and so on. Should "essen" and "Essen", or "china" and "China" really be considered equivalent?</p></li><li><p>Some <a href="http://en.wikipedia.org/wiki/Hebrew_alphabet">Hebrew</a> letters use different forms when at the end of a word, such as פ vs ף, or נ vs ן. Are these equivalent?</p></li><li><p>In <a href="http://en.wikipedia.org/wiki/Georgian_alphabet">Georgian</a>, people recently experimented with using an obsolete alphabet called <em>Asomtavruli</em> to reintroduce capital letters to the written language. What if this had caught on?</p></li><li><p>What about any future characters which are not present in the current version of the Unicode standard?</p></li></ul><p>Case is a concept that is built into written languages. And <strong>human language is inherently messy</strong>. This means that case-insensitivity is always going to be poorly defined, no matter how hard we try.</p><h4>Every filesystem does it differently</h4><p>Unfortunately, filesystems can't engage in hand-waving. Filesystem data must be persistent and forward-compatible. People expect that the data they wrote to a disk last year should still be readable this year, even if they've had an operating system upgrade.</p><p>That's a perfectly reasonable expectation. But it means that the on-disk filesystem specification needs to freeze and stop changing when it's released to the world.</p><p>Because our notion of what exactly "case-insensitive" means has changed over the past twenty years, however, we've seen a number of different methods of case-insensitivity emerge. </p><p>Here are a handful of the most popular case-insensitive filesystems and how they handle case-mapping:</p><ul><li><em>FAT-32</em>: ASCII upper- and lower-case letters, but <em>a</em>-<em>z</em> and <em>A</em>-<em>Z</em> are considered identical. Also variable IBM code pages in high ASCII.</li><li><em>HFS</em>: ASCII upper- and lower-case letters, but <em>a</em>-<em>z</em> and <em>A</em>-<em>Z</em> are considered identical. Also variable Mac encodings in high ASCII.</li><li><em>NTFS</em>: Case-insensitive in different ways <a href="http://blogs.msdn.com/michkap/archive/2005/01/16/353873.aspx">depending on the version of Windows that created the volume</a>.</li><li><em>HFS+</em>: Case-insensitive with a mapping table which was <a href="http://developer.apple.com/technotes/tn/tn1150.html">frozen circa 1996</a>, and thus lacks case mappings for any newer characters.</li></ul><p>None of these — except for NTFS created by Vista — are actually up-to-date with the current Unicode specification. <em>That's because they all predate it</em>. Similarly, if a new filesystem were to introduce case-insensitivity today, it would be locked into, say, Unicode 5.0.0's case mappings. And that would be all well and good until Unicode 5.1.0 came along.</p><p>The history of filesystems is littered with broken historical case mappings like a trail of tears.</p><h4>Case-insensitivity is a layering violation</h4><p>When people argue for case-insensitivity in the filesystem, they almost always give user interface reasons for it. (The only other arguments I've seen are based on contagion, which I'll talk about in a moment.) Here is the canonical example:</p><blockquote>My Aunt Tillie doesn't know the difference between <i>letter.txt</i> and <i>Letter.txt</i>. The filesystem should help her out.</blockquote><p>But in fact this is a <acronym title="user interface">UI</acronym> problem. The problem relates to the <em>display</em> and <em>management</em> of information, not the <em>storage</em> of this information.</p><p>Don't believe me?</p><ul><li><p>When any application displays items in a window, who sorts them case-insensitively? The filesystem? No! The application does it.</p></li><li><p>When you type-select, typing <em>b-a-b-y</em> to select the folder "Baby Pictures" in an application, who does the case-insensitive mapping of the letters you type to the files you select? The filesystem? No! The application again.</p></li><li><p>When you save or copy files, who does the case-insensitive test to warn you if you're creating "file.txt" when "File.txt" already exists? The filesystem? Yes!</p></li></ul><p>Why does the third question have a different answer than the rest?</p><p>And we've already talked about how filesystems are chronically out-of-date with their case mappings. If your aunt is a Turkish Mac user, for example, she's probably going to notice that the behavior of the third one is different for no good reason. Why are you confusing your Aunt Tülay?</p><p>One last point was summarized nicely by <a href="http://www.mikeash.com/">Mike Ash</a> in the comments of <a href="http://drewthaler.blogspot.com/2007/10/don-be-zfs-hater.html">Don't Be a ZFS Hater</a>. I'll just quote him wholesale here:</p><blockquote>Yes, Aunt Tillie will think that "Muffin Recipe.rtf" and "muffin recipe.rtf" ought to be the same file. But you know what? She'll also think that "Muffin Recipe .rtf" and "Recipe for Muffins.rtf" and "Mufin Recipe.txt" ought to be the same file too.<br /><br />Users already don't generally understand how the OS decides whether two files are the same or not. Trying to alleviate this problem by mapping names with different case to the same file solves only 1% of the problem and just isn't worth the effort.</blockquote><p>I agree completely.</p><h4>Case-insensitivity forces layering violations upon other code</h4><p>All too often, pieces of code around the system are required to hard-code knowledge about case-insensitive filesystem behavior. Here are a few examples off the top of my head:</p><ul><li><p><em>Collision prediction</em>. An application may need to know if two files would conflict before it actually writes either of them to disk. If you are writing an application where a user creates a group of documents — a web page editor, perhaps — you may need to know when <em>banana.jpg</em> and <em>BANANA.JPG</em> will conflict.<br /><br />The most common way that programmers solve this is by hard-coding some knowledge about the case-insensitivity of the filesystem in their code. That's a classic layering violation.</p></li><li><p><em>Filename hashing</em>. If you are writing code to hash strings that are filenames, you probably want equivalent paths to generate the same hash. But it's impossible to know which files are equivalent unless you know the filesystem's rules for case-mapping.<br /><br />Again, the most common solution is a layering violation. You either hard-code some knowledge about the case-insensitivity tables, or you hard-code some knowledge about your input data. (For example, you may just require that you'll never, never, ever have multiple access paths for the same file in your input data. Like all layering violations, that might work wonderfully for a while ... right up until the day that it fails miserably.)</p></li></ul><p>I'm sure there are more examples out there.</p><h4>Case-insensitivity is contagious</h4><p>This is the worst part. It's all too easy to accidentally introduce a dependence on case-insensitivity: just use an incorrect path with bad case.</p><p>The moment somebody creates an application or other system that inadvertently depends on case-insensitivity, it forces people to use a case-insensitive filesystem if they want to use that app or system. And that's one of the major reasons why case-insensitivity has stuck around — because it's historically been very difficult to get rid of.</p><p>I've seen this happen with:</p><ul><li><p><em>Source code</em>. Some bozo writes <tt>#include "utils.h"</tt> when the file is named <tt>Utils.h</tt>. Sounds innocent enough, until you find that it's repeated dozens of times across hundreds of files. Now that project can only ever be compiled on a case-insensitive filesystem.</p></li><li><p><em>Game assets</em>. A game tries to load <tt>lipsync.dat</tt> instead of <tt>LIPSYNC.DAT</tt>. Without knowing it, the artist or developer has accidentally locked that game so that it can only run on a case-insensitive filesystem. (This causes real, constant problems in game pipelines; teams create and test their games on case-insensitive NTFS and don't notice such problems until it's burned to a case-sensitive UDF filesystem on DVD or Blu-Ray.)</p></li><li><p><em>Application libraries</em>. DLLs and shared library references are sometimes generated by a build script which uses the wrong case. When that happens, the application may simply fail to launch from a case-sensitive filesystem.</p></li><li><p><em>Miscellaneous data files</em>. Sometimes an application will appear to run on a case-sensitive filesystem but some feature will fail to work because it fails to load a critical data file: the spell-checking dictionary, a required font, a nib, you name it.</p></li></ul><p>Happily, since Mac OS X shipped in 2001, Apple has been busy solving its own problems with case-insensitivity and encouraging its developers to test with case-sensitive filesystems. Two important initiatives in this direction have been NFS home directories and case-sensitive HFSX.</p><p>The upshot of it is that Mac OS X is actually very friendly to case-sensitive disks these days; very little that's bad happens when you use case-sensitive HFSX today. </p><h4>Case-insensitivity adds complexity with no actual benefit</h4><p>I'm going to make an assertion here:</p><p><em>ONE HUNDRED PERCENT of the path lookups happening on your Mac right now are made with correct case.</em></p><p>Think about that for a moment.</p><p>First off, you may think this contradicts the point I just made in the previous section. Nope; I'm simply rounding. The actual figure is something like 99.999%, and I'd probably get tired of typing 9's before I actually approached the real number. There are infinitesimally few path accesses made with incorrect case compared to the ones that are made with the proper case.</p><p>Modern computers make hundreds of filesystem accesses per second. As I type this single sentence in MarsEdit on Mac OS X 10.4.11, my computer has made <strong>3692</strong> filesystem accesses by path. (Yes, really. MarsEdit's "Preview" window is invoking Perl to run Markdown, which loads a handful of modules, and then WebKit re-renders the page. That's a lot of it, but meanwhile there's background activity from Mail, Activity Monitor, iChat, SystemUIServer, iCalAlarmScheduler, AirPort Base Station Agent, Radioshift, NetNewsWire, Twitterrific, and Safari.) </p><p>Under Mac OS X you can measure it yourself with this command in Terminal:</p><p> <tt>sudo fs_usage -f filesys | grep / > /tmp/accesses.txt</tt></p><p>The vast majority of file accesses are made with paths that were returned from the filesystem itself: some bit of code read the contents of a directory, and passed the results on to another bit of code, which eventually decided to access one of those files. So most of the time the filesystem is getting back the paths that it has returned earlier. Very very few accesses are made with paths that come directly from an error-prone human, which is why essentially 100% of filesystem accesses are made with correct case.</p><p>But if essentially all filesystem accesses are made with the correct case to begin with, why do we even have case-insensitivity at all?</p><p>We've already discussed the problems of <em>contagion</em>, which is a circular justification: we have to do it because someone else did it first. We've also discussed UI decisions being incorrectly implemented in the bottommost layer of the operating system. Other than those two, what good is it?</p><p>I don't have an answer to that. For the life of me I can't come up with any reason to justify case-insensitive filesystems from a pure design standpoint. That leads me to my closing argument, which is...</p><h4>A thought experiment</h4><p>Suppose case-insensitive filesystems had never been invented. You're the leader of a team of engineers in charge of XYZZYFS, the next big thing in filesystems. One day you tell the other people who work on it:</p><p>"Hey! I've got this great idea! It's called case-insensitivity. We'll take every path that comes into the filesystem and compare it against a huge table to create a case-folded version of the path which we'll use for comparisons and sorting. This will add a bunch of complexity to the code, slow down all path lookups, increase our RAM footprint, make it more difficult for users of our filesystem to handle paths, and create a compatibility nightmare for future versions if we ever decide to change the table. But, you see, <strong>it'll all be worth it, because...</strong> _________________."</p><p>Can you fill in the blank?</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com16tag:blogger.com,1999:blog-7898615.post-15704801825769427372007-10-10T06:19:00.001-04:002007-10-11T13:16:56.037-04:00ZFS Hater Redux<!-- Generated by Markdown to HTML in MarsEdit --><p>MWJ has responded to my last post, <a href="http://drewthaler.blogspot.com/2007/10/don-be-zfs-hater.html">Don't Be a ZFS Hater</a>, with a post of their own: <a href="http://www.macjournals.com/news/2007/10/07.html#a80">You don't have to hate ZFS to know it's wrong for you</a>.</p><p>I don't like the point-by-point quote and response format — it's way too much like an old-school Usenet flamewar. So I will simply try to hit the high points of their arguments.</p><h4>Where we agree</h4><ul><li><p><em>ZFS is not ready to deploy to the entire Mac OS X user base today</em>. There's still some work to be done.</p></li><li><p><em>ZFS isn't necessary for most of today's Macintosh computers</em>. If you have been using your Mac with no storage-related problems, then you can keep on using it that way. Perform regular backups and you'll be just fine.</p></li><li><p><em>It would be an absolutely terrible idea to take people's perfectly working HFS+ installations on existing computers and forcibly convert them to ZFS, chuckling evilly all the while</em>. Not quite sure where that <a href="http://www.fallacyfiles.org/strawman.html">strawman</a> came from.</p></li><li><p><em>ZFS fatzaps are expensive for small files</em>. If it were true that 20% of the files in a Mac OS X installation required a <a href="http://www.opensolaris.org/os/community/zfs/docs/ondiskformat0822.pdf">fatzap</a> (pdf link to ZFS-on-disk specification), that would indeed be unnecessarily wasteful.</p></li><li><p><em>A typical Mac OS X 10.4.x installation has on the order of about 600,000 files</em>.</p></li></ul><p>I think that's about it. But of course there are a number of places where we disagree too.</p><h4>ZFS would be awfully nice for a small segment of the Mac OS X user base if it were ready today.</h4><p>If you spend any amount of time managing storage — if drives have gone bad on you, if you have ever run out of space on a desktop system and needed to add a drive (or two), if you have a RAID array — then you are the sort of user that could see some immediate benefit.</p><p>But of course as we already agreed, it's not ready today. You haven't been "cheated" and I'm sure you don't feel that way. But feel free to look forward to it: I sure am.</p><h4>ZFS — or something with all the features of ZFS — will be more than nice, it will be <em>necessary</em> for tomorrow's Macintosh computers.</h4><p>Both storage sizes and consumer consumption of storage grow exponentially. I tried to make this point last time, but MWJ seems to have misunderstood and accused me of misquoting. Let's try again.</p><p>In 1997, 20GB of storage meant a server RAID array. Ten years later, in 2007, 20GB of storage is considered "not enough" by most people. Across my entire household I have drives larger than that in my computer, in my TiVo, in my PlayStation 3, and even in my iPod. Now let's extrapolate that into the future.</p><p>In 2007, 20TB of storage means a server RAID array. Ten years from now, in 2017, 20TB of storage will similarly be considered "not enough". MWJ scoffed at ZFS because it's really pretty good at the problems of large storage. But you know what? A solution to managing that much data will need to be in place in Mac OS X <em>well before 20TB drives become the norm</em>. Better hope someone's working on it today.</p><p>Meanwhile — and this is what scares the pants off me — the reliability numbers for hard drives have improved much more slowly than capacity.</p><p>Here's a fairly typical <a href="http://www.windowsmarketplace.com/details.aspx?itemid=3392956">Seagate drive</a> with a capacity of ~150GB = ~1.2 x 10<sup>12</sup> bits. <strike>The recoverable error rate is listed as 10 bits per 10<sup>12</sup> bits. Let's put those numbers together. That means that if you read the entire surface of the disk, you'll typically get <em>twelve bits</em> back that are wrong and which a retry could have fixed.</strike> (<b>Updated Oct 11 2007</b>: In the comments, Anton corrected me: I should've used the unrecoverable error rate here, not the recoverable error rate. The net result is that in ideal operating conditions bit errors occur over 100x less frequently than I originally suggested. However, <i>it's still not zero</i>. The net result is still a looming problem when you scale it across (installed base) x (storage consumption) x (time). See the comment thread.)</p><p>Yes, really. Did you catch the implications of that? <strong>Silent single-bit errors are happening today</strong>. They happen much more often at high-end capacities and utilizations, and we often get lucky because some types of data (video, audio, etc) are resistant to that kind of single-bit error. But today's high end is tomorrow's medium end, and the day after tomorrow's low end. This problem is only going to get worse.</p><p>Worse, <strong>bit errors are cumulative</strong>. If you read and get a bit error, you might wind up writing it back out to disk too. Oops! Now that bit error just went from transient to permanent. </p><p>Still think <a href="http://blogs.sun.com/bonwick/entry/zfs_end_to_end_data">end-to-end data integrity</a> isn't worth it?</p><h4>Apple using ZFS rather than writing their own is a smart choice.</h4><p>As I hope I made abundantly clear in the <a href="http://drewthaler.blogspot.com/2007/10/don-be-zfs-hater.html">last post</a>, extending HFS+ to the future that we can see looming is just not an option — its structure is simply too far removed from these problems. It's really just not worth it. It's pretty awesome that the original HFS design scaled as far as it did: how many people can come up with a 20-year filesystem? But you have to know when to throw in the towel.</p><p>So if you accept that the things I described above are real, looming problems, then Apple really does need a filesystem with at least several of the more important attributes of ZFS.</p><p>The choices at this point are essentially twofold: (1) start completely from scratch, or (2) use ZFS. There's really no point in starting over. ZFS has a usable license and has been under development for at least five years by now. By the time you started over and burned five years on catching up it would be too late.</p><p>And I really do want to reiterate that the shared community of engineers from Apple, Sun, and FreeBSD working on ZFS is a real and measurable benefit. I've heard as much from friends in CoreOS. I can't understand the hostility to this very clear and obvious fact. It's as if Apple suddenly doubled or tripled the number of filesystem engineers it has available, snagging some really brilliant guys at the top of their profession in the process, and then multiplied its testing force by a factor of 10.</p><p>(To respond to a query voiced by MWJ, HFS+ never gathered that community when it was open-sourced because the design was already quite old at that point. It frankly didn't have anything new and exciting to offer, and it was saddled with performance problems and historical compromises of various kinds, so very few people were interested in it.)</p><h4>ZFS fatzaps are unlikely to be a significant problem.</h4><p><em>This gets a bit technical. Please skip this section if you don't care about this level of detail.</em></p><p>MWJ really pounded on this one. That was a bit weird to me, since it seemed to be suggesting that Apple would not expend any engineering effort on solving any obvious glaring problems with ZFS before releasing it. That's not the Apple I know.</p><p>But okay, let's suppose that we're stuck with ZFS and Mac OS X both frozen as they stand today. Let's try to make an <em>a priori</em> prediction of the actual cost of ZFS fatzaps on a typical Mac OS X system.</p><ul><li><p>Classic HFS attributes (FinderInfo, ExtendedFinderInfo, etc) are largely unnecessary and unused today because the Finder uses <code>.DS_Store</code> files instead. In the few cases where these attributes are set and used by legacy code, they should fit easily in a small number of microzaps.</p></li><li><p>Extended attributes may create fatzaps. Today it seems like extended attributes are typically used on large files: disk images, digital photos, etc. This may provoke squawking from the peanut gallery, but once a file is above a certain size — roughly a couple of megabytes — using an extra 128KiB is negligible. If you have a 4MiB file and you add 128KiB to track its attributes, big deal: you've added 3%. It's not nothing, but it's hardly a significant problem.</p></li><li><p>Another likely source of fatzaps in ZFS on Mac OS X is the resource fork. But with Classic gone, new Macs ship with <em>virtually no resource forks on disk</em>. There are none in the BSD subsystem. There are a handful in <code>/System</code> and <code>/Library</code>, mostly fonts. The biggest culprits are large old applications like Quicken and Microsoft Office. A quick measurement on my heavily-used one-year-old laptop shows that I have exactly 1877 resource forks out of 722210 files — that's <strong>0.2%</strong>, not 20%.</p><p>(Fun fact: The space that would be consumed by fatzap headers for these resource files comes out to just 235 MiB, or roughly six and a half <a href="http://www.apple.com/support/downloads/keyboardsoftwareupdate12.html">Keyboard Software Updates</a>. Again: not nothing, but hardly a crisis to scream about.)</p></li></ul><p>Want to measure it yourself? Amit Singh's excellent <a href="http://www.osxbook.com/software/hfsdebug/">hfsdebug</a> utility will show you a quick summary. Just run "<code>sudo hfsdebug -s</code>" and look at the numbers for "files" and "non-zero resource forks". Or try "<code>sudo hfsdebug -b attributes -l any | less</code>" to examine the files which have extended attributes on your disk.</p><h4>ZFS snapshots don't have to be wasteful</h4><p>The cheesesteak analogy was cute. But rather than imagining that snapshots just eat and eat and eat storage until you choke in a <a href="http://en.wikipedia.org/wiki/Mr._Creosote">greasy pile of death</a>, it would help if we all actually understand how hard drive storage is actually used in practice, and how ZFS can work with that.</p><p>There are three major classes of stored data.</p><ul><li><em>Static data</em> is data that you want to keep and almost never modify. This is your archive. Photographs, music, digital video, applications, email, etc. Archives are additive: unless you really run out of room, you rarely delete the old — you only add new stuff. You want the contents safe and immediately accessible, but they are essentially unchanging.</li></ul><p>Snapshotting static data is close enough to free that you won't notice: the only cost is the basic cost of the snapshot. No extraneous data copies are ever created, because you never modify or delete this stuff anyway.</p><ul><li><em>Dynamic data</em> is data that you want to keep, but are modifying with some frequency. This is whatever you are working on at the moment. It might be writing a novel, working in Photoshop, or writing code: in all cases you keep saving new versions over the old.</li></ul><p>Snapshotting dynamic data is more expensive, because if you do it too much without recycling your old snapshots then you can build up a large backlog.</p><ul><li><em>Transient data</em> is data that should not be persistent at all. These are your temporary files: local caches, scratch files, compiler object files, downloaded zip files or disk images, etc. These may be created, modified, or deleted at any moment.</li></ul><p>Snapshotting transient data is generally a bad idea — by definition you don't care that much about it and you'd prefer it to be deleted immediately.</p><p>Got all that? Okay. Now I need to make a couple of points.</p><p>First, I assert that virtually <strong>all</strong> of the data on personal computer hard drives is <em>static</em> most of the time. Think about that. The operating system is static the whole time you are using it, until you install a system update. (And even then, usually just a few hundred megabytes change out of several gigabytes.) Your <code>/Applications</code> folder is static. Your music is static. And so on. Usually a few percent of your data is dynamic, and a few more percent is transient. But in most cases well over 95% is static. (Exceptions are easy to come up with: Sometimes you generate a large amount of transient data while building a disk image in iDVD or importing DV footage. That can shift the ratio below 95%. But once that task is complete you're back to the original ratio.)</p><p>Second, the biggest distinction that matters when snapshotting is separating persistent data from transient data. Taking snapshots of transient data is what will waste disk space in a hurry. Taking snapshots of dynamic data as a local backup is often valuable enough that it's okay to burn the small amount of disk space that it takes, because remember: that's the <em>actual data that you're actively working on</em>. And as we already mentioned, snapshots of static data are free.</p><p>Now here's where it gets interesting.</p><p>With ZFS, snapshots work on the filesystem level. Because it no longer uses the "big floppy" model of storage, new filesystems are very cheap to create. (They are almost as lightweight as directories, and often used to replace them.) So let's create one or more special filesystems just for transient data and exclude them from our regular snapshot process. In fact on Mac OS X that's easy: we have well-defined directories for transient data: <code>~/Library/Caches</code>, <code>/tmp</code>, and so on. Link those all off to one or more transient filesystems and they will never wind up in a snapshot of the important stuff. I wouldn't expect users to do this for themselves, of course — but it could certainly be set up that way automatically by Apple.</p><p>Once the transient data is out of the picture, our snapshots will consist of 95% or more static data — which is not copied in any way — and a tiny percentage of dynamic data. And remember, the dynamic data is not even copied unless and until it changes. The net effect is very similar to doing <strong>an incremental backup of <em>exactly and only the files you are working on</strong></em>. This is essentially a perfect local backup: no duplication except where it's actually needed.</p><p>Will you want to allow snapshots to live forever? Of course not. One reasonable model for taking backup snapshots might be to remember 12 hourly snapshots, 7 daily snapshots, and 4 weekly snapshots. If you are getting tight on storage the system could take new snapshots less frequently and expire them more aggressively. Remember: when nothing is changing the snapshots don't take up any space.</p><h4>Wrap-up: Listen to the smart guys</h4><p>Some very smart people at Sun started the ball rolling by putting an awful lot of thought into the future of storage, and they came up with ZFS.</p><p>After they announced it and started talking about it, other brilliant people at Apple (and FreeBSD, and NetBSD) paid attention to what they were doing. And they listened, and thought about it, and looked at the code, and wound up coming around to the side of ZFS as well.</p><p>If you think I'm smart, just know that I'm in awe of some of the guys who've been involved with this project.</p><p>If you think I'm stupid, why, I look forward to hearing from you in the comments.</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com42tag:blogger.com,1999:blog-7898615.post-60854974826032233352007-10-06T03:03:00.002-04:002008-04-08T10:30:01.598-04:00Don't be a ZFS Hater<!-- Generated by Markdown to HTML in MarsEdit --><p>John Gruber recently <a href="http://daringfireball.net/linked/2007/october#fri-05-zfs">linked to</a> — and thus gave credibility to — a <a href="http://www.macjournals.com/news/2007/10/04#a79">MWJ post</a> ripping on a fairly reasonable <a href="http://www.appleinsider.com/articles/07/10/04/zfs_to_play_larger_role_in_future_versions_of_mac_os_x.html">AppleInsider post about ZFS</a>. Representative quote:</p><blockquote> <p>“We don't find HFS Plus administration to be complex, and we can't tell you what those other things mean, but they sound really cool, and therefore we want them. On the magic unlocked iPhone. For free.”</p></blockquote><p>Har har har. Wait. Hold on a minute. Why is it suddenly fashionable to bash on ZFS?</p><p>Part of it is a backlash to the weird and obviously fake rumor about it becoming the default in Leopard, I guess. (No thanks to Sun's CEO <a href="http://blogs.sun.com/jonathan/">Jonathan Schwartz</a> here, who as far as I know has never publicly said anything about why he either <a href="http://www.macnn.com/articles/07/06/06/zfs.in.leopard/">misspoke or misunderstood</a> what was going on back in June.)</p><p>But don't do that. Don't be a ZFS hater.</p><h4>A word about my background</h4><p>Let's get the credentials out of the way up front. Today I work on a file I/O subsystem for PlayStation 3 games. Before that, I worked in Apple's CoreOS filesystems group. Before that, I worked on <a href="http://www.cocoadev.com/index.pl?DiscRecording">DiscRecording.framework</a>, and singlehandedly created the content subframework that streamed out HFS+, ISO-9660, and Joliet filesystems. Before that, I worked on the same thing for Mac OS 9. And before that, I worked on mass storage drivers for external USB/FireWire drives and internal ATA/ATAPI/SCSI drives.</p><p>You might say I know a thing or two about filesystems and storage.</p><h4>What bugged me about the article</h4><ol><li><p><em>ZFS is a fine candidate to replace HFS+ eventually.</em> It's not going to happen overnight, no. And it'll be available as an option for early adopters <em>way</em> before it becomes the default. But several years from now? Absolutely.</p></li><li><p><em>The bizarre rants about ZFS wasting processor time and disk space.</em> I'm sorry, I wasn't aware that we were still using 30MHz machines with 1.44MB floppies. ZFS is great specifically because it takes two things that modern computers tend to have a <em>surplus</em> of — CPU time and hard disk space — and borrows a bit of it in the name of data integrity and ease of use. This tradeoff made very little sense in, say, 1992. But here in 2007 it's brilliant.</p></li><li><p><em>Sneeringly implying that HFS+ is sufficient.</em> Sure, HFS+ administration is simple, but it's also inflexible. It locks you into what I call the "big floppy" model of storage. This only gets more and more painful as disks get bigger and bigger. Storage management has come a long way since the original HFS was created, and ZFS administration lets you do things that HFS+ can only dream of.</p></li><li><p><em>Claiming that RAID-Z is required for checksums to be useful.</em> This is flat-out wrong. Sure, RAID-Z helps a lot by storing an <a href="http://en.wikipedia.org/wiki/Error_detection_and_correction#Error-correcting_code">error-correcting code</a>. But even without RAID-Z, simply recognizing that the data is bad gets you well down the road to recovering from an error — depending on the exact nature of the problem, a simple retry loop can in fact get you the right data the second or third time. And as soon as you know there is a problem you can mark the block as bad and aggressively copy it elsewhere to preserve it. I suppose the author would prefer that the filesystem silently returned bad data?</p></li><li><p><em>Completely ignoring Moore's Law.</em> How dumb do you need to be to willfully ignore the fact that the things that are bleeding-edge today will be commonplace tomorrow? Twenty gigabyte disks were massive server arrays <a href="http://en.wikipedia.org/wiki/Power_Macintosh_G3">ten years ago</a>. Today I use a hard drive ten times bigger than that <a href="http://www.engadget.com/2006/09/12/hands-on-with-the-tivo-series3/">just to watch TV</a>.</p></li></ol><p>Reading this article made me feel like I was back in 1996 listening to people debate cooperative vs preemptive multitasking. In the Mac community at that time there were, I'm ashamed to say, a lot of heated discussions about how preemptive threading was unnecessary. There were some people (like me) who were clamoring for a preemptive scheduler, while others defended the status quo — claiming, among other things, that Mac OS 8's cooperative threads "weren't that bad" and were "fine if you used them correctly". Um, yeah.</p><p>Since then we've thoroughly settled that debate, of course. And if you know anything about technology you might be able to understand why there's a difference between "not that bad" and "a completely new paradigm".</p><h4>ZFS is cool</h4><p>Let's do a short rundown of reasons why I, a qualified filesystem and storage engineer, think that ZFS is cool. I'll leave out some of the more technical reasons and just try to keep it in plain English, with links for further reading.</p><ul><li><p><a href="http://www.tldp.org/HOWTO/LVM-HOWTO/whatisvolman.html">Logical Volume Management</a>. Hard disks are no longer big floppies. They are building blocks that you can just drop in to add storage to your system. Partitioning, formatting, migrating data from old small drive to new big drive -- these all go away.</p></li><li><p><a href="http://en.wikipedia.org/wiki/Adaptive_Replacement_Cache">Adaptive Replacement Caching</a>. ZFS uses a smarter cache eviction algorithm than OSX's UBC, which lets it deal well with data that is streamed and only read once. (<a href="http://drewthaler.blogspot.com/2006/06/pd-tweaker-10.html">Sound familiar</a>? It could obsolete the need for <tt>F_NOCACHE</tt>.)</p></li><li><p><a href="http://en.wikipedia.org/wiki/Snapshot_%28computer_storage%29">Snapshots</a>. Think about how drastically the <a href="http://www.usabilityfirst.com/glossary/term_583.txl">trash can metaphor</a> changed the way people worked with files. Snapshots are the same concept, extended system-wide. They can eliminate entire classes of problems.</p><p>I don't know about you, but in the past year I have done all of the following, sometimes more than once. Snapshots would've made these a non-issue:</p><ul><li>installed a software update and then found out it broke something</li><li>held off on installing a software update because I was afraid <a href="http://www.macrumors.com/2007/07/10/mac-os-10-4-10-and-macbook-airport-issues/">something might break</a></li><li>lost some work in between backups</li><li>accidentally deleted an entire directory with a mistyped <tt>rm -rf</tt> or SCM delete command.</li></ul></li><li><p><a href="http://en.wikipedia.org/wiki/Copy-on-write">Copy-on-write</a> in the filesystem makes snapshots super-cheap to implement. No, not "free", just "so cheap you wouldn't possibly notice". If you are grousing about wasted disk space, you don't understand how it works. Mac OS X uses copy-on-write extensively in its virtual memory system because it's both cheap and incredibly effective at reducing wasted memory. The same thing applies to the filesystem.</p></li><li><p><a href="http://blogs.sun.com/bonwick/entry/zfs_end_to_end_data">End-to-end data integrity</a>. Journaling is the only thing HFS+ does to prevent data loss. This is hugely important, and big props are due to Dominic Giampaolo for hacking it in. But journaling only protects the write stage. Once the bits are on the disk, HFS+ simply assumes they're correct.</p><p>But as disks get larger and cheaper, we're finding that this isn't sufficient any more. The odds of any one bit being wrong are very small. And yet the 200GB hard disk in my laptop has a capacity of about 1.6 trillion bits. The cumulative probability that EVERY SINGLE ONE of those bits are correct is effectively zero. Zero!</p><p>Backups are one answer to this problem, but as your data set gets larger they get more and more expensive and slow. (How do you back up a terabyte's worth of data? How long does it take? Worse still, how do you really know that your backup <em>actually worked</em> instead of just appearing to work?) So far, disk capacity has consistently grown faster than disk speed, meaning that backups will only continue to get slower and slower. Boy, wouldn't it be great if the filesystem — which is the natural bottleneck for everything disk-related — helped you out a little more on this? ZFS does.</p></li><li><p><strong>Combinations of the above</strong>. There are some pretty cool results that fall out of having all of these things together in one place. Even if HFS+ supported snapshots, you'd still be limited by the "big floppy" storage model. It really starts to get interesting when you combine snapshots with smart use of logical volume management. And we've already discussed how RAID-Z enhances ZFS's basic built-in end-to-end data integrity by adding stronger error correction. There are other cool combinations too. It all adds up to a whole which is greater than the sum of its parts.</p></li></ul><p>Is any of this stuff new and unique to ZFS? Not really. Bits and pieces of everything I've mentioned above have showed up in many places.</p><p>What ZFS brings to the table is that it's the total package — everything all wrapped up in one place, already integrated, and in fact already shipping and working. If you happened to be looking for a next-generation filesystem, and Apple is, you wouldn't need to look much further than ZFS.</p><h4>Still not convinced?</h4><p>Okay, here are three further high-level benefits of ZFS over HFS+:</p><ul><li><p><strong>Designed to support Unix</strong>. There are a lot of subtleties to supporting a modern Unix system. HFS+ was not really designed for that purpose. Yes, it's been hacked up to support Unix permissions, node locking, lazy zero-fill, symbolic links, hard links, NFS readdir semantics, and more. Some of these were easy. Others were painful and exhibit subtle bugs or performance problems to this day. </p></li><li><p><strong>Designed to support modern filesystem concepts</strong>. Transactions. Write cache safety. Sparse files. Extended metadata attributes. I/O sorting and priority. Multiple prefetch streams. Compression. Encryption. And that's just off the top of my head.</p><p>HFS+ is 10-year-old code built on a 20-year-old design. It's been extended to do some of this, and could in theory be extended to do some of the others... but not all of them. You'll just have to trust me that it's getting to the point where some of this stuff is just not worth the engineering cost of hacking it in. HFS+ is great, but it's getting old and creaky.</p></li><li><p><strong>Actually used by someone besides Apple</strong>. Don't underestimate the value of a shared standard. If both Sun and Apple start using the same open-source filesystem, it creates a lot of momentum behind it. Having more OS clients means that you get a lot more eyes on the code, which improves the code via bugfixes and performance enhancements. This makes the code better, which makes ZFS more attractive to new clients, which means more eyes on the code, which means the code gets better.... it's a <a href="http://en.wikipedia.org/wiki/Virtuous_circle_and_vicious_circle">virtuous circle</a>.</p></li></ul><p>Is ZFS the perfect filesystem? I doubt it. I'm sure it's got its limitations just like any other filesystem. In particular, wrapping a GUI around its administration options and coming up with good default parameters will be an interesting trick, and I look forward to seeing how Apple does it.</p><p>But really, seriously, dude. The kid is cool. Don't be like that.</p><p>Don't be a ZFS hater.</p><h4>Updates:</h4><p>MWJ's response: <a href="http://www.macjournals.com/news/2007/10/07.html#a80">You don't have to be a ZFS hater to know it's wrong for you</a>.<br />My followup: <a href="http://drewthaler.blogspot.com/2007/10/zfs-hater-redux.html">ZFS Hater Redux</a></p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com63tag:blogger.com,1999:blog-7898615.post-60768258534708882492007-10-04T16:18:00.001-04:002007-10-05T00:32:47.168-04:00MarsEdit Markdown Scripts updated to 1.0.3<!-- Generated by Markdown to HTML in MarsEdit --><p>No piece of software, <a href="http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html">however simple</a>, is bug-free.</p><p>Daniel Jalkut was kind enough to point out to me that my <a href="http://drewthaler.blogspot.com/2007/08/markdown-scripts-for-marsedit.html">Markdown scripts for MarsEdit</a> didn't deal properly with Unicode text.</p><p>Silly me. I'd forgotten that AppleScript (with its very early-1990s roots) still needs to be explicitly told not to lose data when writing out files. He offered a fix — a few «class utf8» coercions in the right place and all was well again. That was 1.0.1.</p><p>However, just immediately after release, I discovered that the scripts needed to do some more aggressive transcoding of UTF8 into ASCII in order to get Python to read the file in html2text. So I've added support for that. This slows down the HTML-to-Markdown reverse conversion a little bit, but at least it's correct now. That was 1.0.2.</p><p>Finally, later in the evening I realized it was pretty stupid to write AppleScript code to transcode the UTF8 into ASCII, because AppleScript's support for Unicode is so horribly primitive and I was doing it character by character. So I rewrote that whole section as a one-line Perl script. Now it's blazing fast. And that's 1.0.3.</p><p>I've updated the scripts. <a href="http://multisolar.com/software/MarsEditMarkdownScripts/">Download them now</a>!</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com1tag:blogger.com,1999:blog-7898615.post-42142659024846450702007-09-04T02:26:00.002-04:002008-04-08T10:29:17.387-04:00Microbenchmarking<!-- Generated by Markdown to HTML in MarsEdit --><p>I want to talk a little about a technique that can be very useful. Like all programming tools, however, it's a double-edged sword and can easily be abused. </p><p>I'm talking about <strong>microbenchmarks</strong>. A microbenchmark is a form of benchmark. Let's quickly define our terms:</p><dl><dt>Benchmark</dt><dd><p><i>noun:</i> a relative measure of the performance of an operation (or set of operations) in computer software. Many factors may be used to create this measure, such as memory use or I/O, but when unspecified the measure is usually speed.</p></dd><dd><p><i>verb:</i> to create or run a benchmark.</p></dd></dl><h4>Microbenchmarks</h4><p>Sometimes the term "benchmark" is too broad. I want to specifically talk about single benchmarks that are limited in scope. One commonly used term for this is "microbenchmark". </p><dl><dt>Microbenchmark</dt><dd><p><i>noun:</i> a benchmark that measures the performance of a single operation which is a very small portion of a larger system.</p></dd><dd><p><i>verb:</i> to create or run a microbenchmark.</p></dd></dl><p>I would consider each of the following to be an example of a microbenchmark:</p><ul><li><p><strong>Implementation comparisons</strong>. Suppose you are choosing between multiple implementations of the C standard library routine <code>strcmp()</code>. You might use a microbenchmark to compare different implementations against each other until you find the one that's right for you.</p></li><li><p><strong>Equivalent function comparison</strong>. Sometimes there's more than one way to achieve your goal. If you want to know which is faster, you might use a microbenchmark to compare the different functions.</p></li><li><p><strong>Inter-language primitive comparisons</strong>. Microbenchmarks are often used to compare programming languages. For example, Java, C++, and C# are often microbenchmarked to see which has the faster string comparison, stack allocation, heap allocation, and so on.</p></li><li><p><strong>Individual aspects of a large system's performance</strong>. Examples might include adding a row to a database table, sorting a large list of input files, or even application launch time. These aspects may be measured in isolation (i.e., without a strict performance target) with the presumption that speeding them up is generally useful, since the end user's experience is comprised of lots of these small operations.</p></li></ul><p>I think the last example above is the most generic description of a microbenchmark, because it encompasses the others. When you are benchmarking <code>strcmp()</code>, you are really measuring an individual aspect of the C library's performance. And when you are comparing language primitives, you are again measuring an individual aspect of the language's performance.</p><p>The prefix "micro-" is relative, of course. If your job description is "Chief Programmer: strcmp()", then measuring the performance of <code>strcmp()</code> is simply benchmarking, not microbenchmarking. But if you are working on a large modern GUI application for a consumer OS, measuring the performance of <code>strcmp()</code> becomes a microbenchmark because it's such a small part of your overall system.</p><h4>Losing Track of the Macro</h4><p>Before I start talking about how to do microbenchmarks, there's an important point to be made. Improperly applied microbenchmarks can actually be <em>hazardous</em> to real-world performance.</p><p>Benchmarking goes hand-in-hand with optimization when it's done correctly. You benchmark first, and then optimize. Similarly, microbenchmarking goes hand-in-hand with microoptimization. And microoptimization is <a href="http://en.wikipedia.org/wiki/Optimization_%28computer_science%29#When_to_optimize">rarely a good idea</a>.</p><p>That's not to say that microbenchmarks are bad. They can be really useful when applied correctly. I remember the competitions at Apple to create the fastest <a href="http://developer.apple.com/documentation/mac/Memory/Memory-103.html">BlockMove</a> for PowerPC, which were often repeated with each new generation of processor. Since it was one of the most heavily-used system calls in the Mac OS, each incremental improvement made the OS faster. Many individual benchmarks, such as drawing and text manipulation, got faster whenever BlockMove was improved.</p><p>The danger comes not from the microbenchmarking itself. The real problem occurs when you focus so much on the micro that you forget about the big picture. There are three main negative outcomes possible:</p><div style="margin:40px; padding:10px 45px 10px 20px; margin:15px; font-size:90%; background:#FFAAAA; border:1px solid black;"><p style="font-size: 110%; color:#880000"><b>Dangers of Microbenchmarking and Microoptimization</b></p><ul><li><p><strong>Wasting development time</strong>. Newbie programmers sometimes burn weeks optimizing something that doesn't really need optimizing. This doesn't matter much when you're doing it as a hobby, but it matters a lot when you're in a real job.</p></li><li><p><strong>Making something else slower</strong>. Sometimes performance can be like a carpet. Push it down over here, and it pops up over there. If the operation that you're microbenchmarking does not crop up often in real-world scenarios, you may find that all your micro-optimizing actually <em>decreases</em> your real-world performance.</p></li><li><p><strong>Introducing bugs</strong>. Sloppy optimization can be worse than no optimization. Your code might work today, but the trick you used might not be future-proof.</p></li></ul></div><h4>Performance is Chunky</h4><p>There are two important lessons that I've learned about software performance over the years:</p><p>Lesson 1: <strong>Performance is "chunky"</strong>. Not all parts of the code contribute equally to the software's speed. A small piece of code might turn out to be a very big chunk of the performance, and a big piece of code might be almost immaterial. You need to know what your chunks look like before you can optimize intelligently.</p><p>Lesson 2: <strong>Design trumps everything</strong>. Choosing the right design or algorithm for your code is far more important than almost any microoptimization you can make. If your code calls <code>strcmp()</code> 4 million times in a loop, you're better off changing your design to call it less often. There's no reason to waste time looking for a faster <code>strcmp()</code>. </p><p>From these two lessons we can pretty easily derive the types of optimizations that work best. Here they are, from most effective to least effective:</p><div style="margin:40px; padding:10px 45px 10px 20px; margin:15px; font-size:90%; background:#FFFFCC; border:1px solid black;"><p style="font-size:110%"><b>Ordered Rules for Optimization</b></p><p>Want to make your code faster? Follow these rules in order.</p><ol><li><p><b>Design for efficiency</b>. Understand the real task. Eliminate redundancy. Understand how your algorithm is performing, and the ways it might not be optimal. Redesign the whole thing until it <i>is</i> optimal.</p></li><li><p><b>Optimize areas where your code spends a lot of time</b>. Sometimes there is an inner loop which is repeated millions of times. The first answer is always rule #1: "don't do that" — try to redesign your code to reduce the number of times you perform that operation. But if it truly can't be avoided, then go ahead and expend some effort on speeding it up.</p></li><li><p><b>Microoptimization</b>. Pick a single operation and make it faster in isolation. This is almost always the wrong thing to do.</p></li></ol></div><p>Why are microbenchmarking and microoptimization almost always wrong? Because you should be taking care of #1 or #2 first. And the fundamental essence of programming is that the first two are never complete. </p><h4>When should you microbenchmark?</h4><p>If you are writing part of an operating system, a virtual machine, or the runtime for a programming language. Compiler writers may also microbenchmark the <em>output</em> of their compiler.</p><p>Very occasionally, it might be useful to do it as part of the first two optimization tasks. Perhaps you're choosing between different algorithms, one which involves calling <code>functionA()</code> a thousand times, and one which involves calling <code>functionB()</code> a thousand times. Rather than writing two complete implementations and comparing them, it might be instructive to do a quick microbenchmark to see which of the two is faster in isolation.</p><p>You can also do it for your own amusement and education, or for a <a href="http://mikeash.com/blog/pivot/entry.php?id=29">blog entry</a>. While not terribly useful, it can be informative and teach you a thing or two about your <acronym title="operating system">OS</acronym>.</p><h4>How to write a microbenchmark</h4><p>With all that said, let's get down to the details. Suppose that you eventually find yourself in a position where you really do need to run a microbenchmark.</p><p>I use a ten-step process:</p><ol><li><p><strong>Consider all the factors that may impact performance.</strong> There may be non-obvious considerations like memory alignment, cache characteristics, or data set size. Decide exactly how you want to test your operation with those factors in mind.</p></li><li><p><strong>Write a loop to perform the operation a large number of times.</strong> Any single measurement might be way off, because your computer is busy doing all sorts of things like processing interrupts in the background that are out of your control. So you need to average over a longish interval. Try starting with about a hundred thousand iterations, then add multiples of ten until you wind up with a total runtime of a second or two.</p></li><li><p><strong>Use a high-resolution timer to record the start and stop time.</strong> Your data is only as good as your timer. Find the best one available. On Mac OS X that's <a href="http://developer.apple.com/qa/qa2004/qa1398.html"><code>mach_absolute_time()</code></a>, and on Windows it's <a href="http://msdn2.microsoft.com/en-us/library/ms632592.aspx"><code>QueryPerformanceCounter()</code></a>. Other platforms usually have an equivalent high-resolution timer. Call it only twice: once before the big loop, and once after.</p></li><li><p><strong>Write code to compute the result.</strong> The approximate time it takes for a single operation will be <code>elapsedTime / numberOfIterations</code>. The <code>elapsedTime</code> is generally <code>(stopTime - startTime) / timerFrequency</code>. Watch out for integer overflow and floating-point precision loss: it's easiest to just use double-precision math. </p></li><li><p><strong>Consider whether you should compile your code at the highest optimization level available.</strong> Compilers generate significantly slower code when optimization is off. You're almost certainly interested in the performance of the fully optimized build rather than the unoptimized debug build, but optimization can introduce its own difficulties. It depends on what exactly you're benchmarking.</p></li><li><p><strong>Compile, then disassemble your test to make sure it's really doing what you think it's doing.</strong> This step is <em>non-negotiable</em>!! If you can't read assembly, you shouldn't be doing microbenchmarking. Compilers can be tricky and there's no guarantee that it's actually doing what you think it's doing until you look. If you are testing <code>strcmp()</code>, for example, you might find that the compiler has decided to optimize out all ten million calls in your inner loop because you're using a string constant instead of a variable. Or perhaps your ten million iterations of <code>input = input + 1</code> are being optimized out to <code>input = input + 10000000</code>. If this is happening to you, you'll need to figure out a way to force the compiler to do what you want. With gcc, for example, you might need to link functions in via separate modules to prevent inlining, or specify additional flags on the command line.</p></li><li><p><strong>Quiesce your system.</strong> You don't have to shut everything down, but do make sure that you're not running under abnormally heavy load. Most systems these days have a CPU meter which can tell you what's going on. If you're writing code on an embedded system, make sure that any asynchronous startup operations (like initializing the network stack) have finished before you begin.</p></li><li><p><strong>Run the test and get the results.</strong> If it runs too quickly or too slowly, you might need to adjust your iteration count and try again. If you get what looks like a good result, there's one more step:</p></li><li><p><strong>Run the test several more times and make sure your result is reproducible.</strong> This will also give you an idea of the typical error in your measurement. </p></li><li><p><strong>If you support different platforms or processors, run the test on each one.</strong> Sometimes constructs which work well with one processor are the worst-case for another. Occasionally operating systems will change the implementation of their standard library functions enough to perturb performance. Don't assume that just because it's faster on one configuration that it will always be faster everywhere.</p></li></ol><h4>Code Sample</h4><p>Here's a piece of sample code I wrote to microbenchmark the speed of a function call on Mac OS X. I've removed the function body in order to simply show the overall technique.</p><pre class='sh_cpp'>/* foo.cpp */
#include <stdio.h>
#include <mach/mach_time.h>
int testfunc(int arg1, int arg2);
int main(int, const char **)
{
struct mach_timebase_info tb;
uint64_t start, stop, elapsed;
double seconds;
const int iterations = 300000000;
int result = 0;
mach_timebase_info(&tb);
// Run the test.
start = mach_absolute_time();
for (int i=0; i<iterations; ++i)
result = testfunc(result,i);
stop = mach_absolute_time();
elapsed = stop - start;
// Print results.
seconds = ((double)elapsed * tb.denom / tb.numer) / (1000*1000*1000);
printf("%d iterations = %0.9lf seconds\n", iterations, seconds);
printf("1 iteration = %0.9lf seconds\n", seconds/iterations);
return 0;
}</pre><pre class='sh_cpp'>/* bar.cpp */
int testfunc(int, int)
{
return 0;
}</pre><p>Notice how the function that it's calling is in a completely different source file? That's because on my first attempt gcc's inlining optimizer actually completely eliminated the function call. This was only visible upon inspecting the disassembly (step 6). Putting the target function in another module was the easiest way to stop the function from being inlined. (Yes, I tried <code>-fno-inline</code> and <code>__attribute__((noinline))</code>. Neither has the desired effect.)</p><p>I've chosen to ignore the overhead of the loop itself in this measurement. It's essentially negligible for most types of microbenchmarks. Furthermore, as long as you wind up comparing the result against another test run with identical loop overhead, it will simply cancel from both sides of the equation.</p><p>So that's it. Anyone have any interesting situations where you've found that you needed to run a microbenchmark? Does your technique differ from mine? Found any unexpected results? Let me know in the comments.</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com2tag:blogger.com,1999:blog-7898615.post-80116021258296594552007-08-31T19:52:00.001-04:002007-08-31T21:55:22.814-04:00What should TV shows cost?<!-- Generated by Markdown to HTML in MarsEdit --><p>While reading <a href="http://daringfireball.net/linked/2007/august#fri-31-apple_nbc">Daring Fireball</a> today, I saw that Apple has posted a <a href="http://www.apple.com/pr/library/2007/08/31itunes.html">press release</a> scolding NBC for wanting to more than double the cost of their content.</p><blockquote>Apple® today announced that it will not be selling NBC television shows for the upcoming television season on its online iTunes® Store (<a href="http://www.itunes.com/">www.itunes.com</a>). The move follows NBC's decision to not renew its agreement with iTunes after Apple declined to pay more than double the wholesale price for each NBC <acronym title="television">TV</acronym> episode, which would have resulted in the retail price to consumers increasing to $4.99 per episode from the current $1.99. ABC, CBS, FOX and The CW, along with more than 50 cable networks, are signed up to sell <acronym title="television">TV</acronym> shows from their upcoming season on iTunes at $1.99 per episode.</p> <p>'We are disappointed to see NBC leave iTunes because we would not agree to their dramatic price increase,' said Eddy Cue, Apple's vice president of iTunes. 'We hope they will change their minds and offer their <acronym title="television">TV</acronym> shows to the tens of millions of iTunes customers.'</p></blockquote><p>First of all, I'm totally amused that Apple is dragging this dirty laundry out in public to shame NBC. It's a smart business move, and I have no objections to it: I just get a kick out of big corporations fighting.</p><p>Second, it brings up an excellent question about the value of content. Particularly content that is sometimes expensive to produce. What exactly do consumers perceive as the "right price" for something like a <acronym title="television">TV</acronym> show?</p><h4>What Content Producers Think</h4><p>I think content producers operate on a couple of different mental models when it comes to pricing their content for digital distribution. Most of these models are terribly flawed, because they're not looking at the consumer's point of view.</p><p> <strong>Production Cost</strong>: "The more expensive it is to produce, the higher the price should be." </p><p> <strong>Length</strong>: "A one-hour <acronym title="television">TV</acronym> show should cost around the same as a one-hour <acronym title="compact disc">CD</acronym>."</p><p> <strong>Cross-Media Comparisons</strong>: (To the most expensive alternative.) "We can sell a full season of <acronym title="digital versatile discs">DVDs</acronym> for $60, which works out to $5 per show."</p><p> <strong>Threat of Withholding</strong>: "You're going to buy it at whatever price we ask, or else you won't get it at all."</p><p>These models probably only make sense to you if you're a content producer talking about your own content. As a consumer, they probably make you angry.</p><h4>What Consumers Think</h4><p>As a consumer, these are the things I think about when I am considering buying content.</p><p> <strong>Total Usage Time</strong>: "How much total time will I spend enjoying this content?"</p><p>Total usage time is very different from the length of the content. Total usage time is equal to the length, <em>multiplied by</em> the number of uses I expect to get from it.</p><p>For a <acronym title="compact disc">CD</acronym> or album, the total usage time is vastly different from that of a <acronym title="television">TV</acronym> show. When I buy music, I expect to listen to it again and again. Most <acronym title="television">TV</acronym> shows I only watch once. Sure, if it's a download I <em>could</em> watch it again and again, but odds are that the 45 minutes of content in your hour-long show is only going to get 45 minutes of my time. Or less. Movies and concert videos are somewhere in the middle: particularly good movies will sometimes get a second or third viewing, but still nothing approaching what a good <acronym title="compact disc">CD</acronym> gets.</p><p> <strong>Quality and Extras</strong>: "Is this particularly high-quality content? Does it have something extra that I'm interested in, like commentary or subtitles?"</p><p>Although this isn't my primary factor, I'm generally willing to pay a little more for content that goes the extra mile. Sometimes that means higher resolution (Blu-Ray vs <acronym title="Digital Versatile Disc">DVD</acronym>, or <acronym title="Super Audio CD">SACD</acronym> or <acronym title="Digital Versatile Disc">DVD</acronym>-Audio vs <acronym title="compact disc">CD</acronym> vs <acronym title="MPEG Layer 3">MP3</acronym>), sometimes that means particularly extraordinary special effects, sometimes it's commentary from a director or actor that I admire, sometimes it's a behind-the-scenes "Making Of" featurette. </p><p>For example, I almost never buy TV shows on <acronym title="Digital Versatile Disc">DVD</acronym> because they're just too expensive. But in the few rare cases where I do, it's because it's a show that I particularly enjoy and would like in a high-quality format with lots of extras. </p><p> <strong>Cross-Media Comparisons</strong>: (To the least expensive alternative.) "Can I get everything I want somewhere else, for less money?" </p><p>Sometimes I simply want to catch up on a show's plot developments. Reality shows are a good example: I sure don't watch them for the quality of the writing. If I'm traveling and I miss a showing of <a href="http://www.americanidol.com/">American Idol</a> or <a href="http://www.scifi.com/superhero/">Who Wants to Be A Superhero?</a>, I'm not going to spend any significant amount of money at all on finding out who got kicked off this week. I'd rather just look it up online.</p><p>If it's a show like <a href="http://www.scifi.com/battlestar">Battlestar Galactica</a> that I actually do want to watch and appreciate, well, I own a <acronym title="digital video recorder">DVR</acronym> which lets me record the "free" showings from network or cable TV. Chances are unless I'm in a big hurry, I'll just watch the version that was automatically recorded for me once I get home.</p><p>This is also where piracy comes in. As Steve Jobs <a href="http://news.bbc.co.uk/2/hi/entertainment/4265434.stm">has said</a>, content producers have to compete with piracy as a business model. Video-sharing sites and BitTorrent servers may offer the content at no cost. Piracy is a funny thing. It isn't attractive to most people ... until you start withholding or overcharging for content. Then it spikes. Personally I don't have any qualms about watching all or part of a TV show on <a href="http://youtube.com/">YouTube</a> if it isn't available anywhere else. </p><p>You can go into great depth parsing the legal arguments around both of those last two, but you'll be wasting your time. Consumers don't. The fact is that in our minds — yours and mine — TV show downloads are essentially competing with "free", twice over.</p><p> <strong>Convenience vs Importance</strong>: "Is the price I'm paying (in both money and inconvenience) proportionate to how much I care?"</p><p>Sometimes I'm only mildly interested in your content. I think most web browsing falls under this umbrella, which is why it's so difficult to make money by charging for content on the web. If I'm only mildly interested, I'm not going to pay you anything at all for it, but I might spend a few minutes watching it ... <em>if</em> it's free and easy to do so. </p><p>Of course, there are times when I'm <em>extremely</em> interested in your content. I'm generally more willing to pay money for it in that case. But the number of things that are quite that important to me necessarily has to be kept very small — because I don't have an infinite amount of money. (<strong>IMPORTANT NOTE</strong>: If you would like to <em>give</em> me an infinite amount of money, e-mail me and we'll talk.)</p><h4>Resolving the difficulties</h4><p>That's it. Those four criteria are what I use to evaluate prices as a consumer, and I would be willing to bet that I'm not alone. Realistically, I think the consumer models are what will ultimately drive the cost. </p><p>So what's the fair price for a TV show? If you go by total usage time, the value of a TV show is <em>substantially less</em> than the value of a single track of music, despite the fact that it costs more to produce. The convenience factor of getting it whenever you want it may bump up the price you're willing to pay, but I think that $2 is actually already too expensive in the minds of many consumers. They'd be better at $1 ... or even free.</p><p>What's the fair price of a TV show to you?</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com3tag:blogger.com,1999:blog-7898615.post-60106840601628571502007-08-26T12:57:00.001-04:002007-10-04T16:15:54.331-04:00Markdown Scripts for MarsEdit<!-- Generated by Markdown to HTML in MarsEdit --><p>I've created a few AppleScripts for <a href="http://red-sweater.com/marsedit">MarsEdit</a> to simplify the process of using <a href="http://daringfireball.net">Markdown</a> to post to any weblog (like, say, <a href="http://blogger.com/">Blogger</a>) that doesn't natively support it. </p><h4>Translate Markdown to HTML</h4><p>This script takes text written in <a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> and translates it into HTML. Extraneous line breaks are eliminated, because many blog hosts like to translate them into <code><br /></code> tags.</p><p>This works particularly well because MarsEdit has native support for previewing content written in Markdown. I normally use the Markdown preview mode while composing a post, then convert it to HTML just before posting.</p><p>But wait, you say: what if you need to edit a post?</p><p>No problem, says me. Then you use the other script.</p><h4>Translate HTML to Markdown</h4><p>This script uses Aaron Swartz's <a href="http://www.aaronsw.com/2002/html2text">html2text</a> to translate the post from HTML back into Markdown. It works on any HTML post, not just ones that you've created with the other script. Then you're free to edit the post, convert it back to HTML, and repost it.</p><h4>Updated: Now with Unicode support</h4><p><em>Update, Oct 4 2007</em>: MarsEdit's author, Daniel Jalkut, alerted me to the fact that these scripts had problems with non-Roman text and offered a fix. Sure enough, I'd forgotten that AppleScript needs special care to do the right thing and handle text files as UTF-8. I've updated them appropriately.</p><h4>Get them now!</h4><p>Interested? Download the scripts now!</p><p><a href="http://multisolar.com/software/MarsEditMarkdownScripts/">MarsEdit Markdown Scripts</a></p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com5tag:blogger.com,1999:blog-7898615.post-14947722762229528422007-08-19T14:54:00.001-04:002007-08-27T00:41:47.028-04:00BASIC for the iPhone<!-- Generated by Markdown to HTML in MarsEdit --><p>This year <a href="http://c4.rentzsch.com/1/">C4[1]</a> played host to <a href="http://rentzsch.com/c4/ironCoderLive">Iron Coder Live</a>. The API was "iPhone" and the theme was "conspiracy". The <a href="http://macdaddyworld.com/?p=38">winner</a> was well-deserved. But I had fun doing a hack of my own.</p><p>There was just one problem: I don't have an iPhone.</p><p>As I was driving from Cleveland to Chicago, I had a lot of time—about five hours—to think about what I might do for the contest. Without an actual iPhone it had to be something that could be largely developed offline and only run on the phone at the contest. That meant that I would need to stick to the, ahem, <a href="http://developer.apple.com/iphone/">"official API"</a> of the iPhone: <acronym title="HyperText Markup Language">HTML</acronym> and JavaScript.</p><p>Although the phone is cool, I think it's even cooler that a <a href="http://iphone.fiveforty.net/wiki/index.php?title=Main_Page">whole community</a> has built up to create the <acronym title="software development kit">SDK</acronym> that Apple failed to provide. After talking with some old friends at the conference I decided that it would be fun to join the conspiracy and create my own <acronym title="software development kit">SDK</acronym> for the iPhone, offering the ultimate retro-cool language: <a href="http://en.wikipedia.org/wiki/BASIC_programming_language">BASIC</a> for the iPhone.</p><p>The version I showed at the conference garnered a very respectable 5th place, which I'm more than satisfied with considering its far more polished competition. I've since cleaned it up, <a href="http://gnu.org/licenses/gpl-2.0.html">GPLed</a> it, and rechristened it. And here it is:</p><h4>ippleSoft BASIC</h4><p>The interface has been scaled for the iPhone, but it works just fine in Safari and Firefox.</p><ul><li><a href="http://multisolar.com/ipb">ippleSoft BASIC for the iPhone</a> - Run it now!</li><li><a href="http://multisolar.com/ipb/HolyBASIC.js">View the source</a></li><li><a href="http://multisolar.com/ipb/help">Command reference</a> - also available by entering HELP at the prompt.</li></ul><h4>Notes</h4><p><em>Naming</em>: I tried to pick a name that wouldn't infringe on anyone's existing trademark. That's harder than you might think: "iPhone BASIC" would surely lead to a cease-and-desist letter from the hounds. iBASIC, IP-BASIC, etc were all taken. Then I ran into a stroke of luck: It turns out "AppleSoft" is no longer a registered trademark of Apple. They let it expire in 2001. Thus: <strong>ippleSoft</strong>.</p><p><em>Entirely JavaScript, entirely free</em>. I've made it available under <acronym title="GNU General Public License">GPL</acronym> v2. There's no public repository yet, but hey, it's <acronym title="GNU General Public License">GPL</acronym>, so you can go and create one yourself. I've released code into the public domain before, but this is the first project I've ever released under <acronym title="GNU General Public License">GPL</acronym>.</p><p><em>I'm not a JavaScript programmer</em>. I learned about the language and tried to follow best practice, though. Well, as much as I could during a single beer-soaked weekend. </p><p><em>Autoscroll</em>: The output display will autoscroll in Mac Safari, but not iPhone Mobile Safari. You can flick the output display to scroll it, though. If anyone with an iPhone has a suggestion on how to make it autoscroll properly please let me know!</p><p><em>Language</em>: For now I've kept it pretty close to a strict subset of AppleSoft BASIC. There's a lot it doesn't do yet: graphics and text positioning are not supported, and neither are INPUT or GET. Those are pretty high on the list of priorities though.</p><h4>One final thought</h4><p>You know what? <strong>Text-based interfaces suck on the iPhone</strong>. There's just no getting around this. It's not the output so much as the input. The iPhone feels great when you're pushing buttons and flicking the display to scroll. But the keyboard is really lame. </p><p>I'm not sure if that's a feature or a bug for <a href="http://multisolar.com/ipb">ippleSoft BASIC</a>. Personally I find it kind of perversely amusing to use the iPhone to run a language originally designed for <a href="http://en.wikipedia.org/wiki/Teleprinter">teletypes</a>. But it would be interesting to explore ways to take the text out of BASIC.</p><p>Loading and running programs from elsewhere on the web would be a natural. A keyword-board like the one on the <a href="http://www.mainbyte.com/ts1000/">Timex-Sinclair TS1000</a> might be useful if you really must write code on the iPhone. INPUT and GET may need to be supplemented with some type of dialog interface. Anything else?</p><p>What do you think?</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com1tag:blogger.com,1999:blog-7898615.post-31327531718728192402007-03-23T19:26:00.001-04:002008-04-08T10:29:39.586-04:00Crazy Del.icio.us<p>Do you use <a href="http://del.icio.us/">del.icio.us</a>? If not, you might want to. I've been using it for a while now, and the more I use it the more I like it. </p>
<h4>What is del.icio.us?</h4>
<p>It's a social bookmarking site. Here's a description <a href="http://del.icio.us/about/">in their own words</a>.</p>
<h4>Why don't you just tell me what social bookmarking is?</h4>
<p>Okay, fine. Really, it's exactly what it sounds like.</p>
<p>Just like your web browser's "Bookmarks" menu, you post links that you want to remember to your account. Unlike your web browser's "Bookmarks" menu, the links are <i>shared</i> and visible to anyone who wants to find them. You can even see what your friends are bookmarking, and turn around and bookmark the same sites yourself if you find them interesting.
</p><p>
When you add a bookmark, you can provide a brief comment or excerpt to help remind you what it is. You can also assign <a href="http://del.icio.us/help/tags">tags</a> to help categorize links. Since it's public, your list of bookmarks is accessible from <i>any</i> computer you might be at -- not just your home computer.
</p><p>
For example, here's my del.icio.us, containing a bunch of random links that I thought were worth remembering for one reason or another:</p>
<ul><li><a href="http://del.icio.us/drewthaler">http://del.icio.us/drewthaler</a></li></ul>
<p>Notice the nice, easy to remember URL. That's very typical of del.icio.us. Also, take a look at the links on the right side of that page -- I tag everything, and those links make it easy to find all links with a certain tag. Maybe you're only interested in my <b>Apple</b> links, or my <b><acronym title="PlayStation 3">PS3</acronym></b> links:</p>
<ul><li><a href="http://del.icio.us/drewthaler/Apple">http://del.icio.us/drewthaler/Apple</a></li><li><a href="http://del.icio.us/drewthaler/PS3">http://del.icio.us/drewthaler/PS3</a></li></ul>
<p>You can also combine tags. Here are my links that are tagged with both <b>programming</b> and <b>humor</b>:</p>
<ul><li><a href="http://del.icio.us/drewthaler/programming+humor">http://del.icio.us/drewthaler/programming+humor</a></li></ul>
<p>Easy, huh? And the best part (for me) is that if I want to remember a link I saved six months ago, I can do the same thing. I just hop over to my page and zoom down through the categories until I find it. Heck, I don't even have to be on my own computer!</p>
<h4>Isn't there some other site that does this?</h4>
<p>Yes and no. According to Wikipedia's entry on <a href="http://en.wikipedia.org/wiki/Social_bookmarking">social bookmarking</a> there have been several similar services over the years, going back to 1996 or so. But most of them died in the dot-com boom and bust. <a href="http://del.icio.us/">del.icio.us</a> was founded in 2003, and is probably one of the earliest "Web 2.0" sites. It was recently acquired by Yahoo!, so it's not going anywhere.</p>
<p>You might be thinking of <a href="http://digg.com/">Digg</a> or <a href="http://reddit.com/">Reddit</a>, which are <a href="http://en.wikipedia.org/wiki/Social_news">social news</a> sites. But that isn't quite the same thing. In fact, I find that social news starts out cool but quickly gets annoying. Sites are inevitably biased by the demographics of the top users, and the comment threads are worse than useless. del.icio.us has its own version of social news, in the <a href="http://del.icio.us/">hotlist</a> and <a href="http://del.icio.us/popular">popular</a> links accessible from the main page. But you can also ignore them entirely.</p>
<p>You might also be thinking of <a href="http://twitter.com/">Twitter</a>, but that's more of a lifeblogging site. You could abuse Twitter to create a sort of social bookmarking system, like <a href="http://pbones.com/news/newsitem.php?blobDate=1172253218">someone I know did</a>, but that's not really the site's intention. </p>
<p>It also sounds a little like <a href="http://www.delicious-monster.com/">Delicious Library</a>, but there's absolutely no connection. :-)</p>
<h4>What else makes it cool?</h4>
<p>You can subscribe to the links of other people -- both via the web and via <acronym title="Really Simple Syndication">RSS</acronym>. So if you find interesting people who have accounts, you can see what they're paying attention to. You can <a href="http://del.icio.us/network/drewthaler">view my network</a> if you want to.</p>
<p>People whose links I follow include:</p>
<ul><li><a href="http://del.icio.us/wearehugh">Mark Pilgrim</a>, known for his "Dive Into" series on Greasemonkey, accessibility, and more. Mark also aggregates his links on <a href="http://diveintomark.org/">diveintomark</a>, but I follow them on del.icio.us.</li><li><a href="http://del.icio.us/rentzsch">Jon Rentzsch</a>, of <a href="http://redshed.net/">Red Shed Software</a> and <a href="http://c4.rentzsch.com/">C4</a>.</li><li><a href="http://del.icio.us/mezzoblue">Dave Shea</a>, web designer and creator of <a href="http://csszengarden.com/">CSS Zen Garden</a>.</li><li><a href="http://del.icio.us/danieljalkut">Daniel Jalkut</a>, another former Apple employee and owner of <a href="http://www.red-sweater.com/">Red Sweater Software</a>.</li><li><a href="http://del.icio.us/Rosyna">Rosyna</a> from <a href="http://unsanity.com/">Unsanity</a>, an old friend from #macdev on IRC.</li><li><a href="http://del.icio.us/gruber">John Gruber</a> of <a href="http://daringfireball.net">Daring Fireball</a> used to use his account, but stopped using it once he realized he could make people pay him for the RSS feed instead. :-) </li></ul>
<h4>What do you like most about it?</h4>
<p>Three things.</p>
<p>First, it provides a nice sort of link-blog functionality without having to spam everyone with a ton of small posts. This blog, as I've <a href="http://drewthaler.blogspot.com/2004/11/echo-chamber.html">said before</a>, is not a link blog. It's more of an essay blog. If you want random links from me these days, however, you can get them -- just go to <a href="http://del.icio.us/drewthaler">my del.icio.us</a>.</p>
<p>Second, it gives me a way to offload some of my memory to a computer. It's not as extreme as some of the current experiments in lifeblogging, but it's a good compromise for me. And since my bookmarks are on a public server run by Yahoo! I don't really need to worry too much about backing them up or continually copying them from one machine to another. Someone else handles that.</p>
<p>Third, I like checking out the bookmarks of other people. It's pretty nifty to fire up my RSS reader and see that Rosyna has posted some crazy <a href="http://www.youtube.com/watch?v=gDh__j3h1qE">Japanese Spider-Man video</a>, or that Mark Pilgrim saved an interesting <a href="http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss">article</a> about XML , or that Rentzsch just saved a nifty <a href="http://iconfamily.sourceforge.net/">Mac programming link</a>. </p>
<p>Are you using del.icio.us? If so, post a comment or drop me an email letting me know your username.</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com4tag:blogger.com,1999:blog-7898615.post-34992477358142381182007-02-05T17:55:00.000-05:002007-09-04T03:46:24.735-04:00Oh, baby baby<p>Please welcome my son <b>Archer Douglas Thaler</b>, born on Jan 30th 2007 at 5:10am. He was 7lbs 11oz, 20 inches long, and came out pink and screaming -- just the way they're supposed to.</p>
<a href="http://homepage.mac.com/drewthaler/archer/archer-Images/1.jpg" target="_blank"><img src="http://homepage.mac.com/drewthaler/archer/archer-Thumbnails/1.jpg" width="300" height="225" alt="Archer Douglas Thaler, getting weighed for the first time" /></a><a href="http://homepage.mac.com/drewthaler/archer/archer-Images/2.jpg" target="_blank"><img src="http://homepage.mac.com/drewthaler/archer/archer-Thumbnails/2.jpg" width="300" height="225" alt="Archer Douglas Thaler, sleeping" /></a>
<div style="clear: both"></div>
<p>There are a <a href="http://homepage.mac.com/drewthaler/archer/">few more pictures</a> available. Today he's exactly one week old. He's been a great kid so far, not fussy at all and often sleeping at night for a good 4-5 hours at a stretch. His name is a tribute to his great-grandfather Orion, as well as just a cool name that we liked.</p>
<p>I'll be a little busy for a while between work and family, but I hope to get back into posting soon. Lots of good technical stuff to talk about.</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com5tag:blogger.com,1999:blog-7898615.post-84543050526442314782007-01-06T13:46:00.000-05:002007-01-06T16:30:46.557-05:00Better Food, Just as Fast<p>Do you find yourself going out to dinner a lot, or bringing home takeout food more often than you should?</p><p>We sure do. Even though we've been making an effort to eat lighter meals at healthier places -- our faves from around here include <a href="http://www.panera.com/">Panera</a>, <a href="http://www.chipotle.com/">Chipotle</a>, <a href="http://www.zoup.com/">Zoup!</a>, and our local <a href="http://www.heinens.com/">Heinen's</a> grocery store -- it's just not the same as cooking and eating at home. There's a real difference in quality, quantity, and healthiness. And it's expensive, too!</p><p>Worse yet, it's a slippery slope. Once you get into the habit of getting takeout for dinner, it's easy to slip and start eating less healthy fast food too. (<em>cough</em> KFC's beautiful-but-deadly <a href="http://www.kfc.com/menu/bowls_potato.asp">mashed potato bowls</a>, I'm looking at you.)</p><p>My wife Nancy recently came up with a solution. She'd heard about this place nearby called <a href="http://www.simplydonedinners.com/">Simply Done Dinners</a>. Apparently -- and I had no idea this even existed -- places like this are a growing trend around the country. It's basically a place where you can come in, put together homemade dinners, bring them home, and toss them in the freezer to cook later. </p><a href="http://www.simplydonedinners.com/">Simply Done Dinners</a> is local to the Cleveland area, and they have only four stores right now: Parma, North Olmsted, Twinsburg, and Medina. If you're not from around here, don't worry. There's probably a similar store near you. Take a look at this <a href="http://www.easymealprep.com/main/direct02.php">HUGE directory of easy meal-prep stores</a>. See? I told you it was a growing trend. :-)<h4>Our First Taste</h4><p>The first time we tried it out, Nancy simply ordered six dinners online ($109) and had the store in Twinsburg assemble them ($29) so that all she had to do was pick it up. There was <i>no</i> preparation involved: she simply walked in and grabbed the prepared dinner packages. We got one of each of the following:</p><ul><li>Apple Pork Chops with Sweet Potatoes</li><li>Cheeseburger Noodle Casserole</li><li>Cod Provencal</li><li>Lemon Garlic Chicken</li><li>Pasta Broccoli Bake</li><li>Southwestern Meatloaf</li></ul><p>Each dinner package is designed for 4-6 people. For our family of three -- papa bear, mama bear, and baby bear, with proportional appetites -- we found that we got just under two meals per person out of each. Either two dinners from each, or dinner plus a tasty lunch of leftovers the next day. The meatloaf actually lasted much longer: I used it for lunch sandwiches for almost a week, but that was balanced out by the pork chops which got left out for too long and had to be thrown away. All in all, I figure that we got roughly 30 meals from the order.</p><p>If you do the math, that works out to $4.60 per meal per person: a little more expensive than buying all the ingredients yourself, but without <i>any</i> of the hassle. It's also about what you'd pay for a fast food "value meal", and maybe 50 cents to a dollar more than a frozen TV dinner at the grocery store. Really, a surprisingly good value for the kind of quality that you get.</p><p>Of course, these are just main courses and don't come with sides. (Some other chains do provide sides, but they also charge a little more.) So we'd add rolls, or a salad, or some veggies as needed. That adds a bit to the cost-per-meal, strictly speaking, but we already had all that stuff around the house anyway so we didn't factor it in.</p><p>The dinners come in a big disposable pan, the kind that you can just toss in the oven. There's a sticker with cooking directions on the side. Some needed baking, some needed broiling, and other stuff could be done in a crock-pot. (We avoided the crock-pot ones the first time, since we didn't have one.) In all cases it's pretty much drop-it-in-and-wait; no skills required. A bachelor could do it with one hand tied behind his back. :-) They're all designed to be stored in the freezer, but you have to remember to pull them out into the fridge to thaw 48 hours before you want them. We pulled out one or two a week, and eventually started a rotation where every time we used one we'd move another into the fridge so that it would be ready in a couple of days.</p><p>What about the taste? Well, we have a diverse set of tastebuds in our family: I'll eat anything, but Nancy can be a picky eater (to put it mildly). And even though Olivia's pretty darn adventurous for a 10-year-old kid, eating sushi and cow tongue among other things, she doesn't like everything. Sometimes she opts out of dinner and just gets a veggie burger instead.</p><p>But even in our divided household everyone unanimously agreed: <b>the food was delicious!</b> I guess that's the benefit of having a professional chef selecting the recipes.</p><p>Better still, it was all stuff that we either wouldn't have made, or something that was a unique flavor that we probably wouldn't have thought of. So it didn't actually conflict with any regular cooking -- we still made our simple family-friendly foods like nachos, pizza, salads, burgers, soup, sandwiches, pasta, etc. It was more like a supplement to our regular meals which pushed the fast food out of our diet for a while.</p><h4>Cooking Too: Electric Boogaloo</h4><p>Today we received our second order. Nancy is now nine months pregnant (!) and we're anticipating that eating will be a little bit hectic for a while once the baby comes, so we wanted to stock up on easy and nutritious food. This time instead of ordering 6, we ordered 12. And we figured we'd skip the "pick it up" option and try preparing it ourselves. Here's what we chose:</p><ul><li>Balsamic Thyme Chicken</li><li>2 x Apricot Chicken (Heart Healthy)</li><li>Crabmeat and Swiss Cheese Bake</li><li>2 x Creamy Potato Soup</li><li>2 x Down Under Chicken</li><li>Rice Vegetable Cheese Casserole</li><li>2 x Tropical Pork Chops</li><li>Onion Bacon Crusted Cod</li></ul><p>Preparation was really a lot of fun. Nancy and I went together, and we both agreed: it was all the fun parts of cooking without any of the hard stuff! No chopping, no searching for bowls, no scavenging ingredients or trying to work out what you can substitute because you forgot to buy something, and of course the best part -- <b>NO DISHES</b>!!</p><p>Working together we finished making our twelve dinners in just over an hour -- that's about five minutes each. Here's how it works:</p><p>Each store has a fixed menu which changes every month. There are different recipe stations around the room, one station per recipe. Each station has containers of the ingredients you need at waist level, with the appropriate measuring cup for the recipe already in it. Cheese, mayo, chopped onions, chili sauce, apricot jelly, cooked bacon, etc. (If you want a visual, think of the scene behind the counter at a Subway restaurant, but one that is customized for just a single sandwich.) Some ingredients are pre-packaged in containers that are just the right size for the recipe: for example, one casserole had a bag of exactly the right number of bread squares ready to go. Herbs and spices, sugar, oil, seasoning salts, etc for the recipe are all at shoulder height, and each one has the appropriate measuring spoon next to it. The meat is in a big refrigerator on one wall: thawed, pre-cut, and also ready to go. Along the side there's a sink for washing your hands, and a big rack full of all the utensils you could want and all the pans you need. Oh, and there's yet another station with ziploc bags and a big roll of plastic wrap.</p><p>To make your order, you simply find an open station (there was only one other couple there, so this wasn't hard) and start working. Since everything is already prepped for you, you basically wind up dumping stuff together. It's not hard at all. You're free to tweak the proportions if you want; we only did this a little bit since the recipes seem to have a good mix to begin with.</p><p>I'll admit that our very first one (the Down Under Chicken) was a little intimidating simpy because it was a new experience. We took it pretty slowly to make sure we were doing everything right. But once we figured out how it worked, we got into a groove and it couldn't have been easier -- we banged out the rest without a hitch.</p><p>When you're making it yourself you can also split the orders, so that instead of one meal that serves 4-6 you can make two meals of 2-3 each. We did that on many of the orders, in an attempt to reduce the amount of leftovers. We'll see how that works out.</p><p>At one point Nancy commented, "Geez, I feel like we're on a TV show!" You know how in cooking shows they just describe what you'd do, and then whip it out already done? And dirty dishes aren't even discussed? It was exactly like that. Almost a magical experience.</p><p>Net cost: $197 for twelve dinners, plus about two hours of our time on a Saturday morning. If the previous ratio holds and we get 60 meals out of it, that will come out to $3.28 per meal. </p><p>I'd love to tell you how the food tastes, but since we just made it this morning I can't say yet. But boy, did it ever did look good when we made it!</p><p>By the way, in case you were wondering: I'm not affiliated with these folks in any way, nor do I know the guy who runs the store. (Although we chatted afterward and he seemed pretty cool.) I just think it's a great service. And it's the kind of place that's just awesome for families, and which I even kind of wish I'd had access to as a bachelor -- because sometimes you just want a nice dinner without a lot of effort. </p><p>The verdict? Two thumbs way up. The dinners are cheap, fun to make, delicious, and easy ... and we're back to eating at a table, instead of from a paper bag.</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com1tag:blogger.com,1999:blog-7898615.post-42361133976871250992006-11-07T01:09:00.000-05:002006-11-07T02:06:02.768-05:00Japanese PS3 commercials<p>Everyone knows Sony's marketing can be, uh, <a href="http://video.google.com/videoplay?docid=5797108766137110904">interesting</a>. Most people have seen the US commercials for the PlayStation 3, but not so many people have seen the Japanese commercials.</p><p>Since the Japanese launch of the PS3 is scheduled for November 11th (aka 11/11), most of them involve people seeing 11/11 in odd places. They're short and interesting and there aren't any creepy babies.</p><p>Here are some YouTube links for your viewing enjoyment.</p><h4>Concent (The Socket)</h4><object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/UIluz3H9pcY"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/UIluz3H9pcY" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350" alt="Japanese PS3 ad: Concent (The Socket)"></embed></object><h4>Foku (The Fork)</h4><object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/eije-NoZ7o8"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/eije-NoZ7o8" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350" alt="Japanese PS3 ad: Foku (The Fork)"></embed></object><h4>Entotsu (The Smokestack)</h4><object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/HVLVFPKhCLc"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/HVLVFPKhCLc" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350" alt="Japanese PS3 ad: Entotsu (The Smokestack)"></embed></object><h4>Taikan (The Sensation)</h4><object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/ZDRIMTquPGQ"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/ZDRIMTquPGQ" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350" alt="Japanese PS3 ad: Taikan (The Sensation)"></embed></object>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com2tag:blogger.com,1999:blog-7898615.post-67322724031431537242006-11-03T16:09:00.000-05:002006-11-06T20:34:46.660-05:00Blogger: Condensed Label List<p>This is a continuation of the series about customizations I made to my Blogger template after switching to the Blogger beta.</p><p>This time I'm going to talk about the condensed list of <a href="http://help.blogger.com/bin/answer.py?answer=44498">labels</a> that I've put in the sidebar. Synonyms for "labels" used by other blogging tools include "categories" and "sections". For user navigation I like "sections", personally, so that's what the sidebar says.</p><h4>Why customize it?</h4><p>The default list of labels is a standard bulleted list that displays vertically.</p><p>The problem with vertical lists is that, well, they're an inefficient use of vertical space in the sidebar. If you have a lot of labels, you'll wind up with an extremely large portion of your sidebar devoted to this list. The vertical space that the list occupies will be far out of proportion to its importance. </p><p>Frankly, the list of labels isn't that important to me. It's a nice touch, and I would like them to be there, but I wouldn't say that it needs an entire screenful in my sidebar. So I set out to fix that.</p><h4>Widget modifications</h4><p>Here are the modifications I made to the default "Labels" widget to accomplish this.</p><blockquote class="code"><b:widget id='Label1' locked='false' title='Sections' type='Label'><br /><b:includable id='main'><br />  <b:if cond='data:title'><br />    <h2><data:title/></h2><br />  </b:if><br />  <div class='widget-content'><br />    <ul style='padding-left:10px; margin:0; text-indent:0;'><br />    <b:loop values='data:labels' var='label'><br />      <li style='display: inline; list-style-type: none; padding-right: 5px; line-height: 140%;'><br />        <b:if cond='data:blog.url == data:label.url'><br />          <data:label.name/>&#160;(<data:label.count/>)<br />        <b:else/><br />          <a expr:href='data:label.url'><data:label.name/></a>&#160;(<data:label.count/>)<br />        </b:if><br />      </li><br />    </b:loop><br />    </ul><br />  <b:include name='quickedit'/><br />  </div><br /></b:includable><br /></b:widget></blockquote><h4>Widget explanations</h4><p>Since the styles here are very highly specific to this single list, and unlikely to be re-used, I decided to mix CSS with HTML here by assigning the styles via the <code>style</code> attribute on the tags. This isn't normally <a href="http://csszengarden.com/" title="CSS Zen Garden">good practice</a>, but Blogger templates do it a lot already, and it's actually kind of convenient here. </p><p>The <code>display: inline;</code> style on the <code>LI</code> tag makes the list horizontal. Adding <code>list-style-type: none;</code> removes the bullets.</p><p>That's almost good enough right there! But during testing I found that the original template used normal spaces in between the label and the numeric post count. Since I am expecting the list to wrap -- it wraps five times at my normal web browser size -- I need it to wrap cleanly. With a normal space, you often get the break in between the label and the post count, which doesn't look right. So I converted the regular space into a non-breaking space (&#160;).</p><p>Why '&#160;', rather than something like '&nbsp;'? Because I'm still shooting for XHTML eventually, and XHTML does not recognize '&nbsp;' as an entity. The Unicode code point '&#160;' is the <a href="http://www.dpawson.co.uk/xsl/sect2/nbsp.html" title="nbsp discussion">direct equivalent</a>.</p><p>After all that was done, padding, margins, and line height were adjusted to my personal preference. Your needs may vary.</p><h4>Dead ends</h4><p>Although this looks simple, I tried a couple of other things before settling on this solution.</p><ul><li><p><strong>Putting the list in a paragraph</strong> - I considered this as an option, but was unable to get Blogger's template language to do it. You could do it as a space-separated list, but as soon as you add separators of any sort -- like commas -- there's no apparent way to avoid putting a separator in at the end. Blogger <a href="http://help.blogger.com/bin/answer.py?answer=47270&topic=9084">supports an "isLast" property</a> on labels when used in the post widget, but it does not do so in the labels widget. On further consideration I decided that this was probably a bad approach, anyway, since it's not as accessible as <a href="http://diveintoaccessibility.org/day_22_using_real_lists_or_faking_them_properly.html">using real lists</a>.</p></li><li><p><strong>Changing font size based on post count</strong> - This is a relatively new twist in Web design. <a href="http://flickr.com/photos/tags/">Flickr's tags</a> are a popular example. However, I couldn't figure out a way to do it without resorting to Javascript. Blogger has a very minimal expression language for templates, but I haven't been able to find any detailed documentation for it. The closest I came was doing something like this:</p><blockquote class="code"><font expr:size='data:label.count'> ... </font></blockquote><p>But that didn't cap the maximum font size -- potentially leading to problems as I write more posts in each category. For now I've tabled this idea. It would still be interesting, but I think the best way to do it in Blogger would be to leave the base template HTML as-is, then dynamically modify the HTML with Javascript on the client side.</p></li><li><p><strong>Adding some interesting CSS decoration</strong> - I considered doing this too. But the only decent decoration I could think of was a rounded button look similar to what Safari uses in its Bookmarks toolbar. That would have been possible, but I'd need to create and edit some images and use <a href="http://virtuelvis.com/gallery/css/rounded/">this method</a> to get the rounded corners. Worse, it wouldn't display correctly in Internet Explorer so I'd need to do a CSS hack to hide it. So I tabled this idea too. Even so, I might look back into this in the future.</p></li></ul><h4>More template tips</h4><p>Other entries in this series:</p><ul><li><a href="http://drewthaler.blogspot.com/2006/11/blogger-image-as-blog-header.html">Blogger: Image as Blog Header</a></li></ul>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com7tag:blogger.com,1999:blog-7898615.post-87836108056355701542006-11-02T23:30:00.000-05:002006-11-03T15:44:26.625-05:00Blogger: Image as Blog Header<p>I'm going to do a brief series about how I wound up customizing my Blogger template (styles and widgets) after switching to the Blogger beta. First up, how I replaced the header with an image.</p><h4>Why customize it?</h4><p>Like a lot of people, I prefer to use an image instead of text for the header of my blog. I also want it to be clickable and always be a link back to the "home" page of the blog, which is a widely-adopted convention.</p><p>But I do <em>not</em> want to simply encode an inline image. For reasons of <a href="http://diveintoaccessibility.org/">accessibility</a>, I prefer a normal <code>H1</code> tag that gets translated to an image by CSS.</p><p>Since I've been trying to keep the look-and-feel of my old template, I started with <a href="http://homepage.mac.com/drewthaler/images/blog-header.gif">this image</a> from my old template. It's 790 pixels wide by 105 pixels high.</p><h4>Widget modifications</h4><p>Here are the modifications I made to the default "Header" widget to accomplish this. Data that is <b style="color: red;">specific to my blog</b>, and which you'll want to change if you copy this code, is displayed in <b style="color: red;">red</b>.</p><blockquote class="code"><b:widget id='Header1' locked='true' title='Header' type='Header'><br />  <b:includable id='main'><br />    <div class='titlewrapper'><br />      <h1 class='title'><br />        <a href='<b style="color: red;">http://drewthaler.blogspot.com/</b>'><span/><data:title/></a><br />      </h1><br />    </div><br />    <div class='descriptionwrapper'><br />      <p class='description'><span><data:description/></span></p><br />    </div><br />  </b:includable><br /></b:widget></blockquote><h4>Widget explanations</h4><p>The original Blogger template had a conditional so that the header was only a link if we weren't on the main page already. I removed the conditional because I think it makes more sense to always make it a link.</p><p>The original template also used 'data:blog.homepageUrl' for the link, but this resolved to 'http://drewthaler.blogspot.com/index.html', which is redundant. I wanted the shorter and more future-proof URL 'http://drewthaler.blogspot.com/' so I changed the link manually.</p><p>I left the description code as-is, because I don't use it. You may want to do something different.</p><p>You'll notice a single <code><span/></code> tag in the middle. That's required for CSS image replacement.</p><h4>Stylesheet modifications</h4><p>Here are the CSS additions that go with it. These are additions to the original stylesheet.</p><blockquote class="code">/* Replace the header with a graphic on computer displays */<br />@media screen, projection, tv {<br />  h1.title {<br />    width: <b style="color: red;">750px</b>;<br />    height: <b style="color: red;">89px</b>;<br />    left: 0;<br />    top: 0;<br />    padding: <b style="color: red;">15px 0 0 40px</b>;<br />    margin: 0;<br />    border-bottom: 1px solid black;<br />    z-index: 0;<br />  }<br />  h1.title a span {<br />    background: url(<b style="color: red;">http://homepage.mac.com/drewthaler/images/blog-header.gif</b>) no-repeat;<br />    position: absolute;<br />    top: 0;<br />    left: 0;<br />    display: block;<br />    width: <b style="color: red;">790px</b>;<br />    height: <b style="color: red;">105px</b>;<br />    z-index: 1;<br />  }<br />  #sidebar {<br />    z-index: 2;<br />  }<br />}</blockquote><h4>Stylesheet explanations</h4><p>The <code>@media</code> directive means that these styles should only be applied for certain types of media. For screen, projection, and tv renderers I prefer the nicer look. But they will not be applied for screen readers and printing.</p><p>I'm using the Gilder/Levin Method for <a href="http://www.mezzoblue.com/tests/revised-image-replacement/">CSS image replacement</a>. In this method, the span does all the work: it gets resized and repositioned, and the image is displayed as a CSS background image for it. The image is clickable because it's on the span, and the span is inside the link tag.</p><p>The span is given a z-index of 1 so that it sits <em>above</em> the original <code>H1</code>. The <code>H1</code> text is still there, hiding underneath at z-index 0. Then the sidebar is given a z-index of 2 so that it will float above the header image if the two overlap.</p><p>The pixel sizes (790px by 105px) are from the size of my image. The padding (15px 0 0 40px) and bottom border are in there to make CSS-on/images-off browsing still look acceptable. It's a personal preference and based on the size of my image and text, so you might need to tweak it for your setup. The <code>H1</code>'s width of 750px is the image's width (790px) minus the horizontal padding (40px), and the <code>H1</code>'s height of 89px is the image's height (105px) minus the vertical padding (15px) minus the one-pixel bottom border (1px).</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com11tag:blogger.com,1999:blog-7898615.post-75717047598462123592006-10-31T06:04:00.000-05:002006-10-31T07:00:13.746-05:00When Benchmarks Attack<p>In my professional life I've found myself measured by an external benchmark many times. One time that comes to mind was when I was writing disk drivers for <a href="http://en.wikipedia.org/wiki/Mac_OS_8">Mac OS 8</a>. </p><p>The disk driver's job in Mac OS 8 was simply to pass requests from the filesystem layer to the underlying storage medium. Requests would come in for such-and-such amount of data at such-and-such an offset from the start of the volume. After some very minimal translation, we'd pass this request onward to the ATA Manager, or USB Manager, or FireWire libraries. </p><p>(Sounds easy, right? Well, yes, but the devil was in the details. USB and FireWire supported "hot-plugging", i.e. attaching or removing the drive while the computer was still running. Supporting this in an OS that was never designed for it was a big chore. CD and DVD drives were also much more difficult to handle than regular hard drives, for similar reasons.)</p><p>But we ran into a problem as we were preparing our drivers for release. The hardware manufacturers that were buying our drivers wanted to make sure our drivers were "fast". So they ran disk benchmarks against our drivers. Not an unreasonable thing to do, you might say, although as I've stated there really wasn't a lot of code in the critical path. The problem is that most of the <em>disk</em> benchmarks turned out to be inappropriate as measures of <em>driver</em> performance.</p><h4>Measuring weight with a ruler</h4><p>One common disk benchmark of the time was to read sequential 512-byte blocks from a large file. In Mac OS 8 these reads were passed directly down to the disk driver.</p><p>Remember, the disk driver's job was supposed to be to simply pass the incoming requests on to the next layer in the OS. The vast majority of the time would be spent accessing the hardware. So no matter what the requests were, in effect this test should have returned almost exactly the same results for all drivers, with code differences accounting for less than 1% of the results. Right? Wrong.</p><p>As we ran the tests, we found out that on this particular benchmark, our drivers were much slower than existing third-party drivers (our competition, more or less). Dramatically slower, in fact -- if we ran the test in 100 seconds, they ran it in 10 seconds.</p><p>Upon further examination, we found out the reason why they did so well on this benchmark. They had already been optimized for it!</p><p>We discovered that the other drivers contained caching logic which would cluster these small 512-byte sequential reads into larger 32KiB or so chunks. Doing so would decrease the number of round-trips to the hardware needed, which increased their performance on this benchmark.</p><h4>Do what sells, not what's right</h4><p>Now, it's important to understand that this tiny-sequential-read benchmark doesn't even reflect real-world use. The fact that larger I/O requests perform better than smaller I/O requests has been well known for decades, and almost every commercial application out there used large I/O requests for this very reason. Buffered I/O is built into the standard C libraries, for pete's sake. In the real world, requests that came into the disk driver tended to be either large or non-sequential.</p><p>Modifying our drivers to do the same thing would basically be pointless -- a lot of work for very little performance difference.</p><p>(It only gets worse when you realize that our disk driver was directly underneath the Mac OS disk cache. A driver-level cache was almost completely redundant. And the right place to do this sort of readahead caching would have been there, in the existing OS cache layer, not in each individual disk driver.)</p><p>But ... sigh. The real world doesn't always make sense. These small sequential reads were a well-known benchmark, even if it was a disk benchmark and not a driver benchmark. And that simple fact elevated this atypical scenario into the eyes of a lot of people who didn't really understand what it meant. To them, if our driver didn't do the same thing as the competition, we wouldn't measure up.</p><h4>De-optimizing to improve the benchmark</h4><p>So in order to make sales we were forced to burn another month adding and testing driver-level caching so that we'd perform better on this benchmark.</p><p>The irony? The work we did to improve this atypical benchmark actually <em>increased</em> the amount of time we spent in the driver code, and sometimes <em>increased</em> the amount of data we read, which in turn <em>decreased</em> real-world performance by as much as 1-2%.</p><p>But hey, at least that benchmark got faster.</p><p>And we sold our driver.</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com3tag:blogger.com,1999:blog-7898615.post-24459484861895853082006-10-30T02:00:00.000-05:002007-09-04T03:28:06.574-04:00Switched to Blogger Beta<p>Yesterday I <a href="http://www.blogger.com/migrate-login.g">moved this blog to the new Blogger Beta</a>.
</p><p>
I went whole-hog and switched to a new template as well. I'm still tweaking it, and XHTML compliance is temporarily gone. But for the most part things should be back to normal. RSS readers may see that every post has been modified. This was a side effect of the switch, although in fact I added categories/labels to all posts once I saw that they were going to be touched anyway.
</p><p>
Why switch? The mainline Blogger service (1.0) has been <a href="http://buzz.blogger.com/2006/10/blogger-outages-novel.html">having boatloads of problems</a> over the past month or two. It hasn't been very well maintained and it seems like it's just barely holding together. All the Google blogs are using the beta now, and in fact there are some very nice features in the beta that I was tempted by.
</p><p>
Cool stuff that you get from the switch:
</p>
<ul><li><a href="http://help.blogger.com/bin/answer.py?answer=42659&topic=9084">MUCH faster publishing</a>. 1.0 generated a zillion static HTML files, the 2.0 beta uses a database.</li><li><a href="http://help.blogger.com/bin/answer.py?answer=44498">Labels</a>, aka categories.</li><li><a href="http://buzz.blogger.com/2005/10/introducing-backlinks.html">Backlinks</a>, aka trackbacks. Better than MT's, since these are automatic. (Presumably filled in by Google crawls?)</li><li><a href="http://help.blogger.com/bin/answer.py?answer=42663&topic=9084">Comment feeds</a>, both global and per-post.</li><li><a href="http://help.blogger.com/bin/answer.py?answer=46888">Better template management</a>. It's more powerful and exposes more, and it's smart enough to let you add and rearrange certain things on your page with no effort.</li><li><a href="http://help.blogger.com/bin/answer.py?answer=46995&topic=9084">Widgets</a>, aka server-side directives in your template.</li></ul>
<p>Downsides of the switch:</p>
<ul><li><b>RSS reset</b>. Everything in my RSS feeds got reset when I switched. Not a huge problem.</li><li><b>Porting customizations</b>. To get some of the nicer features you need to upgrade your template. If you had your blog moderately customized, and change your template like I did, then it can be kind of a chore to port your customizations over. For me it took about a day.</li><li><b>Limited Safari support</b>. Posting from Safari works just fine. Template editing seems like it has to be done in Firefox.</li><li><b>It's a beta.</b> And knowing Google, it will probably remain a beta for another <a href="http://www.google.com/press/pressrel/gmail.html">three years</a> or so. Dude. Can't you guys commit?</li></ul>
<p>I haven't seen any other major downsides yet, but I'll let you know.</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com3tag:blogger.com,1999:blog-7898615.post-87576490666279633562006-10-29T03:34:00.001-05:002008-04-08T10:28:54.073-04:00Video Game Tips for Parents<p>I want to talk a little about a couple of lessons that I've learned from several years of experience with my daughter and video games.
</p><p>
If you haven't done so already, I'd also recommend reading <a href="http://drewthaler.blogspot.com/2005/03/great-ps2-games-for-young-kids-part.html">these other tips</a> from an earlier post, where I describe the things I went through trying to figure out which PlayStation 2 games would work for my 6 year old daughter.
</p><p>
Here's what I've learned:
</p>
<ul><li><p><b>Never, EVER buy a game without reading a review first.</b> It's just a bad idea. That brings us to our second rule:</p></li><li><p><b>Never, EVER buy a game without reading a review first.</b> Seriously. I mean it! If you're new to video games, you might assume that most games are all about the same and it doesn't matter what you buy. Not a chance. Would you say the same for books and movies? There are some steaming pieces of trash out there which have been slapped together with spackle and duct tape, and they still sell a few copies because they're put in the store with fancy box art.</p><p>This rule has several corollaries. Here's a list of very bad reasons to buy a game "cold" (i.e., without reading a review) that people can fall victim to:</p><p>Bad Reason #1: <i>It uses the name of some great game that you remember.</i> Many classic video games have been resurrected into horrible zombie caricatures of their former greatness. Frogger is one of the worst offenders.</p><p>Bad Reason #2: <i>It's a sequel to a game you or your child liked.</i> Often the sequel changes the gameplay. And sometimes the rights to a game are transferred to another studio, and when that happens the second studio usually does a ham-handed job with the sequel. (Movies are the same way. Consider <a href="http://www.imdb.com/title/tt0077631/">Grease</a> and <a href="http://www.imdb.com/title/tt0084021/">Grease 2</a>.)</p><p>Bad Reason #3: <i>It's a TV or movie tie-in.</i> TV and movie tie-ins are very often poorly made. Sometimes they just whip them together with no concern for gameplay or difficulty. There are some terrific games which are exceptions to this rule, of course -- many of Nickelodeon's games are pretty good -- but you won't know unless you read a review.</p><p>Bad Reason #4: <i>The box art and description makes it sound interesting.</i> Um, yeah. Every game is a "great adventure" and "exciting" and "fun" by the time the marketing people are done with it. The box has no relation whatsoever to the actual game.</p></li><li><p><b>Look for the Greatest Hits titles.</b> This is one place where the box can actually tell you something about the game. Sony's "Greatest Hits" are titles that have sold particularly well -- they are the gaming equivalent of a record going platinum. The nice thing is that the games get a lower price when this happens. So even though these games cost around $20, they're often much more fun than newer games which cost $50. Of course, brisk sales don't necessarily mean the game is age-appropriate, so you should still check reviews.</p></li><li><p><b>Don't be afraid of older games.</b> Quality is far more important. The age of the game really doesn't matter: a fun game will always be a fun game. It doesn't matter if the game is "new" or not; it will still be new to your child! Any parent who's watched their kid get hooked on <i>The Cosby Show</i> or <i>Full House</i> or some other unexpected sitcom will understand how the same logic applies directly to games. Younger kids aren't hooked on fancy graphics and don't care about what's latest and greatest; they just want a game that's fun. As an extra bonus, older games are cheaper -- often by a lot!</p></li><li><p><b>Buy games used, and trade in old games.</b> Most dedicated game stores, such as <a href="http://www.ebgames.com/">EB Games</a>, offer used games for sale and offer you store credit on trade-ins. This is a great way to save a lot of money. The used games will be literally as good as new. Trading in is also a useful lesson for your kids; I've made it a point to help my daughter pick which games she wants to trade in. We keep some old favorites around because she still plays them, or because they are good for sleepovers, but most eventually go back. Then we shop for new games, trying to see how much we can get without spending more than $10.</p></li><li><p><b>Consider renting games.</b> It's up to you to decide whether this approach works for you. I don't do it with my daughter, because she simply doesn't play games enough to justify it, but some people do. It can be a fun way to try out a game without making a $40-$50 commitment. Just watch out for late fees! These days you can avoid them completely. Blockbuster now offers no-late-fee rentals (online and in-store) with their <a href="http://beta.blockbuster.com/stores/gamePass">GamePass</a> service, and there are a ton of NetFlix-like online rental services, including <a href="http://gamefly.com/">GameFly</a>, <a href="http://gamelender.com/">GameLender</a>, <a href="http://gplay.com/">GPlay</a>, and others.</p></li><li><p><b>Swap games with friends</b>. Your child might not even consider this unless you suggest it. Loaning games to friends is a nice way to socialize and it saves money, too. And it gives the kids something else to talk about!</p></li><li><p><b>Play the games with your child.</b> Especially with younger kids, but even as your child gets older this is important. It's a lot like reading a book together. It's a way to have fun and share an experience. When your child is particularly young, you might find that he gets stuck and gives up on a game quietly without really saying anything. If you help get past the tricky spots, he can go on having fun for longer. Or perhaps your kid will be like my daughter, and get (happily) scared when you reach the big, intimidating "boss" monster together, and she'll shove the controller over to you and want you to take over for a while. I usually play just long enough to show her how to do it, and then pass it back to her to try. Sometimes, if she asks, I'll get her past the hard part to the point where she wants to take over again. It's fun for both of you, and can be a great confidence builder.</p></li><li><p><b>For big games, consider a hint book / strategy guide.</b> Don't do this all the time, of course. But there are some larger games (such as Kingdom Hearts) where I found it to be very useful. What's great about these guides for kids ages 5-7 is that it can encourage their reading skills. My daughter wasn't really motivated to read much when she was 6, but the game strategy guide really got her going! It sounds silly, but it worked.</p></li></ul>
<p>Any tips that you want to share?</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com1tag:blogger.com,1999:blog-7898615.post-1162004130272762972006-10-28T13:00:00.001-04:002008-04-08T10:28:31.599-04:00Great PS2 Games for Young Kids, Part Two<p>Well, it's been (ahem) about a year and a half since I promised a "part two" to my earlier post on <a href="http://drewthaler.blogspot.com/2005/03/great-ps2-games-for-young-kids-part.html">Great PS2 Games for Young Kids, Part One</a>. And it's time for the next installment. Three more games this time:</p>
<ul><li><a href="#MonsterRancher">Monster Rancher 3</a></li><li><a href="#DDR">Dance Dance Revolution</a></li><li><a href="#KingdomHearts">Kingdom Hearts</a></li></ul>
<p>[This post used to contain a lengthy list of tips. To trim it to a more manageable size, I've moved it to a new entry: <a href="http://drewthaler.blogspot.com/2006/10/video-game-tips-for-parents.html">Video Game Tips for Parents</a>.]
</p><p>
Okay. With that out of the way, let's get to the games! Three more good ones here. Although Olivia is now age 10, I'll talk about some games that she loved between the ages of about 7 and 9.
</p>
<h3><a name="MonsterRancher">Monster Rancher 3</a></h3><iframe src="http://rcm.amazon.com/e/cm?t=drewthaler-20&o=1&p=8&l=as1&asins=B0000AHOOH&fc1=000000&IS2=1&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0" align="right"></iframe><iframe src="http://rcm.amazon.com/e/cm?t=drewthaler-20&o=1&p=8&l=as1&asins=B00005OLX5&fc1=000000&IS1=1&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0" align="right"></iframe>
<p>This is actually a series of games, ranging from Monster Rancher 1 to 4, plus the relatively new (and very different) Monster Rancher EVO. At the time we got it, the fourth game was out but I'd heard more favorable reviews of the third game. Following my own advice -- don't be afraid of old games! -- I went with number three. It might be hard to find the third game these days; I hear that the fourth one is also good, but I can't say for sure since we've only played this one.
</p><p>
You play as a monster trainer. The game starts by creating a monster, either from some pre-made guys or -- the better choice -- from a "saucer stone", which is a code name for "any old random CD or DVD you have lying around the house". (You'll have to swap discs manually, at which point you should pause and take a moment to teach your child about how to put CDs away properly when they're done with them.) Each disc will create a unique monster with different looks and abilities, and the same disc will create the same type of monster if used again. Your monster starts as a baby, and you feed it and train it to help it grow stronger. Over time it matures, grows old, and eventually dies, at which point you can start over again. There is a little bit of anime-style story, and there is a tournament where the monsters can optionally fight (without blood, and losers aren't really "killed", but there is cartoonish violence -- monsters chomp each other, whap each other with giant cartoon mallets, etc) to gain levels and prizes. And that's pretty much it.
</p><p>
What's fascinating about this game is the way that kids just love it. But it's the kind of game that can drive an adult crazy! Why? Because it's cute, and there's a lot of repetition. Kids that are 10 and under love repetition; just like they enjoy watching the same video over and over, or reading the same book over and over, they don't mind doing the same thing in a game over and over. There is a <i>lot</i> of repetition in the game as you train your monster. You'll see the same animations over and over (sigh, and over) again. And yet there's still some variety -- you can train in different ways, or use different monsters, or go to a completely new area to train in.
</p><p>
The controls are menu-based, but pretty simple to figure out. There is some text that your child should pay attention to. For example, the game will suggest that it's time to feed your monster, or to let it rest. Perhaps the trickiest part is saving the game and continuing after your monster dies (which is necessary to open up new areas). Olivia had a tendency to just start new games, since she got attached to her monster and didn't want to save over it after it had grown old and died. But doing that meant that she never got to train anywhere other than the first area.
</p><p>
The game can also help build the skills your child needs to keep a pet. Monster Rancher isn't quite a "virtual pet" simulator, like a <a href="http://www.tamagotchi.com/">Tamagotchi</a> or <a href="http://www.nintendogs.com/">Nintendogs</a>, but it shares some of the same elements. If you treat your monster nicely, he'll be sweet and lovable and grow stronger. If you spoil him too much, he'll get fat and temperamental. If you punish him too much or don't feed him enough, he might get mean. And even though it can be very sad when a monster grows old and dies, that's part of life too. The game handles it well and you can quickly start over with a new baby monster -- which gets a boost from the "heart" left over by the previous one.
</p><p>
Kids also really love the "saucer stone" part. Since you don't know what any disc will give you, you'll have to try a bunch of them and see what you get. It's surprisingly entertaining, and kids love it because it's something they never thought might be possible. It's a really unique gameplay mechanism that I've never seen anywhere else. Just be careful: unattended, your kids might quickly make a mess of your CD collection! We gave Olivia permission try lots of CDs but always made sure that she was careful with them and put everything back as soon as she was done.
</p><p>
Some people might be concerned about the whole "raising animals to fight" part. That's your call. Personally, this wasn't a problem for us. First, we make sure our daughter is able to distinguish fantasy from reality (always a good thing) and that she knows how to behave in real life. Second, the monster fighting is very much treated as a sport in the game -- just like boxing, karate, or amateur wrestling might be. There are tournaments, prizes, and so on. So it's not as if you're teaching your kids to enjoy cockfights or the WWF. It's an extremely mild game.
</p>
<h3><a name="DDR">Dance Dance Revolution</a></h3><iframe src="http://rcm.amazon.com/e/cm?t=drewthaler-20&o=1&p=12&l=st1&mode=videogames&search=Dance%20Dance%20Revolution%20PS2%20Konami&fc1=&lt1=&lc1=&bg1=&f=ifr" marginwidth="0" marginheight="0" width="300" height="250" border="0" frameborder="0" style="border:none;" scrolling="no" align="right"></iframe>
<p>This is another game that appeals to people across all ages. You've probably seen the arcade version in a mall. It's the one that has people stepping on four arrows while dance music plays, often drawing a crowd when the better players are "on stage". There's no real gender bias to the game, but my impression is that with younger kids it's more popular with girls, while among teenagers it's more popular among boys. I don't know this for sure; that's just the impression I get. Somebody could probably write a PhD thesis dissecting the relationship of this game to gender roles. :-)
</p><p>
First of all, you absolutely need to get the special "mat" controller that lets you dance. Some versions come with it bundled, or you can <a href="http://www.amazon.com/gp/product/B0000AV7GB?ie=UTF8&tag=drewthaler-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=B0000AV7GB">buy it separately</a>. They sell some very expensive ones, but the regular old cheap one works well. Once you have that the game is very simple, but challenging. You're given a wide variety of songs to choose from, each with its own dance moves. All you need to do is just step on the arrows at the right time.
</p><p>
Sounds easy, right?
</p><p>
You wish. The guys at the mall may make it look simple, but DDR is very physical and can be challenging both for you and your child. You'll want to start out with the difficulty dialed all the way down to the lowest setting. It's okay to screw up -- and you will -- as long as you keep trying. Stick with it! After a while you'll start getting the hang of it. When you're first starting out, it's not unusual to have to stop after a few songs because you just get too tired and sweaty. I've found that taking turns of either one or three songs works well.
</p><p>
What's great about this game is that it's a very physical thing, and it's something your child will want to practice. It's not very mentally challenging, but it can be tricky trying to figure out how to do all the moves you need to get through a song. It's sort of like puzzle-solving with your feet. It's not a game that you'll "beat" any time soon; you will be able to continue playing and improving for a long time. It's also an easy game to pick up and play; there's no story, and nothing gets in your way. You just start it up and go. And it's great at parties as long as you make sure the kids share.
</p><p>
There are a lot of versions of this game. Some come with the "mat" controller bundled, some don't. As mentioned before, you'll really need the controller. We chose to get the <a href="http://www.amazon.com/gp/product/B0002RQ37U?ie=UTF8&tag=drewthaler-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=B0002RQ37U">Dance Dance Revolution Extreme Bundle</a>, which included it. (NOTE: The preceding link lists a price of $199.95, which is insane. It should be about $40, which is the price you'll find for the almost equivalent <a href="http://www.amazon.com/gp/product/B0009Z3K1C?ie=UTF8&tag=drewthaler-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=B0009Z3K1C">DDR Extreme 2 Bundle</a>. I e-mailed the seller and he said, paraphrased, that the price is deliberately high because it's new and unopened and someone stupid might buy it at that price.)
</p><p>
The primary difference between the versions is really the song lists. They tend to be techno dance music, and more or less appropriate for everyone. You might hear any of these songs on the radio. Your standards may vary, of course, but we really didn't find anything that we were concerned about in the game.
</p>
<h3><a name="KingdomHearts">Kingdom Hearts</a></h3><iframe src="http://rcm.amazon.com/e/cm?t=drewthaler-20&o=1&p=8&l=as1&asins=B000066TS5&fc1=000000&IS2=1&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0" align="right"></iframe>
<p>Kingdom Hearts has a special kind of magic. It turns Disney movies into three-dimensional worlds that you can run through and play around in, and that's just fantastic. Since it contains a lot of characters and stories that your child will already know, it really is a lot of fun, and unlocking the game's worlds can be really rewarding. And if you look at the top of the box you'll see that it's now become a "Greatest Hits" title, which is why it's gotten so cheap.
</p><p>
This is a tricky one to put on the list, but it's just so good that I had to do it. Despite its Disney theme, this is definitely <b>not</b> an easy game for a young child. <b>It's very long, complicated, can be very difficult, and has a few scary points.</b> I would say that it's probably targeted a little more at the tween to teen market. Olivia and I started playing it when she was only 7, but we didn't finish for months and months! <b>It definitely shouldn't be a child's first exposure to video games, and you should be prepared to help your child play it almost the whole way through.</b> In fact, I would strongly suggest getting a hint book like the <a href="http://www.amazon.com/gp/product/0744001986?ie=UTF8&tag=drewthaler-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0744001986">Kingdom Hearts Official Strategy Guide</a> ... these can be a lot of fun, and can encourage your child's reading skills.
</p><p>
You play Sora, a young boy who lives on an island with his friends. After some lengthy training and a series of opening sequences which seem to take forever, eventually your island is ripped apart. You land in a central hub called Traverse Town, and eventually meet up with Donald and Goofy -- who have been sent by King Mickey to find you and then deal with the problem of "Heartless", shadowy monsters which are invading all the Disney worlds. Eventually you'll visit the worlds of (and fight the major villains from) a lot of different Disney movies: Little Mermaid, Hercules, Nightmare Before Christmas, Alice in Wonderland, Aladdin, Peter Pan, and more.
</p><p>
There is violence in this game: fighting monsters is most of what you do. Fighting involves swordfights with a "Keyblade" that looks like a giant key. You're rarely fighting people; most of the fighting is against Heartless, who look like shadowy insects. Otherwise the content should be fine for all ages. Not all of the characters are Disney characters; some are Square-Enix characters (from other games made by the same game studio) and some were created just for this game.
</p><p>
The controls are moderately complicated. The basic moves are just running around, jumping, and hitting the attack button -- easily mastered by most kids if they've played a few games before. But there are a lot of menus, and even items that you can optionally buy and use (healing potions, magic, and so on). Saving goes through a menu as well, and must be done at a save point. There's no autosave, so your child must remember to save or else lose her progress.
</p><p>
The worlds you run around in can be big and complicated, and it's not always clear what to do next. But I've found that because it's a Disney theme, kids are very highly motivated to explore and look around. They will probably get stuck a lot, and the game makes it worse by creating certain situations where you just can't make forward progress and you have to give up and go to another world. For example, the Colosseum in Hercules isn't open for a long time, and there's no obvious reason why. That's why I'd suggest a <a href="http://www.amazon.com/gp/product/0744001986?ie=UTF8&tag=drewthaler-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0744001986">hint book</a>, with maps and strategies. When your child gets stuck, help him figure out how and where to look up the answer. You'll be helping him with his game, and very sneakily teaching him valuable skills like "how to use a reference book"!
</p><p>
There is also a sequel, <a href="http://www.amazon.com/gp/product/B0009A4EVM?ie=UTF8&tag=drewthaler-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=B0009A4EVM">Kingdom Hearts II</a>, which is very similar to the first game. It's also long and complicated, but almost as good as the first game. I found that Olivia's enthusiasm ran out after a while on the sequel, but that might be because it didn't come out until two years after we finished the first one.
</p>
<h3>Wrap-Up</h3>
<p>I still believe that the most important thing you can do as a parent is to read reviews of games before you buy them. Games can be expensive, and you don't want to buy bad ones.
</p><p>
There are a few places I go to find reviews. <a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.com%2F&tag=drewthaler-20&linkCode=ur2&camp=1789&creative=9325">Amazon</a> frequently has reviews written by kids and parents. I like <a href="http://ps2.gamespot.com/">GameSpot</a>'s reviews, although as a parent you sometimes need to translate a little: the criticisms of "too short" and "too easy" often mean the game will be just right for kids. <a href="http://ps2.ign.com/">IGN</a> also has reviews, but the reviews aren't as well-written; sometimes it feels like they are written for gaming insiders who follow every little bit of news.
</p><p>
I hope to write more in this series, but I encourage you to write your own experiences in the comments. Let me know what you've tried, and what worked and didn't!</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com5tag:blogger.com,1999:blog-7898615.post-1155059142628074612006-08-08T13:30:00.001-04:002008-04-08T10:28:04.365-04:00New Parallels Desktop Beta<p>A new <a href="http://parallels.com/en/products/desktop/update_beta/">beta update</a> of Parallels Desktop has been released that updates Parallels Desktop for Mac to Build 1862 Beta.</p>
<p>This update fixes the disk caching policy problem that <a href="http://www.multisolar.com/software/PDTweaker/">PD Tweaker</a> was created for. If you were wondering, PD Tweaker is perfectly safe to run with the new update and doesn't conflict with it at all. But it will be unnecessary once you have configured your VM properly.
</p><p>
Curiously, instead of just fixing it they decided to make it an option under the virtual machine settings -> Options -> VM flags:
</p>
<blockquote><p>Choose virtual hard disk cache policy for better performance of:<br />
<br />
<tt>[X]</tt> Virtual machine<br />
<tt>[ ]</tt> Mac OS X</p></blockquote>
<p>"Virtual machine" is the default setting. For the technically-minded among you, this is like having a radio button to select between two behaviors: "incorrect" and "correct", and defaulting to "incorrect".
</p><p>
In this case the <b>correct behavior is to select the second option, "Mac OS X"</b>. There are rare scenarios where you might want the other behavior, for example if you were setting up a dedicated server box that does nothing except run virtual machines. But in almost all other cases the second option is correct. I'll blog more about this later.
</p><p>
There are several significant other improvements, including video acceleration -- which completely eliminates the display-update lag when you're typing in Windows, hooray! All in all it seems like a very worthwhile update so far. Remember to re-install the Parallels Tools on your client OS after updating so that you get the new drivers.</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com0tag:blogger.com,1999:blog-7898615.post-1151712875933612372006-06-30T19:58:00.001-04:002008-04-08T10:27:42.885-04:00CLImax 1.5d2 re-released<a href="http://www.multisolar.com/software/CLImax/"><img src="http://www.multisolar.com/software/CLImax/icon" width="128" height="128" alt="CLImax" /></a><p>Any old-school scripters out there might be happy to hear that I've re-released CLImax 1.5d2, which I recently rediscovered on a long-lost backup. </p>
<p><a href="http://www.multisolar.com/software/CLImax/">CLImax</a> is an AppleScript command-line interface for the Mac OS. It was originally written in 1996 for System 7.5, and development was stopped in 1998. Ten years after its first release, version 1.5d2 can still run under Classic today. It's not as convenient as it was under 9.2.2 natively, but it's not bad either.</p>
<p>I've received a bunch of positive comments about CLImax from people including Bill Cheeseman (of <a href="http://www.applescriptsourcebook.com">AppleScript Sourcebook</a>), Ray Barber (of <a href="http://macscripter.net/">MacScripter</a>), and Peter Hosey (of <a href="http://trac.adiumx.com/wiki/boredzo">Adium X</a>). Peter was the one who actually got me to re-release it.</p>
<p>CLImax 1.5d2 is now FREEWARE and available at no charge. Be sure to visit the <a href="http://www.multisolar.com/software/CLImax/">CLImax homepage</a> for more information, including screenshots.</p>
<p>I'm currently soliciting feedback on whether it'd be worth porting it to Mac OS X and creating a modern version. Thoughts?</p>Drew Thalerhttp://www.blogger.com/profile/01081923007415869973noreply@blogger.com2