<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xml:lang="en" xml:base="http://chadaustin.me/wp-atom.php">
	<title type="text">Chad Austin</title>
	<subtitle type="text" />

	<updated>2010-03-04T08:02:18Z</updated>
	<generator uri="http://wordpress.org/" version="2.9.1">WordPress</generator>

	<link rel="alternate" type="text/html" href="http://chadaustin.me" />
	<id>http://chadaustin.me/feed/atom/</id>
	

			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/chadaustin" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="chadaustin" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
		<author>
			<name>Chad Austin</name>
						<uri>http://aegisknight.org/</uri>
					</author>
		<title type="html"><![CDATA[Your Version Control and Build Systems Don&#8217;t Scale]]></title>
		<link rel="alternate" type="text/html" href="http://chadaustin.me/2010/03/your-version-control-and-build-systems-dont-scale-introducing-ibb/" />
		<id>http://chadaustin.me/?p=1508</id>
		<updated>2010-03-04T08:02:18Z</updated>
		<published>2010-03-04T07:59:08Z</published>
		<category scheme="http://chadaustin.me" term="Uncategorized" /><category scheme="http://chadaustin.me" term="git" /><category scheme="http://chadaustin.me" term="ibb" /><category scheme="http://chadaustin.me" term="scons" />		<summary type="html"><![CDATA[Let&#8217;s spend a minute and talk about the performance of a tool you use every day: your build system.  For this purpose, they&#8217;re all the same, so let&#8217;s assume you use GNU Make.  For a no-op build, what is Make&#8217;s running time?  You know, that O(N) stuff.

If you said O(Files), you&#8217;re right. [...]]]></summary>
		<content type="html" xml:base="http://chadaustin.me/2010/03/your-version-control-and-build-systems-dont-scale-introducing-ibb/">&lt;p&gt;Let&amp;#8217;s spend a minute and talk about the performance of a tool you use every day: your build system.  For this purpose, they&amp;#8217;re all the same, so let&amp;#8217;s assume you use GNU Make.  For a no-op build, what is Make&amp;#8217;s running time?  You know, that O(N) stuff.&lt;/p&gt;

&lt;p&gt;If you said &lt;code&gt;O(Files)&lt;/code&gt;, you&amp;#8217;re right.  Every time you type &lt;code&gt;make&lt;/code&gt; and press enter, it scans every file in the project, looking for out-of-date sources.  That doesn&amp;#8217;t sound so bad.  Linear algorithms are good, right?&lt;/p&gt;

&lt;p&gt;Oh, but projects grow over time, typically in proportion with the number of engineers (even if some are &lt;a href="http://twitter.com/chadaustin/status/8623778614"&gt;net&lt;/a&gt; &lt;a href="http://twitter.com/chadaustin/status/8624762041"&gt;negative&lt;/a&gt;).  Since projects grow:&lt;/p&gt;

&lt;pre&gt;
O(Files) = O(Engineers * Time)
&lt;/pre&gt;

&lt;p&gt;Assuming you&amp;#8217;re successful, your team is probably growing too:&lt;/p&gt;

&lt;pre&gt;
O(Engineers) = O(Time)
&lt;/pre&gt;

&lt;p&gt;Applying some substitutions:&lt;/p&gt;

&lt;pre&gt;
O(Make) = O(Files) = O(Engineers * Time) = O(Time^2)
&lt;/pre&gt;

&lt;p&gt;A no-op make is &lt;em&gt;quadratic&lt;/em&gt; in the duration of the project?!&lt;/p&gt;

&lt;p&gt;Exhibit A, Mozilla:&lt;/p&gt;

&lt;pre&gt;
Chad@laptop /c/xulrunner/mozilla-central/obj-xulrunner
$ time make
rm -f -rf ./dist/sdk
[tons of output snipped]
make[1]: Leaving directory `/c/xulrunner/mozilla-central/obj-xulrunner'

real    21m31.526s
user    4m13.292s
sys     9m15.066s
&lt;/pre&gt;

&lt;p&gt;21.5 MINUTES!  This is a no-op build!  I changed nothing from the last build!&lt;/p&gt;

&lt;p&gt;Mozilla&amp;#8217;s build is an especially egregious example, but it&amp;#8217;s not uncommon for nontrivial Make, SCons, or Jam no-op builds to exceed 15 seconds.  Every time you run SCons, for example, it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;loads Python,&lt;/li&gt;
&lt;li&gt;imports a bunch of Python code,&lt;/li&gt;
&lt;li&gt;creates an entire dependency graph in memory,&lt;/li&gt;
&lt;li&gt;scans all files for changes,&lt;/li&gt;
&lt;li&gt;determines what to build,&lt;/li&gt;
&lt;li&gt;builds it,&lt;/li&gt;
&lt;li&gt;and throws all of those intermediate results away.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Am I the only person who thinks this situation is insane?  We&amp;#8217;re spending all of our time improving &lt;a href="http://www.scons.org/wiki/GoFastButton"&gt;constant&lt;/a&gt; &lt;a href="http://gamesfromwithin.com/the-quest-for-the-perfect-build-system-part-2"&gt;factors&lt;/a&gt; rather than addressing fundamentally quadratic build algorithms.&lt;/p&gt;

&lt;p&gt;No-op builds should be &lt;code&gt;O(1)&lt;/code&gt; and instantaneous, and most other builds should be &lt;code&gt;O(WhateverChanged)&lt;/code&gt;.  What if I told you this is possible?&lt;/p&gt;

&lt;h2&gt;Introducing IBB: I/O-Bound Build&lt;/h2&gt;

&lt;p&gt;Dusty, one of the best engineers I know, once told me that C compilers are now fast enough that they&amp;#8217;re I/O-bound, not CPU-bound as you&amp;#8217;d expect.  This was inspiration for a &lt;del&gt;build system&lt;/del&gt; dependency engine architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A long-running server process that contains a complete dependency graph between files, including the commands required to update targets from sources.&lt;/li&gt;
&lt;li&gt;An ultra-tiny C program that communicates build requests to the build server.&lt;/li&gt;
&lt;li&gt;A background thread that watches for filesystem updates (via &lt;a href="http://msdn.microsoft.com/en-us/library/aa365465(VS.85).aspx"&gt;ReadDirectoryChangesW&lt;/a&gt; or &lt;a href="http://en.wikipedia.org/wiki/File_alteration_monitor"&gt;libfam&lt;/a&gt;) and updates the dependency graph in memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have built a prototype of ibb&amp;#8217;s architecture, and its code is available on &lt;a href="http://github.com/chadaustin/ibb"&gt;my github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In ibb, a no-op build takes constant time, no matter the size of the project.  I tested with Noel Llopis&amp;#8217;s &lt;a href="http://gamesfromwithin.com/the-quest-for-the-perfect-build-system"&gt;build system stress test&lt;/a&gt; and no-op builds are merely &lt;b&gt;50 milliseconds&lt;/b&gt;.  Take that, everyone else!&lt;/p&gt;

&lt;h2&gt;A Faster Grep&lt;/h2&gt;

&lt;p&gt;Let&amp;#8217;s say you wanted to run a regular expression across your entire codebase.  On Windows, you&amp;#8217;ll spend all of your time in kernel calls, even if the files are in cache.  However, remember that modern memory bandwidths are measured in GB/s&amp;#8230;&lt;/p&gt;

&lt;p&gt;ibb&amp;#8217;s &lt;a href="http://github.com/chadaustin/ibb/blob/master/example/search/main.ibb"&gt;file search&lt;/a&gt; implementation can run a regular expression across 200 MB of PHP and JavaScript in &lt;b&gt;100 milliseconds&lt;/b&gt;.  It copies file data into memory on the first run and rapidly scans across that memory on future runs.  It could just as easily mmap and use OS&amp;#8217;s disk cache to avoid kernel calls.&lt;/p&gt;

&lt;h2&gt;Minimal Test Runner&lt;/h2&gt;

&lt;p&gt;Carl Masak&amp;#8217;s inspirational &lt;a href="http://use.perl.org/~masak/journal/39639"&gt;addictive TDD harness&lt;/a&gt; is also possible with ibb.  If you can determine which unit tests depend on which source files (via an __import__ hook in Python, say), you can run appropriate tests immediately after saving a source file.&lt;/p&gt;

&lt;h2&gt;Version Control&lt;/h2&gt;

&lt;p&gt;I&amp;#8217;ve watched both git and Subversion fall apart as a codebase grows.  git is so faaast&amp;#8230;  until you import a 20 GB repository.  Then it&amp;#8217;s &lt;code&gt;O(Files)&lt;/code&gt; just like everything else.&lt;/p&gt;

&lt;pre&gt;
$ time git status
# On branch master
nothing to commit (working directory clean)

real    0m9.603s
user    0m0.858s
sys     0m7.378s
&lt;/pre&gt;

&lt;p&gt;10 seconds to see what files I&amp;#8217;ve modified.  Ouch.&lt;/p&gt;

&lt;p&gt;Imagine if ibb could keep track of which files have changed&amp;#8230;&lt;/p&gt;

&lt;h2&gt;What This Means For You&lt;/h2&gt;

&lt;p&gt;Running tests, grepping code, and building binaries from source are equivalent problems.  ibb&amp;#8217;s architecture supports lightning-fast implementations of all of the above.&lt;/p&gt;

&lt;p&gt;By converting an &lt;code&gt;O(Time^2)&lt;/code&gt; build, test runner, or version control system to &lt;code&gt;O(1)&lt;/code&gt;, we eliminate hours of costly engineer time and encourage good habits like committing often and frequently running tests, no matter the age of the project.  Frankly, instant feedback feels great.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s crazy to me that this architecture isn&amp;#8217;t standard practice across development tools.&lt;/p&gt;

&lt;p&gt;Take &lt;a href="http://github.com/chadaustin/ibb"&gt;ibb&amp;#8217;s concepts or code&lt;/a&gt;, integrate it with your engineering processes, and improve the quality of your team&amp;#8217;s life today.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/chadaustin/~4/eisD9teKN2c" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://chadaustin.me/2010/03/your-version-control-and-build-systems-dont-scale-introducing-ibb/#comments" thr:count="3" />
		<link rel="replies" type="application/atom+xml" href="http://chadaustin.me/2010/03/your-version-control-and-build-systems-dont-scale-introducing-ibb/feed/atom/" thr:count="3" />
		<thr:total>3</thr:total>
	</entry>
		<entry>
		<author>
			<name>Chad Austin</name>
						<uri>http://aegisknight.org/</uri>
					</author>
		<title type="html"><![CDATA[The Completionist&#8217;s Guide to Sims 3 iPhone]]></title>
		<link rel="alternate" type="text/html" href="http://chadaustin.me/2010/01/the-completionists-guide-to-sims-3-iphone/" />
		<id>http://chadaustin.me/?p=1495</id>
		<updated>2010-01-05T03:56:25Z</updated>
		<published>2010-01-05T03:54:11Z</published>
		<category scheme="http://chadaustin.me" term="Uncategorized" /><category scheme="http://chadaustin.me" term="design" /><category scheme="http://chadaustin.me" term="games" />		<summary type="html"><![CDATA[I play simulation games in two phases: first, I tackle the often-repetitive mechanics, unlocking every option and building up money so that I can creatively decorate my house or farm or whatever.

Sims 3 for iPhone was no different.  Having accomplished nearly everything in the game, I will share a strategy for completing all 73 [...]]]></summary>
		<content type="html" xml:base="http://chadaustin.me/2010/01/the-completionists-guide-to-sims-3-iphone/">&lt;p&gt;I play simulation games in two phases: first, I tackle the often-repetitive mechanics, unlocking every option and building up money so that I can creatively decorate my house or farm or whatever.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.ea.com/games/the-sims-3-iphone"&gt;Sims 3 for iPhone&lt;/a&gt; was no different.  Having accomplished nearly everything in the game, I will share a strategy for completing all 73 goals and acquiring the best job: $600 per day at the Pawn Shop.&lt;/p&gt;

&lt;h2&gt;The Objective&lt;/h2&gt;

&lt;p&gt;To open the pawn shop, you must complete the following 73 goals:&lt;/p&gt;

&lt;h3&gt;Goals for all Sims (55)&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Try fishing&lt;/li&gt;
&lt;li&gt;Try cooking&lt;/li&gt;
&lt;li&gt;Buy fishing kit&lt;/li&gt;
&lt;li&gt;Buy watering can&lt;/li&gt;
&lt;li&gt;Buy repair kit&lt;/li&gt;
&lt;li&gt;Buy a stove&lt;/li&gt;
&lt;li&gt;Buy a bath&lt;/li&gt;
&lt;li&gt;Gain a skill point at cooking&lt;/li&gt;
&lt;li&gt;Gain a skill point at fishing&lt;/li&gt;
&lt;li&gt;Gain a skill point at repairing&lt;/li&gt;
&lt;li&gt;Meet a new Sim&lt;/li&gt;
&lt;li&gt;Befriend a Sim&lt;/li&gt;
&lt;li&gt;Begin a romantic relationship&lt;/li&gt;
&lt;li&gt;Make an enemy&lt;/li&gt;
&lt;li&gt;Make a Sim laugh&lt;/li&gt;
&lt;li&gt;Annoy a Sim&lt;/li&gt;
&lt;li&gt;Insult a Sim&lt;/li&gt;
&lt;li&gt;Creep-out another Sim&lt;/li&gt;
&lt;li&gt;Slap a Sim&lt;/li&gt;
&lt;li&gt;Get a job&lt;/li&gt;
&lt;li&gt;Buy something&lt;/li&gt;
&lt;li&gt;Catch a fish&lt;/li&gt;
&lt;li&gt;Catch a trout&lt;/li&gt;
&lt;li&gt;Catch a salmon&lt;/li&gt;
&lt;li&gt;Catch a catfish&lt;/li&gt;
&lt;li&gt;Repair something&lt;/li&gt;
&lt;li&gt;Discover a new recipe&lt;/li&gt;
&lt;li&gt;Cook something&lt;/li&gt;
&lt;li&gt;Cook grilled cheese&lt;/li&gt;
&lt;li&gt;Cook steak &amp;#038; veggies&lt;/li&gt;
&lt;li&gt;Cook minestrone&lt;/li&gt;
&lt;li&gt;Grow something&lt;/li&gt;
&lt;li&gt;Grow carrots&lt;/li&gt;
&lt;li&gt;Grow corn&lt;/li&gt;
&lt;li&gt;Grow tomato&lt;/li&gt;
&lt;li&gt;Watch TV&lt;/li&gt;
&lt;li&gt;Kick over a Trash Can&lt;/li&gt;
&lt;li&gt;Sleep in another Sim&amp;#8217;s bed&lt;/li&gt;
&lt;li&gt;Use another Sim&amp;#8217;s shower&lt;/li&gt;
&lt;li&gt;Use another Sim&amp;#8217;s toilet&lt;/li&gt;
&lt;li&gt;Get a better couch&lt;/li&gt;
&lt;li&gt;Get a better TV&lt;/li&gt;
&lt;li&gt;Accumulate $1000&lt;/li&gt;
&lt;li&gt;Catch 15 fish&lt;/li&gt;
&lt;li&gt;Harvest 30 crops&lt;/li&gt;
&lt;li&gt;Stay entertained for three days&lt;/li&gt;
&lt;li&gt;Stay fed for three days&lt;/li&gt;
&lt;li&gt;Stay rested for three days&lt;/li&gt;
&lt;li&gt;Stay clean for three days&lt;/li&gt;
&lt;li&gt;Meet all the Sims in town&lt;/li&gt;
&lt;li&gt;Make a Sim jealous of you&lt;/li&gt;
&lt;li&gt;Sleep in three other Sim&amp;#8217;s beds&lt;/li&gt;
&lt;li&gt;WooHoo with someone&lt;/li&gt;
&lt;li&gt;Get a promotion&lt;/li&gt;
&lt;li&gt;Reach the top of the career ladder&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Maniac Personal Goals (4)&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use everyone&amp;#8217;s toilet at least once&lt;/li&gt;
&lt;li&gt;Use everyone&amp;#8217;s shower at least once&lt;/li&gt;
&lt;li&gt;Creep out five people&lt;/li&gt;
&lt;li&gt;Watch three people sleeping&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Sleaze Personal Goals (2)&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Be romantically involved with three Sims&lt;/li&gt;
&lt;li&gt;WooHoo eight times in one day&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Power Seeker Personal Goals (3)&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Accumulate $5000&lt;/li&gt;
&lt;li&gt;Own the best house&lt;/li&gt;
&lt;li&gt;Own the best TV, stereo and stove&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Nice Guy Personal Goals (2)&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Get married&lt;/li&gt;
&lt;li&gt;Be liked by all the Sims in town&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Jerk Personal Goals (4)&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Be disliked by all the Sims in town&lt;/li&gt;
&lt;li&gt;Slap four people&lt;/li&gt;
&lt;li&gt;Insult five people&lt;/li&gt;
&lt;li&gt;Kick over all the trash cans in town&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Jack of All Trades Personal Goals (3)&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Achieve the highest fishing skill level&lt;/li&gt;
&lt;li&gt;Achieve the highest repairing skill level&lt;/li&gt;
&lt;li&gt;Achieve the highest cooking skill level&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are six Sim classes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jack of All Trades&lt;/li&gt;
&lt;li&gt;Nice Guy&lt;/li&gt;
&lt;li&gt;Jerk&lt;/li&gt;
&lt;li&gt;Sleaze&lt;/li&gt;
&lt;li&gt;Power Seeker&lt;/li&gt;
&lt;li&gt;Maniac&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As previously mentioned, you will need to complete every Goal to unlock the Pawn Shop.  Of the 73 total Goals, 55 randomly appear as Wishes, no matter which Sim class you choose, and they&amp;#8217;re generally easy to complete.&lt;/p&gt;

&lt;p&gt;On the other hand, each Sim&amp;#8217;s Personal Goals are relatively difficult.  You&amp;#8217;ll need to create at least six Sims, one of each type.  For the optimal path through the game, you should complete their personal goals from hardest to easiest.  I will give an efficient play sequence below.&lt;/p&gt;

&lt;h2&gt;Play Order&lt;/h2&gt;

&lt;h3&gt;Jack of All Trades&lt;/h3&gt;

&lt;p&gt;Create six Sims, and designate one as your &amp;#8220;main&amp;#8221; Sim.  Your main Sim is the one with which you most identify.&lt;/p&gt;

&lt;p&gt;Your main Sim is a Jack of All Trades (you&amp;#8217;ll later need its Repair skill at the Pawn Shop).  Play him or her first, building up skill levels as rapidly as possible.  Learn to fish, because fishing is the best way to make money.  As you accumulate money, buy as many of the cheapest stereos you can afford, filling your house.  Each time you enter the house to eat or rest, turn them all on.  Eventually, they will start breaking down, allowing you to practice repairing.&lt;/p&gt;

&lt;p&gt;Practicing cooking is easy &amp;#8211; simply buy bread, cheese, and the Grilled Cheese recipe and make it over and over again.&lt;/p&gt;

&lt;p&gt;Once fishing, repairing, and cooking are level 5, save, quit and move to the next Sim.&lt;/p&gt;

&lt;h3&gt;Power Seeker&lt;/h3&gt;

&lt;p&gt;Your second Sim is your Power Seeker.  Fish until you have $5000 and tool around town until you have the option to upgrade your house twice and buy the most expensive TV, stereo, and stove.  Furniture and home upgrades simply take time.  This is a good opportunity to accumulate general Goals.&lt;/p&gt;

&lt;p&gt;At this point, you should have most of the 55 general Goals.&lt;/p&gt;

&lt;h3&gt;The Other Sim Types&lt;/h3&gt;

&lt;p&gt;Sleaze, Nice Guy, Jerk, and Maniac have fairly easy Personal Goals.  The order in which you complete them does not matter.&lt;/p&gt;

&lt;p&gt;At this point, you should have almost all of the Personal Goals.  If not, keep playing &amp;#8212; they&amp;#8217;ll eventually show up.&lt;/p&gt;

&lt;h3&gt;Goal Tips&lt;/h3&gt;

&lt;p&gt;If you need the &amp;#8220;Buy XXX&amp;#8221; goal but you already have XXX, then try selling it.  Eventually the Goal should appear as a Wish.  Lock it in and repurchase the item.&lt;/p&gt;

&lt;p&gt;If you need the &amp;#8220;Gain a skill point at XXX&amp;#8221; goal and you&amp;#8217;re maxed out, switch to a Sim that is not maxed out.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re having trouble Meeting all Sims, double-check all of the houses at different times of the day.  I&amp;#8217;ve noticed Bernie can be hard to find.  Most Sims are sleeping in the middle of the night &amp;#8211; try breaking into their houses, waking them up, and meeting them.&lt;/p&gt;

&lt;p&gt;If you need to befriend a Sim but you&amp;#8217;re already friends with all of the Sims, start a new Sim or insult a Sim until it becomes an enemy, then befriend him or her.&lt;/p&gt;

&lt;p&gt;The best way to annoy, insult, and creep-out other Sims is to find a house with two Sims (e.g. Marcell and Theresa), barge in, and start flirting with one of them.  Both will be creeped out and annoyed, and the flirting will insult the other and make him or her jealous.  If that doesn&amp;#8217;t work, start using their toilet, shower, and fridge.&lt;/p&gt;

&lt;h2&gt;Tips and Tricks&lt;/h2&gt;

&lt;p&gt;Fishing is the best way to make money.  Each tuna sells at QuickMart for $100, and salmon for $65.&lt;/p&gt;

&lt;p&gt;Besides the Pawn Shop, working at the Town Hall is the best.  It&amp;#8217;s easy to get promotions (both Ruth and the Town Hall are nearby) and you just need to be friends with everyone in town.  As Vice President, you can make $300 per day.&lt;/p&gt;

&lt;p&gt;Creating romantic relationships is easy.  It sounds rude, but keep pestering the Sim with Flirt, Tender Embrace, Hot Smooch, and WooHoo.  You should be able marry a Sim within two conversations.&lt;/p&gt;

&lt;p&gt;Too many WooHoos and your Sim will die!  Don&amp;#8217;t overdo it in the bedroom!&lt;/p&gt;

&lt;p&gt;If you get married, give your spouse a phone call and invite him or her over.  Once your spouse arrives, you can invite him or her to move in.&lt;/p&gt;

&lt;p&gt;Since the Town Hall is right by your house, it&amp;#8217;s the best job until the Pawn Shop is open.&lt;/p&gt;

&lt;h2&gt;The Sims&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Nina&lt;/li&gt;
&lt;li&gt;Ruth&lt;/li&gt;
&lt;li&gt;Johnny&lt;/li&gt;
&lt;li&gt;Kia&lt;/li&gt;
&lt;li&gt;Jake&lt;/li&gt;
&lt;li&gt;Maggie&lt;/li&gt;
&lt;li&gt;Jack&lt;/li&gt;
&lt;li&gt;Jill&lt;/li&gt;
&lt;li&gt;Walter&lt;/li&gt;
&lt;li&gt;Luke&lt;/li&gt;
&lt;li&gt;Bernie&lt;/li&gt;
&lt;li&gt;Marcell&lt;/li&gt;
&lt;li&gt;Theresa&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;The Jobs&lt;/h2&gt;

&lt;h3&gt;Town Hall (boss: Ruth)&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Campaign Intern ($100/day) M-F 8:30-18:00&lt;/li&gt;
&lt;li&gt;City Council Member ($150/day) M-F 8:30-18:00&lt;/li&gt;
&lt;li&gt;Local Representative ($200/day) M-F 9:00-18:00&lt;/li&gt;
&lt;li&gt;Mayor ($250/day) M-F 10:00-18:00&lt;/li&gt;
&lt;li&gt;Vice President ($300/day) M-F 10:00-17:00&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Corsican Bistro (boss: Marcell)&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Kitchen Scullion ($100/day) M-F 10:30-18:30&lt;/li&gt;
&lt;li&gt;Ingredient Taster ($150/day) M-F 10:30-18:30&lt;/li&gt;
&lt;li&gt;Line Chef ($200/day) Tue-Sat 11:00-17:00&lt;/li&gt;
&lt;li&gt;Sous-Chef ($250/day) Tue-Sat 11:00-17:00&lt;/li&gt;
&lt;li&gt;Chef de Cuisine ($300/day) Tue-Fri 11:00-17:00&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Laboratory (boss: Kia)&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Test Subject ($100/day) M-F 9:00-16:00&lt;/li&gt;
&lt;li&gt;Lab Tech ($150/day) M-F 09:00-16:00&lt;/li&gt;
&lt;li&gt;Fertilizer Analyst ($200/day) M-F 09:00-16:00&lt;/li&gt;
&lt;li&gt;Carnivorous Plant Tender ($250/day) M-F 09:00-16:00&lt;/li&gt;
&lt;li&gt;Genetic Resequencer ($300/day) M-F 10:00-16:00&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Quickmart (boss: Bernie)&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Filing Clerk ($100/day) M-F 08:30-18:30&lt;/li&gt;
&lt;li&gt;It&amp;#8217;s not worth getting promotions at Quickmart.  Bernie is a dick and you have to work there FOREVER before he&amp;#8217;ll promote you.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Pawn Shop (boss: Nina)&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Con Artist ($300/day) M-F 16:30-23:55&lt;/li&gt;
&lt;li&gt;Safecracker ($400/day) M-F 16:30-23:55&lt;/li&gt;
&lt;li&gt;Cat Burglar ($500/day) M-F 17:00-23:55&lt;/li&gt;
&lt;li&gt;Master Thief ($600/day) M-F 17:00-23:00&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;In the End&lt;/h2&gt;

&lt;p&gt;With the information given above, you should have no problem achieving 73 goals and as much money as you need to decorate your dream home.&lt;/p&gt;

&lt;p&gt;If you get stuck at any point, feel free to leave a comment on this page and I&amp;#8217;ll update the document.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/chadaustin/~4/3jQmia_I1bg" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://chadaustin.me/2010/01/the-completionists-guide-to-sims-3-iphone/#comments" thr:count="2" />
		<link rel="replies" type="application/atom+xml" href="http://chadaustin.me/2010/01/the-completionists-guide-to-sims-3-iphone/feed/atom/" thr:count="2" />
		<thr:total>2</thr:total>
	</entry>
		<entry>
		<author>
			<name>Chad Austin</name>
						<uri>http://aegisknight.org/</uri>
					</author>
		<title type="html"><![CDATA[Comparing Final Fantasy III to Final Fantasy IV]]></title>
		<link rel="alternate" type="text/html" href="http://chadaustin.me/2010/01/comparing-ff3-to-ffantasy-iv/" />
		<id>http://chadaustin.me/?p=1491</id>
		<updated>2010-01-05T03:57:31Z</updated>
		<published>2010-01-02T07:35:02Z</published>
		<category scheme="http://chadaustin.me" term="Uncategorized" /><category scheme="http://chadaustin.me" term="games design" />		<summary type="html"><![CDATA[Having grown up with Final Fantasy IV on SNES, I recently enjoyed playing through Final Fantasy III.  For my own edification and those curious, I&#8217;d like to note some of the design similarities between the games, providing color on the evolution of the Final Fantasy franchise.


Airships are a primary theme, both as transportation and [...]]]></summary>
		<content type="html" xml:base="http://chadaustin.me/2010/01/comparing-ff3-to-ffantasy-iv/">&lt;p&gt;Having grown up with Final Fantasy IV on SNES, I recently enjoyed playing through &lt;a href="http://www.amazon.com/gp/product/B000GABOTU?ie=UTF8&amp;#038;tag=aegisknightor-20&amp;#038;linkCode=as2&amp;#038;camp=1789&amp;#038;creative=390957&amp;#038;creativeASIN=B000GABOTU"&gt;Final Fantasy III&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=aegisknightor-20&amp;#038;l=as2&amp;#038;o=1&amp;#038;a=B000GABOTU" width="1" height="1" alt="" style="border:none !important; margin:0px !important;" /&gt;.  For my own edification and those curious, I&amp;#8217;d like to note some of the design similarities between the games, providing color on the evolution of the Final Fantasy franchise.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Airships are a primary theme, both as transportation and cultural status.&lt;/li&gt;
&lt;li&gt;Final Fantasy 3 introduced the character class system in a big way, setting the stage for the classes used in FF4&amp;#8217;s story.&lt;/li&gt;
&lt;li&gt;Desch and Yang provide similar service to their respective stories: help the party for a while, followed by dramatic sacrifice.&lt;/li&gt;
&lt;li&gt;FF3 introduced the Toad and Mini status effects as first-class gameplay elements.  Toad allows you to swim and Mini allows you to fit in tiny passages.  While Mini, your attacks are useless but magic still works.  These status effects remained in FF4, although vestigial.  (I always wondered why &amp;#8220;mini-mages&amp;#8221; were so common in FF4.  Without having played FF3, they didn&amp;#8217;t make sense.)&lt;/li&gt;
&lt;li&gt;FF3 introduced the Leviathan, Odin, Bahamut hierarchy.&lt;/li&gt;
&lt;li&gt;Eureka (FF3) paralleled the Lunar Subterrane (FF4).  They&amp;#8217;re both extremely hard when you first enter, but they force the party to gain about ten levels.  In addition, they contain several smaller bosses and a bunch of powerful equipment.  Both provide a sense of progress and accomplishment, without feeling like grind.&lt;/li&gt;
&lt;li&gt;The last areas and bosses of both games are unusually difficult.  They each took me multiple attempts to complete.&lt;/li&gt;
&lt;li&gt;In both final battles, previous allies provide &amp;#8220;spiritual assistance&amp;#8221;, making it possible to defeat the overpowering final boss.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However incomplete this list, these are the similarities I noted.  Final Fantasy 3 had not quite discovered the Final Fantasy &amp;#8220;sauce&amp;#8221;, but it was an important step along the way.&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/chadaustin/~4/LQPKbzlE_Iw" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://chadaustin.me/2010/01/comparing-ff3-to-ffantasy-iv/#comments" thr:count="1" />
		<link rel="replies" type="application/atom+xml" href="http://chadaustin.me/2010/01/comparing-ff3-to-ffantasy-iv/feed/atom/" thr:count="1" />
		<thr:total>1</thr:total>
	</entry>
		<entry>
		<author>
			<name>Chad Austin</name>
						<uri>http://aegisknight.org/</uri>
					</author>
		<title type="html"><![CDATA[Avoid Manual Initialization]]></title>
		<link rel="alternate" type="text/html" href="http://chadaustin.me/2010/01/avoid-manual-initialization/" />
		<id>http://chadaustin.me/?p=1487</id>
		<updated>2010-01-01T07:20:39Z</updated>
		<published>2010-01-01T07:20:39Z</published>
		<category scheme="http://chadaustin.me" term="Uncategorized" /><category scheme="http://chadaustin.me" term="design" />		<summary type="html"><![CDATA[Too many software libraries require that you manually initialize them before use.  As illustration:


library.initialize()
window = library.createLibraryObject()


Why require your users to remember initialization busywork?  createLibraryObject should initialize the library, refcounting the initialization if necessary.

The primary benefit is cognitive.  If a library requires initialization, its objects and functions have an additional, externally-visible behavior: &#8220;If [...]]]></summary>
		<content type="html" xml:base="http://chadaustin.me/2010/01/avoid-manual-initialization/">&lt;p&gt;Too many software libraries require that you manually initialize them before use.  As illustration:&lt;/p&gt;

&lt;pre&gt;
library.initialize()
window = library.createLibraryObject()
&lt;/pre&gt;

&lt;p&gt;Why require your users to remember initialization busywork?  createLibraryObject should initialize the library, refcounting the initialization if necessary.&lt;/p&gt;

&lt;p&gt;The primary benefit is cognitive.  If a library requires initialization, its objects and functions have an additional, externally-visible behavior: &amp;#8220;If not initialized, return error.&amp;#8221;&lt;/p&gt;

&lt;p&gt;If the library&amp;#8217;s internal state is managed implicitly, it does not leak out of the API.  createLibraryObject should lazily initialize the library on object construction.  Optionally, on object destruction, it can deinitialize the library.&lt;/p&gt;

&lt;p&gt;A secondary benefit of lazy initialization is performance: interactive desktop applications rarely need immediate access to all of its subsystems.  By deferring as much initialization as possible, application startup time is reduced.&lt;/p&gt;

&lt;p&gt;[This post is a test of my new host: &lt;a href="http://prgmr.com/xen/"&gt;prgmr.com&lt;/a&gt;]&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/chadaustin/~4/8W6-l9uG03c" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://chadaustin.me/2010/01/avoid-manual-initialization/#comments" thr:count="3" />
		<link rel="replies" type="application/atom+xml" href="http://chadaustin.me/2010/01/avoid-manual-initialization/feed/atom/" thr:count="3" />
		<thr:total>3</thr:total>
	</entry>
		<entry>
		<author>
			<name>Chad Austin</name>
						<uri>http://aegisknight.org/</uri>
					</author>
		<title type="html"><![CDATA[9 Reasons Why MinTTY is the Best Terminal on Windows]]></title>
		<link rel="alternate" type="text/html" href="http://chadaustin.me/2009/10/reasons-why-mintty-is-the-best-terminal-on-windows/" />
		<id>http://chadaustin.me/?p=1473</id>
		<updated>2009-10-20T08:33:42Z</updated>
		<published>2009-10-20T08:24:25Z</published>
		<category scheme="http://chadaustin.me" term="Uncategorized" />		<summary type="html"><![CDATA[MinTTY is a fantastic piece of software that smoothes some of the edges of the Windows command line experience.  You should use it and here&#8217;s why:

MinTTY comes with Cygwin

Installing MinTTY is trivial: just select the mintty package in Cygwin&#8217;s setup.exe and point your Cygwin shortcut to C:\cygwin\bin\mintty.exe -.  The trailing hyphen is important.



Sane [...]]]></summary>
		<content type="html" xml:base="http://chadaustin.me/2009/10/reasons-why-mintty-is-the-best-terminal-on-windows/">&lt;p&gt;&lt;a href="http://code.google.com/p/mintty/"&gt;MinTTY&lt;/a&gt; is a fantastic piece of software that smoothes some of the edges of the Windows command line experience.  You should use it and here&amp;#8217;s why:&lt;/p&gt;

&lt;ol class="boldbullets" start="1"&gt;&lt;li&gt;MinTTY comes with Cygwin&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Installing MinTTY is trivial: just select the mintty package in Cygwin&amp;#8217;s setup.exe and point your Cygwin shortcut to &lt;code&gt;C:\cygwin\bin\mintty.exe -&lt;/code&gt;.  The trailing hyphen is important.&lt;/p&gt;

&lt;a href="http://aegisknight.org/wp-uploads/mintty_setup.png"&gt;&lt;img src="http://aegisknight.org/wp-uploads/mintty_setup-300x215.png" alt="MinTTY Setup" title="MinTTY Setup" width="300" height="215" class="aligncenter size-medium wp-image-1474" /&gt;&lt;/a&gt;

&lt;ol class="boldbullets" start="2"&gt;&lt;li&gt;Sane copy and paste&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;By default, MinTTY copies on select and pastes on right-click, just like Linux.  However, you can make it behave like a typical Windows application and show a context menu upon right-click.&lt;/p&gt;

&lt;a href="http://aegisknight.org/wp-uploads/mintty_right_click.png"&gt;&lt;img src="http://aegisknight.org/wp-uploads/mintty_right_click-300x146.png" alt="MinTTY Context Menu" title="MinTTY Context Menu" width="300" height="146" class="aligncenter size-medium wp-image-1481" /&gt;&lt;/a&gt;

&lt;p&gt;I won&amp;#8217;t bother explaining how difficult copying and pasting is in standard Windows consoles.&lt;/p&gt;

&lt;ol class="boldbullets" start="3"&gt;&lt;li&gt;Resizing&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;MinTTY supports arbitrary window sizes, including maximized.  Enough said.&lt;/p&gt;

&lt;ol class="boldbullets" start="4"&gt;&lt;li&gt;Works with less/emacs/ssh&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Because MinTTY is based on PuTTY, it doesn&amp;#8217;t display output strangely when running emacs over ssh, among other examples.&lt;/p&gt;

&lt;ol class="boldbullets" start="5"&gt;&lt;li&gt;It&amp;#8217;s &lt;em&gt;FAST&lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Anyone who has done command line work on Windows has surely noticed that, when a program spews output to the console, system performance nosedives.  Sometimes, even the mouse cursor skips, making it hard to kill the program responsible.&lt;/p&gt;

&lt;p&gt;MinTTY doesn&amp;#8217;t have this problem &amp;#8212; it uses minimal CPU, even under heavy load.&lt;/p&gt;

&lt;ol class="boldbullets" start="6"&gt;&lt;li&gt;Doesn&amp;#8217;t bypass RSI Guard&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Five years ago, I was diagnosed with repetitive stress injuries from programming.  To make matters worse, I get obsessive when I work, and nothing can pull me away from the keyboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.rsiguard.com/"&gt;RSI Guard&lt;/a&gt; keeps my wrists and elbows pain-free by enforcing short, periodic breaks.  However&amp;#8230;  years of exposure to RSI Guard has caused me to discover its holes.  For example, native console windows bypass RSI Guard&amp;#8217;s protection, so when RSI Guard blocked keyboard and mouse input, I would quickly switch to typing in a console window and continue to work.  Because MinTTY is a standard Windows application, it closes this backdoor.&lt;/p&gt;

&lt;ol class="boldbullets" start="7"&gt;&lt;li&gt;Closes even when programs are backgrounded&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Open a fresh Cygwin and type &lt;code&gt;notepad &amp;amp;&lt;/code&gt; followed by &lt;code&gt;exit&lt;/code&gt;.  The Cygwin console sticks open until you close Notepad.&lt;/p&gt;

&lt;p&gt;In MinTTY, you can always close the window, no matter how many background processes you&amp;#8217;ve started.&lt;/p&gt;

&lt;ol class="boldbullets" start="8"&gt;&lt;li&gt;Alt-F2 opens a new terminal window&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Pure convenience: Alt-F2 opens a new terminal.  No need to reach for the mouse.&lt;/p&gt;

&lt;ol class="boldbullets" start="9"&gt;&lt;li&gt;Shift-PageUp and Shift-PageDown!&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;For rapidly paging through previous lines of output, you can press Shift-PageUp and Shift-PageDown, just like the Linux console.  Another huge convenience.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/chadaustin/~4/4KpZNox6Axw" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://chadaustin.me/2009/10/reasons-why-mintty-is-the-best-terminal-on-windows/#comments" thr:count="6" />
		<link rel="replies" type="application/atom+xml" href="http://chadaustin.me/2009/10/reasons-why-mintty-is-the-best-terminal-on-windows/feed/atom/" thr:count="6" />
		<thr:total>6</thr:total>
	</entry>
		<entry>
		<author>
			<name>Chad Austin</name>
						<uri>http://aegisknight.org/</uri>
					</author>
		<title type="html"><![CDATA[OpenCL Rocks: Why You Care]]></title>
		<link rel="alternate" type="text/html" href="http://chadaustin.me/2009/08/opencl-rocks-why-you-care/" />
		<id>http://chadaustin.me/?p=1467</id>
		<updated>2009-08-24T05:28:08Z</updated>
		<published>2009-08-24T05:25:18Z</published>
		<category scheme="http://chadaustin.me" term="Uncategorized" />		<summary type="html"><![CDATA[Today I attended the Hot Chips 2009 conference, where I was introduced to OpenCL*.  I&#8217;d never heard of OpenCL before, but it&#8217;s totally hot and I will tell you why.

What is OpenCL?

OpenCL (Open Computing Library) is an open and free API that lets your programs efficiently leverage all of the computing power in your [...]]]></summary>
		<content type="html" xml:base="http://chadaustin.me/2009/08/opencl-rocks-why-you-care/">&lt;p&gt;Today I attended the &lt;a href="http://www.hotchips.org/hc21/program/tutorials.htm"&gt;Hot Chips 2009&lt;/a&gt; conference, where I was introduced to OpenCL*.  I&amp;#8217;d never heard of &lt;a href="http://www.khronos.org/opencl/"&gt;OpenCL&lt;/a&gt; before, but it&amp;#8217;s totally hot and I will tell you why.&lt;/p&gt;

&lt;h2&gt;What is OpenCL?&lt;/h2&gt;

&lt;p&gt;OpenCL (Open Computing Library) is an open and free API that lets your programs efficiently leverage all of the computing power in your computer, including multiple CPU cores, vector computation units, GPUs, Cell coprocessors, DSPs, etc.  OpenCL programs, called kernels, are written in a variant of C and are automatically scheduled across your available hardware.  Your customers don&amp;#8217;t have a GPU but their processor has 2 or 4 cores?  No problem: OpenCL will utilize that spare power.&lt;/p&gt;

&lt;p&gt;In addition, OpenCL specifies 4-, 8-, and 16-wide SIMD vector types, meaning it can easily leverage both the vector computation units on GPUs and extended vector instruction sets on CPUs, such as SSE and AVX.  (Looking forward to Larrabee.)&lt;/p&gt;

&lt;p&gt;With OpenCL, Apple and the Khronos Group are cleanly solving two clear market needs: we have increasing amounts of computational hardware available to us, but each bit of hardware is a bit different, with separate APIs, performance, and instruction sets.  As much as possible, OpenCL unifies the interface to this hardware.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s true that GPUs and CPUs have different performance characteristics, but the same types of programs run efficiently on both: do way more math than memory loads and split your program into large parallel chunks.&lt;/p&gt;

&lt;h2&gt;Where do I get it?&lt;/h2&gt;

&lt;p&gt;The major vendors are starting to provide OpenCL implementations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.apple.com/macosx/technology/"&gt;Apple&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.nvidia.com/object/cuda_opencl.html"&gt;NVIDIA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.amd.com/us/press-releases/Pages/amd-delivers-and-submits-2009aug04.aspx"&gt;AMD/ATI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Intel&amp;#8217;s on the way, I&amp;#8217;m sure.  I expect we&amp;#8217;ll see an OpenCL implementation on Larrabee as well.&lt;/p&gt;

&lt;h2&gt;How do I use it?&lt;/h2&gt;

&lt;p&gt;OpenCL programs are called kernels &amp;#8212; functions that run in parallel across large amounts of data.  You&amp;#8217;re given a lot of freedom: OpenCL uses a variant of the C99 programming language, with only a handful of restrictions.&lt;/p&gt;

&lt;p&gt;If you find that too onerous, you can use OpenCL with native functions you&amp;#8217;ve already written!  Just let it schedule your tasks and manage task dependencies to easily get started running code on multiple cores.&lt;/p&gt;

&lt;p&gt;I won&amp;#8217;t go into the details of the memory model or API; you can look that up on &lt;a href="http://www.google.com/search?q=&amp;quot;opencl&amp;quot;+tutorial"&gt;Google&lt;/a&gt;.  However, here&amp;#8217;s an example kernel:&lt;/p&gt;

&lt;pre&gt;
kernel void square(
    global float* input,
    global float* output
) {
    int i = get_global_id(0);
    output[i] = input[i] * input[i];
}
&lt;/pre&gt;

&lt;p&gt;It squares a bunch of numbers in an array, storing the results in an output array.  This trivial example will easily consume all of the compute power in your system.  (Defining compute to mean ALU + memory, of course&amp;#8230;)&lt;/p&gt;

&lt;h2&gt;Next Steps&lt;/h2&gt;

&lt;p&gt;I hope that&amp;#8217;s enough information to get you excited about OpenCL!  OpenCL is a huge step towards transparently leveraging additional cores, vector instructions, and GPUs.&lt;/p&gt;

&lt;p&gt;* Full disclaimer: I have never actually used OpenCL, but I&amp;#8217;ve definitely struggled with the problems it solves.  The IMVU client has some optimized inner loops that we&amp;#8217;ve hand-implemented for the GPU, SSE, or C-compiled x87 code.  Unfortunately, we have had to manually select between those code paths based on the capabilities of the hardware.  This sucks.  With even decent OpenCL implementations, we could avoid all of that work and transparently benefit from future hardware improvements.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/chadaustin/~4/_klnp1zNgmE" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://chadaustin.me/2009/08/opencl-rocks-why-you-care/#comments" thr:count="1" />
		<link rel="replies" type="application/atom+xml" href="http://chadaustin.me/2009/08/opencl-rocks-why-you-care/feed/atom/" thr:count="1" />
		<thr:total>1</thr:total>
	</entry>
		<entry>
		<author>
			<name>Chad Austin</name>
						<uri>http://aegisknight.org/</uri>
					</author>
		<title type="html"><![CDATA[IMVU Crash Reporting: Stalls and Deadlocks]]></title>
		<link rel="alternate" type="text/html" href="http://chadaustin.me/2009/06/imvu-crash-reporting-stalls-and-deadlocks/" />
		<id>http://aegisknight.org/?p=1457</id>
		<updated>2009-06-18T06:52:38Z</updated>
		<published>2009-06-18T06:52:38Z</published>
		<category scheme="http://chadaustin.me" term="Uncategorized" /><category scheme="http://chadaustin.me" term="c++" /><category scheme="http://chadaustin.me" term="crashes" /><category scheme="http://chadaustin.me" term="imvu" /><category scheme="http://chadaustin.me" term="python" />		<summary type="html"><![CDATA[By mid-2006, we&#8217;d primarily focused on access violations and unhandled exceptions, the explosive application failures.  After extensive effort, we got our client&#8217;s crash rate down to 2% or so, where 2% of all sessions ended in a crash.*  Still the customers cried &#8220;Fix the crashes!&#8221;

It turns out that when a customer says &#8220;crash&#8221; [...]]]></summary>
		<content type="html" xml:base="http://chadaustin.me/2009/06/imvu-crash-reporting-stalls-and-deadlocks/">&lt;p&gt;By mid-2006, we&amp;#8217;d primarily focused on access violations and unhandled exceptions, the explosive application failures.  After extensive effort, we got our client&amp;#8217;s crash rate down to 2% or so, where 2% of all sessions ended in a crash.&lt;a href="#footnote_session_length"&gt;*&lt;/a&gt;  Still the customers cried &amp;#8220;Fix the crashes!&amp;#8221;&lt;/p&gt;

&lt;p&gt;It turns out that when a customer says &amp;#8220;crash&amp;#8221; they mean &amp;#8220;it stopped doing what I wanted&amp;#8221;, but engineers hear &amp;#8220;the program threw an exception or caused an access violation&amp;#8221;.  Thus, to the customer, crash can mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the application was unresponsive for a period of time&lt;/li&gt;
&lt;li&gt;the UI failed to load, making the client unusable&lt;/li&gt;
&lt;li&gt;the application has been disconnected from the server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, any time the customer cannot make progress and it&amp;#8217;s not (perceived to be) their fault, the application has crashed.&lt;/p&gt;

&lt;p&gt;OK, we&amp;#8217;ve got our work cut out for us&amp;#8230;  Let&amp;#8217;s start by considering deadlocks and stalls.&lt;/p&gt;

&lt;p&gt;First, some terminology: in computer science, a &lt;a href="http://en.wikipedia.org/wiki/Deadlock "&gt;deadlock&lt;/a&gt; is a situation where two threads or processes are waiting for each other, so neither makes progress.  That definition is a bit academic for our purposes.  Let&amp;#8217;s redefine deadlock as any situation where the program becomes unresponsive for an unreasonable length of time.  This definition includes &lt;a href="http://en.wikipedia.org/wiki/Livelock"&gt;livelock&lt;/a&gt;, slow operations without progress indication, and network (or disk!) I/O that blocks the program from responding to input.&lt;/p&gt;

&lt;p&gt;It actually doesn&amp;#8217;t matter whether the program will &lt;i&gt;eventually&lt;/i&gt; respond to input.  People get impatient quickly.  You&amp;#8217;ve only got a few seconds to respond to the customer&amp;#8217;s commands.&lt;/p&gt;

&lt;h2&gt;Detecting Deadlocks in C++&lt;/h2&gt;

&lt;p&gt;The embedded programming world has a &amp;#8220;&lt;a href="http://en.wikipedia.org/wiki/Watchdog_timer"&gt;watchdog timer&lt;/a&gt;&amp;#8221; concept.  Your program is responsible for periodically pinging the watchdog, and if for several seconds you don&amp;#8217;t, the watchdog restarts your program and reports debugging information.&lt;/p&gt;

&lt;p&gt;Implementing this in C++ is straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start a watchdog thread that wakes up every few seconds to check that the program is still responding to events.&lt;/li&gt;
&lt;li&gt;Add a heartbeat to your main event loop that frequently pings the watchdog.&lt;/li&gt;
&lt;li&gt;If the watchdog timer detects the program is unresponsive, record stack traces and log files, then report the failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;IMVU&amp;#8217;s &lt;a href="http://aegisknight.org/2009/04/imvus-callstack-api-now-open-source/"&gt;CallStack API&lt;/a&gt; allows us to grab the C++ call stack of an arbitrary thread, so, if the main thread is unresponsive, we report its current stack every couple of seconds.  This is often all that&amp;#8217;s needed to find and fix the deadlock.&lt;/p&gt;

&lt;h2&gt;Detecting Deadlocks in Python&lt;/h2&gt;

&lt;p&gt;In Python, we can take the same approach as above:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start a watchdog thread.&lt;/li&gt;
&lt;li&gt;Ping the Python watchdog thread in your main loop.&lt;/li&gt;
&lt;li&gt;If the watchdog detects that you&amp;#8217;re unresponsive, record the main thread&amp;#8217;s Python stack (this time with &lt;a href="http://docs.python.org/library/sys.html#sys._current_frames"&gt;sys._current_frames&lt;/a&gt;) and report it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Python&amp;#8217;s &lt;a href="http://docs.python.org/dev/glossary.html#term-global-interpreter-lock"&gt;global interpreter lock&lt;/a&gt; (GIL) can throw a wrench in this plan.  If one thread enters an infinite loop while keeping the GIL held (say, in a native extension), the watchdog thread will never wake and so cannot report a deadlock.  In practice, this isn&amp;#8217;t a problem, because the C++ deadlock detector will notice and report a deadlock.  Plus, most common deadlocks are caused by calls that release the GIL: &lt;code&gt;threading.Lock.acquire&lt;/code&gt;, &lt;code&gt;socket.read&lt;/code&gt;, &lt;code&gt;file.read&lt;/code&gt;, and so on.&lt;/p&gt;

&lt;p&gt;It might help to think of the Python deadlock detector as a fallback that, if successful, adds richer information to your deadlock reports.  If it failed, whatever.  The C++ deadlock detector is probably enough to diagnose and fix the problem.&lt;/p&gt;

&lt;h2&gt;What did we learn?&lt;/h2&gt;

&lt;p&gt;It turned out the IMVU client had several bugs where we blocked the main thread on the network, sometimes for up to 30 seconds.  By that point, most users just clicked the close box [X] and terminated the process.  Oops.&lt;/p&gt;

&lt;p&gt;In addition, the deadlock detectors pointed out places where we were doing too much work in between message pumps.  For example, loading some assets into the 3D scene might nominally take 200ms.  On a computer with 256 MB of RAM, though, the system might start thrashing and loading the same assets would take 5s and report as a &amp;#8220;deadlock&amp;#8221;.  The solution was to reducing the program&amp;#8217;s working set and bite off smaller chunks of work in between pumps.&lt;/p&gt;

&lt;p&gt;I don&amp;#8217;t recall seeing many &amp;#8220;computer science&amp;#8221; deadlocks, but these watchdogs were invaluable in tracking down important failure conditions in the IMVU client.&lt;/p&gt;

&lt;p&gt;Next time, we&amp;#8217;ll improve the accuracy of our crash metrics and answer the question &amp;#8220;How do you know your metrics are valid?&amp;#8221;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a id="footnote_session_length"&gt;*&lt;/a&gt; Median session length is a more useful reliability metric.  It&amp;#8217;s possible to fix crashes and see no change in your percentage of failed sessions, if fixing crashes simply causes sessions to become longer.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/chadaustin/~4/aGQJcaBlKPM" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://chadaustin.me/2009/06/imvu-crash-reporting-stalls-and-deadlocks/#comments" thr:count="4" />
		<link rel="replies" type="application/atom+xml" href="http://chadaustin.me/2009/06/imvu-crash-reporting-stalls-and-deadlocks/feed/atom/" thr:count="4" />
		<thr:total>4</thr:total>
	</entry>
		<entry>
		<author>
			<name>Chad Austin</name>
						<uri>http://aegisknight.org/</uri>
					</author>
		<title type="html"><![CDATA[How I Lost 20 Pounds in 20 Weeks With My iPhone (or: Data is King)]]></title>
		<link rel="alternate" type="text/html" href="http://chadaustin.me/2009/06/how-i-lost-20-pounds-in-20-weeks/" />
		<id>http://aegisknight.org/?p=1430</id>
		<updated>2009-06-07T21:53:27Z</updated>
		<published>2009-06-07T21:50:32Z</published>
		<category scheme="http://chadaustin.me" term="Uncategorized" /><category scheme="http://chadaustin.me" term="food" /><category scheme="http://chadaustin.me" term="iphone" /><category scheme="http://chadaustin.me" term="life" />		<summary type="html"><![CDATA[Well, it was really more like 17 weeks, but who&#8217;s counting.  ;)  First, I&#8217;ll give the punchline.



Chad, you were skinny! Why diet?


High school: 140 pounds
College: 150 pounds
Grad school: 160 pounds
After four years at IMVU in delicious downtown Palo Alto: 180 pounds


At my height, 180 lbs. isn&#8217;t terrible, but the trajectory is obviously wrong. [...]]]></summary>
		<content type="html" xml:base="http://chadaustin.me/2009/06/how-i-lost-20-pounds-in-20-weeks/">&lt;p&gt;Well, it was really more like 17 weeks, but who&amp;#8217;s counting.  ;)  First, I&amp;#8217;ll give the punchline.&lt;/p&gt;

&lt;a href="http://aegisknight.org/wp-uploads/goal.jpeg"&gt;&lt;img src="http://aegisknight.org/wp-uploads/goal-199x300.jpg" alt="Goal!" title="Goal!" width="199" height="300" class="aligncenter size-medium wp-image-1431" /&gt;&lt;/a&gt;

&lt;h2&gt;Chad, you were skinny! Why diet?&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;High school: 140 pounds&lt;/li&gt;
&lt;li&gt;College: 150 pounds&lt;/li&gt;
&lt;li&gt;Grad school: 160 pounds&lt;/li&gt;
&lt;li&gt;After four years at IMVU in delicious downtown Palo Alto: 180 pounds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At my height, 180 lbs. isn&amp;#8217;t terrible, but the trajectory is obviously wrong.  Without adjustments to my lifestyle, you can see what would happen.  So I started paying attention.&lt;/p&gt;

&lt;p&gt;In February, Laura and I got iPhones.  Shortly after, I discovered &lt;a href="http://www.freshapps.com/lose-it/"&gt;Lose It!&lt;/a&gt;, a calorie-counting and weight-tracking app.  I knew my eat-box-of-cheez-its-when-bored habit was bad, so I began simply tracking calories with Lose It!, hoping to break some bad habits.  After all, if you give an engineer some data, he&amp;#8217;ll optimize it.&lt;/p&gt;

&lt;p&gt;A few weeks later, I ended up reading &lt;a href="http://www.fourmilab.ch/hackdiet/"&gt;The Hacker&amp;#8217;s Diet&lt;/a&gt;.  It&amp;#8217;s a quick, educational, and inspirational read.  John Walker&amp;#8217;s thesis is that anyone can lose weight if they correct the flawed feedback mechanisms causing them to eat more than they consume every day.&lt;/p&gt;

&lt;p&gt;See, our bodies are complicated machines.  We can&amp;#8217;t entirely understand them, so we use models (created by people smarter than me) to help us predict how our bodies will behave under various inputs.  Thus, there are tons of weight loss plans, and I&amp;#8217;m sure they&amp;#8217;ve all worked for someone: all raw, low-carb, no-carb, low-calorie, intense exercise, glass of red wine every night, protein shakes in the morning, seven snacks a day, etc. etc.&lt;/p&gt;

&lt;p&gt;All of that is too complicated for me, so I chose the simplest model I knew: Calories In, Calories Out. It goes something like this:&lt;/p&gt;

&lt;h2&gt;The Hacker&amp;#8217;s Diet (Theory)&lt;/h2&gt;

&lt;p&gt;(I am not an expert!  This is what worked for me.  Consult your nutritionist and physician.  Don&amp;#8217;t starve yourself.  Take your vitamins.  Etc.)&lt;/p&gt;

&lt;pre&gt;
1 lb. of body fat = &lt;strong&gt;3500 calories&lt;/strong&gt;
Calories stored = calories eaten - calories burned
Every day, I eat X calories
Every day, I burn ~2500 calories
&lt;br/&gt;
If X &amp;gt; 2500, you will gain weight at (X-2500)/3500 pounds per day.
If X &amp;lt; 2500, you will lose weight at (2500-X)/3500 pounds per day.
&lt;/pre&gt;

&lt;p&gt;Thus, if you eat &lt;strong&gt;500 calories&lt;/strong&gt; less than you burn every day, you will lose &lt;strong&gt;one pound per week&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Key insight&lt;/em&gt;: this is not difficult!  For example, a strawberry milkshake from In-n-Out is 700 calories.  A 6 oz. frozen yogurt with strawberries and mangos from &lt;a href="http://www.fraicheyogurt.com/"&gt;Fraiche&lt;/a&gt; is 200 calories.  That&amp;#8217;s 500 calories saved right there!&lt;/p&gt;

&lt;a href="http://aegisknight.org/wp-uploads/fraiche-yogurt-250.jpg"&gt;&lt;img src="http://aegisknight.org/wp-uploads/fraiche-yogurt-250.jpg" alt="Fraiche" title="Fraiche" width="250" height="259" class="aligncenter size-full wp-image-1439" /&gt;&lt;/a&gt;

&lt;p&gt;Sounds great!  How do I deal with this on a day-to-day basis?&lt;/p&gt;

&lt;h2&gt;The Hacker&amp;#8217;s Diet (Practice)&lt;/h2&gt;

&lt;p&gt;My mother once told me &amp;#8220;Chad, be very careful with drugs and alcohol.  You have an obsessive personality.&amp;#8221;  She was absolutely right about the obsessive personality; fortunately, I&amp;#8217;ve &lt;a href="http://audiere.sourceforge.net/"&gt;learned&lt;/a&gt; to &lt;a href="http://corona.sourceforge.net/"&gt;channel&lt;/a&gt; my &lt;a href="http://aegisknight.org/sphere/"&gt;obsessions&lt;/a&gt; &lt;a href="http://aegisknight.org/hci_portfolio/"&gt;productively&lt;/a&gt;.  (Although I did spend a year and hundreds of dollars on &lt;a href="http://www.travian.us/"&gt;Travian&lt;/a&gt;&amp;#8230;)&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s how calorie-counting with Lose It! works in practice:&lt;/p&gt;

&lt;ol class="boldbullets"&gt;

&lt;li&gt;&lt;span&gt;Keep track of everything you eat.  This is pretty easy because their database contains most common foods.  If it&amp;#8217;s not in the database, just enter it yourself.  Record it right before or after you eat so you don&amp;#8217;t forget.&lt;/span&gt;&lt;/li&gt;

&lt;li&gt;&lt;span&gt;Estimate your daily caloric burn.  There are &lt;a href="http://www.caloriesperhour.com/index_burn.php"&gt;standard estimation formulae&lt;/a&gt;, but the exact amount doesn&amp;#8217;t matter a great deal.  If you are losing weight faster than you expected, increase your burn.  If you are losing weight slower than you expected, decrease your burn.  I started at 2500 calories/day, but shortly realized my actual burn was 2300 calories/day.&lt;/span&gt;&lt;/li&gt;

&lt;li&gt;&lt;span&gt;Stay within your daily calorie budget!  Treat it as a hard limit so that, if you screw up and eat a &lt;a href="http://www.in-n-out.com/"&gt;Double Double and Shake&lt;/a&gt; (1400 calories total) for lunch, you&amp;#8217;ll be very sad at dinner when you can&amp;#8217;t eat anything else.  :(  You won&amp;#8217;t make that mistake again.  &lt;strong&gt;*cough*&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt;

&lt;li&gt;&lt;span&gt;Drink water.  Take vitamins.  Sleep.  Take care of yourself if you get sick.&lt;/span&gt;&lt;/li&gt;

&lt;li&gt;&lt;span&gt;Weigh yourself every day.  Watch the mostly-linear progress!&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That&amp;#8217;s all there is to it!  Time + calorie deficit = easy weight loss!&lt;/p&gt;

&lt;p&gt;Really?  Surely there&amp;#8217;s more to it&amp;#8230;&lt;/p&gt;

&lt;h2&gt;Unexpected Side Effects&lt;/h2&gt;

&lt;ol class="boldbullets"&gt;
&lt;li&gt;&lt;span&gt;The first couple weeks after I reduced my caloric intake to ~1800, I got hungry.  Then tired.  REALLY TIRED.  I started sleeping 10 hours a night.  It turns out that your body is good at noticing &amp;#8220;Hey, where&amp;#8217;d the energy go?  Time to slow the engine down.&amp;#8221;  I suspect this is the part where most people quit, especially if they don&amp;#8217;t see immediate progress.  Remember: this effect is annoying, but temporary.  Your body will adjust to the reduced intake and before you know it you&amp;#8217;ll feel great again.&lt;/span&gt;&lt;/li&gt;

&lt;li&gt;&lt;span&gt;My headaches are GONE!  I used to get very frequent headaches related to low blood sugar.  Maybe burning fat means I have a more even supply of energy through the day?  Maybe eating less means my blood sugar doesn&amp;#8217;t spike?  Who knows, but I&amp;#8217;ll take it!&lt;/span&gt;&lt;/li&gt;

&lt;li&gt;&lt;span&gt;Body fat is an inert material.  For years, it quietly stores all kinds of chemicals and toxins.  Burning fat means those chemicals go into your bloodstream.  Some of those chemicals reek.  Thus, you will randomly smell like holy hell for a week or so.  You can&amp;#8217;t predict when either.  I thought John Walker was &lt;a href="http://www.fourmilab.ch/hackdiet/www/subsubsection1_3_3_0_4_5.html#SECTION0330450000000000000"&gt;exaggerating&lt;/a&gt;&amp;#8230; but it&amp;#8217;s true:&lt;/span&gt;

&lt;blockquote&gt;
&lt;p&gt;As your body chemistry adjusts, other curious things may happen. One day, trapped in a tedious meeting, I began to emit an odor evocative of a roadkill skunk marinated in ratpiss. My esteemed colleagues were either too polite to remark upon this phenomenon, or (more likely) unsure of the culprit, so I managed to escape to the open air unfingered as the malodorous miscreant. This situation persisted for about two weeks, after which it disappeared for good as suddenly as its onset.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;

&lt;li&gt;&lt;span&gt;Optimizing for fullness per calorie has unexpected effects.  Pizza is actually low-calorie when you consider that two slices of pepperoni is only 600 calories and filling.  Fruit is also great: 100 calories for a pear.&lt;/span&gt;&lt;/li&gt;

&lt;li&gt;&lt;span&gt;Alcohol is &lt;em&gt;full&lt;/em&gt; of calories.  80 for a shot of whiskey.  :x  Turns out I&amp;#8217;d rather eat some bread than have a beer.&lt;/span&gt;&lt;/li&gt;

&lt;li&gt;&lt;span&gt;It&amp;#8217;s way too easy to blow your budget on soda and juice.  Switch to diet soda, iced tea, black coffee, and water.  Liquid calories aren&amp;#8217;t worth it.&lt;/span&gt;&lt;/li&gt;

&lt;li&gt;&lt;span&gt;Speaking of, caffeine is awesome.  Suppresses appetite and gives you energy.&lt;/span&gt;&lt;/li&gt;

&lt;li&gt;&lt;span&gt;Body weight is noisy.  On any given day, you may be 4 pounds heavier or lighter than the day before.  (You can try this at home: drink two bottles of water before weighing yourself.)  Some weeks, it will look like you&amp;#8217;ve made no progress.  It&amp;#8217;s infuriating, but hang in there.  In the end, your weight graph will be linear.&lt;/span&gt;&lt;/li&gt;

&lt;li&gt;&lt;span&gt;When it comes to nutrition, everyone&amp;#8217;s an expert.  &amp;#8220;Are you exercising?&amp;#8221;  No.  &amp;#8220;Are you eating healthy food?&amp;#8221;  Do pizza, burritos, and frozen White Castle count?  Dieting is hard enough by itself.  Actively avoid being &lt;em&gt;too&lt;/em&gt; ambitious.  It&amp;#8217;s much easier to cut calories if you can still eat things you love.  Worry about the low-order bits &lt;em&gt;after&lt;/em&gt; you hit your target weight.&lt;/span&gt;&lt;/li&gt;

&lt;li&gt;&lt;span&gt;I used to love the feeling of a full stomach.  Now it&amp;#8217;s unpleasant.  I&amp;#8217;ve finally defeated that post-great-depression &amp;#8220;EAT EVERYTHING ON YOUR PLATE OR YOU&amp;#8217;RE GROUNDED!&amp;#8221; instinct.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Getting Through Rough Days&lt;/h2&gt;

&lt;p&gt;Let&amp;#8217;s face it.  Some days you&amp;#8217;ll screw up and eat too much for breakfast or lunch.  At 11:00 p.m. you can&amp;#8217;t sleep because you&amp;#8217;re too hungry.  How do you take the edge off without blowing your calorie budget?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tomatoes.  35 calories PER!  If you like &amp;#8216;em, chow down.&lt;/li&gt;
&lt;li&gt;Cantaloupe.  35 calories per 1/8 melon.&lt;/li&gt;
&lt;li&gt;Hot chicken broth in a mug.  Warm, tasty, and 50 calories.&lt;/li&gt;
&lt;li&gt;Strawberries.  8 calories per delicious berry!&lt;/li&gt;
&lt;li&gt;Low-calorie yogurt.  60 calories.&lt;/li&gt;
&lt;li&gt;String cheese.  70 calories.&lt;/li&gt;
&lt;li&gt;Pickles.  ZERO.&lt;/li&gt;
&lt;li&gt;Water.  ZERO.  Somehow, drinking water can make you less hungry!&lt;/li&gt;
&lt;li&gt;Also, if you still want crackers or cookies, &lt;a href="http://www.google.com/search?q=100%20calorie%20packs"&gt;100 calorie packs&lt;/a&gt; are pretty common these days.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And finally, my secret weapon&amp;#8230;  Trader Joe&amp;#8217;s Whole Wheat Bread.  I can&amp;#8217;t remember its exact name, but it comes in half-rounds and has three ingredients: whole wheat, water, salt.  200 calories, 16g of protein and 16g of fiber per EXTREMELY FILLING slice.  You can eat this stuff until your jaw hurts.  It&amp;#8217;s epic.  However, keep in mind that 16g of fiber is a ton.  Stay near a bathroom.&lt;/p&gt;

&lt;a href="http://aegisknight.org/wp-uploads/whole-wheat-bread.jpg"&gt;&lt;img src="http://aegisknight.org/wp-uploads/whole-wheat-bread-300x225.jpg" alt="whole-wheat-bread" title="whole-wheat-bread" width="300" height="225" class="aligncenter size-medium wp-image-1446" /&gt;&lt;/a&gt;

&lt;h2&gt;What About Exercise?&lt;/h2&gt;

&lt;p&gt;Remember the basic equation:&lt;/p&gt;

&lt;pre&gt;
Calories stored = Calories eaten - Calories burned
&lt;/pre&gt;

&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; lose weight with exercise, but it&amp;#8217;s harder than you&amp;#8217;d think.  Exercising tends to make me hungry, causing me to eat more than I would normally.  Plus, it takes a lot of exercise to burn off a significant number of calories.  If you vigorously lifted weights for an hour, you&amp;#8217;d only burn ~400 calories, less than a single cheeseburger!  You&amp;#8217;d have to keep that up every single day without increasing your diet to lose a less than a pound per week.  I decided it&amp;#8217;s easier to simply eat less.&lt;/p&gt;

&lt;p&gt;Note that I&amp;#8217;m not saying that exercise is not valuable.  Exercise has great health, happiness, and life extension benefits.  I just don&amp;#8217;t think it&amp;#8217;s an efficient way for me to lose weight.&lt;/p&gt;

&lt;h2&gt;What Next?&lt;/h2&gt;

&lt;p&gt;What next?  I think I&amp;#8217;m going to try to drive my weight down a bit further and then replace the pounds of fat lost with muscle.  Or maybe I&amp;#8217;ll get myself to floss every day.  We&amp;#8217;ll see!&lt;/p&gt;

&lt;p&gt;I always thought weight loss was hard because I&amp;#8217;d witnessed people throw themselves at it hardcore and then fail just as hard.  In contrast, I chose an easy, long-term, data-driven plan and stuck with it.  Small changes over a long time make a big difference.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/chadaustin/~4/rAOwAXhrdaE" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://chadaustin.me/2009/06/how-i-lost-20-pounds-in-20-weeks/#comments" thr:count="23" />
		<link rel="replies" type="application/atom+xml" href="http://chadaustin.me/2009/06/how-i-lost-20-pounds-in-20-weeks/feed/atom/" thr:count="23" />
		<thr:total>23</thr:total>
	</entry>
		<entry>
		<author>
			<name>Chad Austin</name>
						<uri>http://aegisknight.org/</uri>
					</author>
		<title type="html"><![CDATA[Fast Builds: Incremental Linking and Embedded SxS Manifests]]></title>
		<link rel="alternate" type="text/html" href="http://chadaustin.me/2009/05/incremental-linking-and-embedded-manifests/" />
		<id>http://aegisknight.org/?p=1414</id>
		<updated>2009-06-01T03:48:36Z</updated>
		<published>2009-06-01T02:31:54Z</published>
		<category scheme="http://chadaustin.me" term="Uncategorized" /><category scheme="http://chadaustin.me" term="c++" /><category scheme="http://chadaustin.me" term="imvu" /><category scheme="http://chadaustin.me" term="scons" />		<summary type="html"><![CDATA[
As I&#8217;ve said before, fast builds are crucial for efficient development.  But for those of us who use C++ regularly, link times are killer.  It&#8217;s not uncommon to spend minutes linking your compiled objects into a single binary.  Incremental linking helps a great deal, but, as you&#8217;ll see, incremental linking has become [...]]]></summary>
		<content type="html" xml:base="http://chadaustin.me/2009/05/incremental-linking-and-embedded-manifests/">&lt;p&gt;
As I&amp;#8217;ve said before, fast builds are crucial for efficient development.  But for those of us who use C++ regularly, link times are killer.  It&amp;#8217;s not uncommon to spend minutes linking your compiled objects into a single binary.  Incremental linking helps a great deal, but, as you&amp;#8217;ll see, incremental linking has become a lot harder in the last few versions of Visual Studio&amp;#8230;
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Linker"&gt;Linking&lt;/a&gt; an EXE or DLL is a very expensive operation &amp;#8212; it&amp;#8217;s roughly O(N) where N is the amount of code being linked.  Worse, several optimizing linkers defer code generation to link time, exacerbating the problem!  When you&amp;#8217;re trying to practice TDD, even a couple seconds in your red-green-refactor iteration loop is brutal.  And it&amp;#8217;s not uncommon for large projects to spend minutes linking.&lt;/p&gt;

&lt;p&gt;Luckily, Visual C++ supports an &lt;a href="http://msdn.microsoft.com/en-us/library/4khtbfyf(VS.80).aspx"&gt;/INCREMENTAL&lt;/a&gt; flag, instructing relinks to modify the DLL or EXE in-place, reducing link time to O(changed code) rather than O(all code).  In the olden days of Visual C++ 6, all you had to do was enable /INCREMENTAL, and bam, fast builds.&lt;/p&gt;

&lt;p&gt;These days, it&amp;#8217;s not so simple.  Let&amp;#8217;s take an excursion into how modern Windows finds DLL dependencies&amp;#8230;&lt;/p&gt;

&lt;h2&gt;Side-by-Side (SxS) Manifests&lt;/h2&gt;

&lt;p&gt;Let&amp;#8217;s say you&amp;#8217;re writing a DLL &lt;code&gt;foo.dll&lt;/code&gt; that depends on the CRT by using, say, &lt;code&gt;printf&lt;/code&gt; or &lt;code&gt;std::string&lt;/code&gt;.  When you link &lt;code&gt;foo.dll&lt;/code&gt;, the linker will also produce &lt;code&gt;foo.dll.manifest&lt;/code&gt;.  Windows XP and Vista use .manifest files to load the correct CRT version.  (This prevents DLL hell: two programs can depend on different versions of the same DLL.)&lt;/p&gt;

&lt;p&gt;Since remembering to carry around .manifest files is annoying and error-prone, Microsoft and others recommend that you embed them into your EXE or DLL as a resource:&lt;/p&gt;

&lt;pre&gt;
mt.exe –manifest foo.dll.manifest -outputresource:foo.dll;2
&lt;/pre&gt;

&lt;p&gt;Convenient, but it modifies the DLL in place, breaking incremental links!  This is a &lt;a href="http://markmail.org/message/f4g2qi2kf5wu7n5t"&gt;known problem&lt;/a&gt;, and the &lt;a href="http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx"&gt;&amp;#8220;solutions&amp;#8221;&lt;/a&gt; others suggest are INSANE.  My favorite is the &lt;a href="http://blogs.msdn.com/nikolad/articles/425359.aspx"&gt;300-line makefile&lt;/a&gt; with a note from the author &amp;#8220;[If this does not work], please let me know ASAP. I will try fixing it for you.&amp;#8221;  Why doesn&amp;#8217;t Visual Studio just provide an /EMBEDMANIFESTRESOURCE flag that would automatically solve the problem?!&lt;/p&gt;

&lt;p&gt;I just want incremental linking and embedded manifests.  Is that so much to ask?  I tried a bunch of approaches.  Most didn&amp;#8217;t work.  I&amp;#8217;ll show them, and then give my current (working) approach.  If you don&amp;#8217;t care about the sordid journey, &lt;a href="#solution"&gt;skip to the end&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;What Didn&amp;#8217;t Work&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Not embedding manifests at all.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What went wrong: I could never figure out the rules where by manifest dependencies are discovered.  If python.exe depends on the release CRT and your module DLL depends on the debug CRT, and they live in different directories (??), loading the module DLL would fail.  Gave up.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Linking a temporary file (foo.pre.dll), making a copy (foo.pre.dll -&gt; foo.dll), and embedding foo.pre.dll.manifest into foo.dll with mt.exe.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What went wrong: As far as I can tell, mt.exe is a terrible piece of code.  In procmon I&amp;#8217;ve watched it close file handles it didn&amp;#8217;t open, causing permissions violations down the line.  (?!)  Sometimes it silently corrupts your EXEs and DLLs too.  This may be a known weakness in &lt;a href="http://msdn.microsoft.com/en-us/library/ms648049(VS.85).aspx"&gt;UpdateResource&lt;/a&gt;.  Yay!  (Thanks to &lt;a href="http://www.luminance.org/"&gt;Kevin Gadd&lt;/a&gt;; he was instrumental in diagnosing these bugs.)  mt.exe may or &lt;a href="http://www.wintellect.com/CS/blogs/jrobbins/archive/2009/01/24/the-case-of-the-corrupt-pe-binaries.aspx"&gt;may not&lt;/a&gt; be fixed in recent Visual Studios.  Either way, I&amp;#8217;m convinced mt.exe has caused us several intermittent build failures in the past.  Avoiding it is a good thing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Linking to a temporary file (foo.pre.dll), generating a resource script (foo.pre.rc) from (foo.pre.dll.manifest), compiling said resource script (foo.pre.res), and including the compiled resource into the final link (foo.dll).&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What went wrong: This approach is reliable but slow.  Linking each DLL and EXE twice, even if both links are incremental, is often slower than just doing a full link to begin with.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Linking foo.dll with foo.dll.manifest (via a resource script, as above) if it exists.  If foo.dll.manifest changed as a result of the link, relink.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I didn&amp;#8217;t actually try this one because non-DAG builds scare me.  I like the simplicity and reliability of the &amp;#8220;inputs -&gt; command -&gt; outputs&amp;#8221; build model.  It&amp;#8217;s weird if foo.dll.manifest is an input and an output of the link.  Yes, technically, that&amp;#8217;s how incremental linking works at all, but the non-DAG machinery is hidden in link.exe.  From SCons&amp;#8217;s perspective, it&amp;#8217;s still a DAG.&lt;/p&gt;

&lt;h2&gt;&lt;a id="solution"&gt;Finally, a working solution:&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;For every build configuration {debug,release} and dependency {CRT,MFC,&amp;#8230;}, link a tiny program to generate said dependency manifest.  Compile manifest into a resource script (.rc -&gt; .res) and link the compiled manifest resources into your other DLLs and EXEs.&lt;/p&gt;

&lt;p&gt;This approach has several advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;These pre-generated manifest resources are created once and reused in future builds, with no impact to build time.&lt;/li&gt;
&lt;li&gt;The build is a DAG.&lt;/li&gt;
&lt;li&gt;We avoid letting mt.exe wreak havoc on our build by sidestepping it entirely.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I can think of one disadvantage &amp;#8211; you need to know up-front on which SxS DLLs you depend.  For most programs, the CRT is the only one.  And hopefully understanding your dependencies isn&amp;#8217;t a bad thing, though.  ;)&lt;/p&gt;

&lt;p&gt;After several evenings of investigation, we&amp;#8217;re back to the same link times we had with Visual C++ 6!  Yay!&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;The Code&lt;/h2&gt;

&lt;p&gt;If you care, here&amp;#8217;s our SCons implementation of embedded manifests:&lt;/p&gt;

&lt;pre&gt;
# manifest_resource(env, is_dll) returns a manifest resource suitable for inclusion into
# the sources list of a Program or SharedLibrary.
manifest_resources = {}
def manifest_resource(env, is_dll):
    if is_dll:
        resource_type = 2 #define ISOLATIONAWARE_MANIFEST_RESOURCE_ID 2
    else:
        resource_type = 1 #define CREATEPROCESS_MANIFEST_RESOURCE_ID  1

    is_debug = env['DEBUG'] # could use a 'build_config' key if we had more than debug/release
    del env

    def build_manifest_resource():
        if is_debug:
            env = baseEnv.Clone(tools=[Debug])
        else:
            env = baseEnv.Clone(tools=[Release])
        env['LINKFLAGS'].remove('/MANIFEST:NO')

        if is_dll:
            linker = env.SharedLibrary
            target_name = 'crt_manifest.dll'
            source = env.File('#/MSVC/crt_manifest_dll.cpp')
        else:
            linker = env.Program
            target_name = 'crt_manifest.exe'
            source = env.File('#/MSVC/crt_manifest_exe.cpp')

        env['OUTPUT_PATH'] = '#/${BUILDDIR}/${IMVU_BUILDDIR_NAME}/%s' % (target_name,)

        obj = env.SharedObject('${OUTPUT_PATH}.obj', source)
        result = linker([env.File('${OUTPUT_PATH}'), '${OUTPUT_PATH}.manifest'], obj)
        manifest = result[1]

        def genrc(env, target, source):
            [target] = target
            [source] = source
            # 24 = RT_MANIFEST
            file(target.abspath, 'w').write('%d 24 "%s"' % (resource_type, source.abspath,))

        rc = env.Command('${OUTPUT_PATH}.rc', manifest, genrc)
        res = env.RES('${OUTPUT_PATH}.res', rc)
        env.Depends(res, manifest)
        return res
    
    key = (is_debug, resource_type)
    try:
        return manifest_resources[key]
    except KeyError:
        res = build_manifest_resource()

        manifest_resources[key] = res
        return res
&lt;/pre&gt;
&lt;img src="http://feeds.feedburner.com/~r/chadaustin/~4/IL_uX2ALxDo" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://chadaustin.me/2009/05/incremental-linking-and-embedded-manifests/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://chadaustin.me/2009/05/incremental-linking-and-embedded-manifests/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	</entry>
		<entry>
		<author>
			<name>Chad Austin</name>
						<uri>http://aegisknight.org/</uri>
					</author>
		<title type="html"><![CDATA[Fast Builds: Unintrusive Precompiled Headers (PCH)]]></title>
		<link rel="alternate" type="text/html" href="http://chadaustin.me/2009/05/unintrusive-precompiled-headers-pch/" />
		<id>http://aegisknight.org/?p=1399</id>
		<updated>2009-06-01T00:42:29Z</updated>
		<published>2009-05-20T20:24:59Z</published>
		<category scheme="http://chadaustin.me" term="Uncategorized" /><category scheme="http://chadaustin.me" term="c++" /><category scheme="http://chadaustin.me" term="imvu" /><category scheme="http://chadaustin.me" term="scons" />		<summary type="html"><![CDATA[
Fast builds are critical to the C++ programmer&#8217;s productivity and happiness.  One common technique for reducing build times is precompiled headers (PCH).  There&#8217;s plenty of literature out there; I won&#8217;t describe PCH in detail here.


But one thing that&#8217;s always bothered me about PCH is that it affects your code.  #pragma hdrstop and [...]]]></summary>
		<content type="html" xml:base="http://chadaustin.me/2009/05/unintrusive-precompiled-headers-pch/">&lt;p&gt;
&lt;a href="http://gamesfromwithin.com/?p=100"&gt;Fast builds&lt;/a&gt; are critical to the C++ programmer&amp;#8217;s productivity and happiness.  One common technique for reducing build times is precompiled headers (PCH).  There&amp;#8217;s &lt;a href="http://gamesfromwithin.com/?p=39"&gt;plenty of literature&lt;/a&gt; out there; I won&amp;#8217;t describe PCH in detail here.
&lt;/p&gt;

&lt;p&gt;But one thing that&amp;#8217;s always bothered me about PCH is that it affects your code.  &lt;code&gt;#pragma hdrstop&lt;/code&gt; and &lt;code&gt;#include "StdAfx.h"&lt;/code&gt; everywhere.  Gross.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m a strong believer in clean code without boilerplate, so can&amp;#8217;t we do better?  Ideally we could make a simple tweak to the build system and see build times magically improve.  &lt;a href="http://ennos.home.pages.de/"&gt;Enno&lt;/a&gt; enticed me with mentions of his fast builds, so I took a look&amp;#8230;&lt;/p&gt;

&lt;p&gt;Using PCH in Visual C++ requires a header (call it Precompiled.h) that includes all of the expensive dependencies:&lt;/p&gt;

&lt;pre&gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;map&amp;gt;
#include &amp;lt;iostream&amp;gt;
#include &amp;lt;fstream&amp;gt;
#include &amp;lt;boost/python.hpp&amp;gt;
#include &amp;lt;windows.h&amp;gt;
#include &amp;lt;mmsystem.h&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Additionally, we need a source file (let&amp;#8217;s get creative and call it Precompiled.cpp), which is empty except for &lt;code&gt;#include "Precompiled.h"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Compile Precompiled.cpp with &lt;code&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/7zc28563.aspx"&gt;/Yc&lt;/a&gt; Precompiled.h&lt;/code&gt; to generate Precompiled.pch, the actual precompiled header. Then, use the precompiled header on the rest of your files with &lt;code&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/z0atkd6c.aspx"&gt;/Yu&lt;/a&gt; Precompiled.h&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;OK, here&amp;#8217;s the step that prevented me from using PCH for so long: every single source file in your project must &lt;code&gt;#include "Precompiled.h"&lt;/code&gt; on its first line.&lt;/p&gt;

&lt;p&gt;That&amp;#8217;s ridiculous!  I don&amp;#8217;t want to touch every file!&lt;/p&gt;

&lt;p&gt;It turns out our savior is the &lt;a href="http://msdn.microsoft.com/en-us/library/8c5ztk84.aspx"&gt;/FI&lt;/a&gt; option.  From the documentation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This option has the same effect as specifying the file with double quotation marks in an #include directive on the first line of every source file specified on the command line [...]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Exactly what we want!&lt;/p&gt;

&lt;p&gt;But wait, doesn&amp;#8217;t that mean every .cpp in our project will have access to every symbol included by the PCH?  Yes.  :(  It&amp;#8217;s worth the build speedup.&lt;/p&gt;

&lt;p&gt;However, explicit physical dependencies are important, and the only way to prevent important things from breaking is by blocking commits if they fail.  Since enabling and disabling PCH does not require any code changes, it&amp;#8217;s easy enough to add a &amp;#8220;disable PCH&amp;#8221; option to your build system and run it on your continuous integration server:&lt;/p&gt;

&lt;a href="http://aegisknight.org/wp-uploads/compile_without_pch.png"&gt;&lt;img src="http://aegisknight.org/wp-uploads/compile_without_pch-138x300.png" alt="Compile without PCH" title="Compile without PCH" width="138" height="300" class="aligncenter size-medium wp-image-1404" /&gt;&lt;/a&gt;

&lt;p&gt;If somebody uses &lt;code&gt;std::string&lt;/code&gt; but forgets to &lt;code&gt;#include &amp;lt;string&amp;gt;&lt;/code&gt;, the build will fail and block commits.&lt;/p&gt;

&lt;p&gt;In the end, here&amp;#8217;s the bit of SCons magic that lets me quickly drop PCH into a project:&lt;/p&gt;

&lt;pre&gt;
def enable_pch(env, source_file, header):
    if PCH_ENABLED:
        PCH, PCH_OBJ = env.PCH(source_file)
        env['PCH'] = PCH
        env['PCHSTOP'] = header
        env.Append(CPPFLAGS=['/FI' + header])
        return [PCH_OBJ]
    else:
        return [source_file]
&lt;/pre&gt;

&lt;p&gt;Now you can benefit from fast builds with minimal effort and no change to your existing code!&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/chadaustin/~4/AeZzZDdO2Pc" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://chadaustin.me/2009/05/unintrusive-precompiled-headers-pch/#comments" thr:count="5" />
		<link rel="replies" type="application/atom+xml" href="http://chadaustin.me/2009/05/unintrusive-precompiled-headers-pch/feed/atom/" thr:count="5" />
		<thr:total>5</thr:total>
	</entry>
	</feed><!-- Dynamic page generated in 0.376 seconds. --><!-- Cached page generated by WP-Super-Cache on 2010-03-10 07:12:03 -->
