<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Rusty Russell&#039;s Coding Blog</title>
	<atom:link href="http://rusty.ozlabs.org/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://rusty.ozlabs.org</link>
	<description>Stealing From Smart People</description>
	<lastBuildDate>Mon, 01 Apr 2013 02:36:49 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.2</generator>
		<item>
		<title>Thanks for the Bitcoin donation!</title>
		<link>http://rusty.ozlabs.org/?p=337</link>
		<comments>http://rusty.ozlabs.org/?p=337#comments</comments>
		<pubDate>Mon, 01 Apr 2013 02:36:49 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=337</guid>
		<description><![CDATA[Last week I used 2 BTC to support Jupiter Broadcasting&#8217;s Unfilter show (and their other shows, but only Unfilter takes BTC so far).  Just now I noticed that someone made a 0.5BTC donation to my blog (I&#8217;ve had a BTC donation address in the sidebar of my blog for a few years now).  Thanks! As [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I used 2 BTC to support Jupiter Broadcasting&#8217;s Unfilter show (and their other shows, but only Unfilter takes BTC so far).  Just now I noticed that someone made a 0.5BTC donation to my blog (I&#8217;ve had a BTC donation address in the sidebar of my blog for a few years now).  Thanks!</p>
<p>As I promised to pass donations onwards, I googled for bitcoin donations, and chose the following places to give 0.05 BTC each:</p>
<ol>
<li><a title="Juice Rap News donation page" href="http://thejuicemedia.com/donate/">Juice Rap News</a> for making high-baud political commentary (<a title="Unfilter" href="http://www.jupiterbroadcasting.com/show/unfilter/">Unfilter</a> in rap form)</li>
<li><a title="Freedom Box foundation donation" href="http://freedomboxfoundation.org/donate/">Freedom Box</a> for actually doing something about Internet freedom.</li>
<li><a title="Torservers.net donation page" href="https://www.torservers.net/donate.html">Torservers.net</a> (as recommended by torproject.org) for the same.</li>
<li><a title="Fdroid homepage" href="http://f-droid.org/">f-droid.org</a> for keeping a healthy Open alternative.</li>
<li><a title="Bitcoin Foundation donation page" href="https://bitcoinfoundation.org/donate">Bitcoin Foundation</a> to support and strengthen the infrastructure that made this possible.</li>
<li><a title="FSF's donation page" href="http://www.fsf.org/donate/">The Free Software Foundation</a> even though I don&#8217;t always agree with them.</li>
<li><a title="Wikileaks' donation page" href="http://shop.wikileaks.org/donate#dbitcoin">Wikileaks</a> for recognizing something society needs, even if they stumble at delivery.</li>
<li><a title="Internet Archive fundraising in bitcoins" href="http://blog.archive.org/2013/02/21/employees-to-be-paid-in-bitcoin-please-donate/">The Internet Archive</a> for something that only gets more useful over time.</li>
</ol>
<p>There are two left to go, so I&#8217;ll keep an eye out for more opportunities to donate in the next few weeks&#8230;</p>
<p>-0.05</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=337</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>GCC and C vs C++ Speed, Measured.</title>
		<link>http://rusty.ozlabs.org/?p=330</link>
		<comments>http://rusty.ozlabs.org/?p=330#comments</comments>
		<pubDate>Wed, 20 Mar 2013 22:52:38 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=330</guid>
		<description><![CDATA[With the imminent release of gcc 4.8, GCC has finally switched to C++ as the implementation language.  As usual, LWN has excellent coverage.  Those with long memories will remember Linux trying to use g++ back in 1992 and retreating in horror at the larger, slower code.  The main benefit was stricter typechecking, particularly for enums (a [...]]]></description>
			<content:encoded><![CDATA[<p>With the imminent release of <a title="GCC 4.8 Changes" href="http://gcc.gnu.org/gcc-4.8/changes.html">gcc 4.8</a>, GCC has finally switched to C++ as the implementation language.  As usual, <a title="GCC's move to C++" href="https://lwn.net/Articles/542457/">LWN has excellent coverage</a>.  Those with long memories will remember Linux trying to use g++ back in 1992 and retreating in horror at the larger, slower code.  The main benefit was stricter typechecking, particularly for enums (a great idea: I had -Wstrict-enum patches for gcc about 12 years ago, which was a superset of the -Wenum-compare we have now, but never got it merged).</p>
<p>With this in mind, and Ian Taylor&#8217;s bold assertion that &#8220;The C subset of C++ is as efficient as C&#8221;, I wanted to test what had changed with some actual measurements.  So I grabbed gcc 4.7.2 (the last release which could do this), and built it with C and C++ compilers:</p>
<ol>
<li>../gcc-4.7.2/configure &#8211;prefix=/usr/local/gcc-c &#8211;disable-bootstrap &#8211;enable-languages=c,c++ &#8211;disable-multiarch &#8211;disable-multilib</li>
<li>../gcc-4.7.2/configure &#8211;prefix=/usr/local/gcc-cxx &#8211;disable-bootstrap &#8211;enable-languages=c,c++ &#8211;disable-multiarch &#8211;disable-multilib &#8211;enable-build-with-cxx</li>
</ol>
<p>The C++-compiled binaries are slightly larger, though that&#8217;s mostly debug info:</p>
<ol>
<li>-rwxr-xr-x 3 rusty rusty 1886551 Mar 18 17:13 /usr/local/gcc-c/bin/gcc<br />
text       data        bss        dec        hex    filename<br />
552530       3752       6888     563170      897e2    /usr/local/gcc-c/bin/gcc</li>
<li>-rwxr-xr-x 3 rusty rusty 1956593 Mar 18 17:13 /usr/local/gcc-cxx/bin/gcc<br />
text       data        bss        dec        hex    filename<br />
552731       3760       7176     563667      899d3    /usr/local/gcc-cxx/bin/gcc</li>
</ol>
<p>Then I used them both to compile a clean Linux kernel 10 times:</p>
<ol>
<li>for i in `seq 10`; do time make -s CC=/usr/local/gcc-c/bin/gcc 2&gt;/dev/null; make -s clean; done</li>
<li>for i in `seq 10`; do time make -s CC=/usr/local/gcc-cxx/bin/gcc 2&gt;/dev/null; make -s clean; done</li>
</ol>
<p>Using <a title="stats - simple filter to gather numbers in repeated text." href="https://github.com/rustyrussell/stats">stats &#8211;trim-outliers</a>, which throws away best and worse, and we have the times for the remaining 8:</p>
<ol>
<li>real    14m24.359000-35.107000(25.1521+/-0.62)s<br />
user    12m50.468000-52.576000(50.912+/-0.23)s<br />
sys    1m24.921000-27.465000(25.795+/-0.31)s</li>
<li>real    14m27.148000-29.635000(27.8895+/-0.78)s<br />
user    12m50.428000-52.852000(51.956+/-0.7)s<br />
sys    1m26.597000-29.274000(27.863+/-0.66)s</li>
</ol>
<p>So the C++-compiled binaries are measurably slower, though not noticably: it&#8217;s about 865 seconds vs 868 seconds, or about .3%.  Even if a kernel compile spends half its time linking, statting, etc, that&#8217;s under 1% slowdown.</p>
<p>And it&#8217;s perfectly explicable by the larger executable size.  If we strip all the gcc binaries, and do another 10 runs of each (&#8230; flash forward to the next day.. oops, powerfail, make that 2 days later):</p>
<ol>
<li>real    14m24.659000-33.435000(26.1196+/-0.65)s<br />
user    12m50.032000-57.701000(50.9755+/-0.36)s<br />
sys    1m26.057000-28.406000(26.863+/-0.36)s</li>
<li>real    14m26.811000-29.284000(27.1308+/-0.17)s<br />
user    12m51.428000-52.696000(52.156+/-0.39)s<br />
sys    1m26.157000-27.973000(26.869+/-0.41)s</li>
</ol>
<p>Now the difference is 0.1%, pretty much in the noise.</p>
<p>Summary: so whether you like C++ or not, the performance argument is moot.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=330</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Looking forward to linux.conf.au 2013</title>
		<link>http://rusty.ozlabs.org/?p=326</link>
		<comments>http://rusty.ozlabs.org/?p=326#comments</comments>
		<pubDate>Wed, 16 Jan 2013 01:36:21 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=326</guid>
		<description><![CDATA[This year&#8217;s organizers took specific pains to attract deep content, and the schedule reflects that: there are very few slots where I&#8217;m not torn between two topics.  This will be great fun! After a little introspection, I did not submit a talk this year.  My work in 2012 was with Linaro helping with KVM on [...]]]></description>
			<content:encoded><![CDATA[<p>This year&#8217;s organizers took specific pains to attract deep content, and <a href="http://lca2013.linux.org.au/programme/schedule">the schedule</a> reflects that: there are very few slots where I&#8217;m not torn between two topics.  This will be great fun!</p>
<p>After a little introspection, I did not submit a talk this year.  My work in 2012 was with Linaro helping with KVM on ARM: that topic is better addressed by Christoffer Dall, so I convinced him to submit (unfortunately, he withdrew as January became an untenable time for him to travel).  My other coding work was incremental, not revolutionary: module signatures, CCAN nor ntdb shook the ground this year.  There just wasn&#8217;t anything I was excited about: a reliable litmus test.</p>
<p>See you at LCA!</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=326</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fixed-length semi-lockless queues revisited</title>
		<link>http://rusty.ozlabs.org/?p=317</link>
		<comments>http://rusty.ozlabs.org/?p=317#comments</comments>
		<pubDate>Mon, 24 Dec 2012 04:33:49 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=317</guid>
		<description><![CDATA[There were some great comments on my previous post, both in comments here and on the Google Plus post which points to it.  I&#8217;d like to address the point here, now I&#8217;ve had a few moments to do follow-up work. One anonymous commenter, as well as Stephen Hemminger via email, point to the existing lockless [...]]]></description>
			<content:encoded><![CDATA[<p>There were some great comments on my <a title="Fixed-length semi-lockless queues..." href="http://rusty.ozlabs.org/?p=302">previous post</a>, both in comments here and on the <a title="Google Plus post on lockless queues..." href="https://plus.google.com/103188246877163594460/posts">Google Plus</a> post which points to it.  I&#8217;d like to address the point here, now I&#8217;ve had a few moments to do follow-up work.</p>
<p>One anonymous commenter, as well as Stephen Hemminger via email, point to the existing lockless queue code in <a href="git://git.lttng.org/userspace-rcu.git">liburcu</a>.  I had actually waded through this before (I say waded, because it&#8217;s wrapped in a few layers which I find annoying; there&#8217;s a reason I write little CCAN modules).  It&#8217;s clever and genuinely lockless; my hat off to , but it only works in conjunction with RCU.  In particular, it&#8217;s an unlimited-length queue which uses a dummy element to avoid ever being empty, and the fact that it can safely traverse the &#8216;-&gt;next&#8217; entry even as an element is being dequeued, because the rules say you can&#8217;t alter that field or free the object until later.</p>
<p><a href="http://rusty.ozlabs.org/wp-uploads/2012/12/bsd-style.png"><img class="alignright  wp-image-318" title="Repeated benchmarks with my implementation vs hacked FreeBSD" src="http://rusty.ozlabs.org/wp-uploads/2012/12/bsd-style-300x167.png" alt="" width="150" height="84" /></a>Stephen also pointed me to Kip Macy&#8217;s <a href="http://code.metager.de/source/xref/freebsd/sys/sys/buf_ring.h">buf_ring</a> from FreeBSD; it uses two producer counters, prod_head and prod_tail.  The consumer looks at prod_tail as usual, the producers compare and swap increment prod_head, then place their element, then wait for prod_tail to catch up with prod_head before incrementing prod_tail.  Reimplementing this in my code showed it to be slower than the lower-bit-to-lock case for my benchmarks, though not much (the main difference is in the single-producer-using-muliple-producer-safe-routines, which are the first three benchmarks).  I ignored the buf_ring consumer, which uses a similar two-counter scheme for consumers, which is only useful for debugging, and used the same consumer code as before.</p>
<p><a title="Arjen's homepage" href="http://www.fenrus.org/">Arjen van de Ven</a> makes several excellent points.  Firstly, that transaction-style features may allow efficient lock-ellision in upcoming Intel CPUs (and, of course, PowerPC has announced transaction support for Power8), so we&#8217;ll have to revisit in a few years when that reaches me.</p>
<p>His more immediate point is thatuncontended locks are really cheap on recent CPUs; cheaper than cache-hot compare-and-swap operations.  All the benchmarks I did involve everyone banging on the queue all the time, so I&#8217;m only measuring the contended cases.  So I hacked my benchmarks to allow for &#8220;0 consumers&#8221; by having the producer discard all the queue contents every time it filled.  Similarly, filling the queue with junk when it&#8217;s empty for a &#8220;0 producers&#8221; benchmark.</p>
<p><a href="http://rusty.ozlabs.org/wp-uploads/2012/12/uncontended.png"><img class="alignright  wp-image-319" title="uncontended" src="http://rusty.ozlabs.org/wp-uploads/2012/12/uncontended-300x158.png" alt="" width="150" height="79" /></a>Here we can see that the dumb, single lock comes into its own, being twice as fast as my optimal-when-contended version.  If we just consider the common case of a single writer and a single reader, the lockless implementation takes 24ns in the contended case, and 14ns in the uncontended cases, whereas the naive locked implementation takes 107ns in the contended case and 7ns in the uncontended case.  In other words, you&#8217;d have to be uncontended over 90% of the time to win.  That can&#8217;t happen in a naive implementation which wakes the consumer as soon as the first item has been inserted into the queue (and if you implement a batch version of queue_insert, the atomic exchange gets amortized, so it gets harder to beat).</p>
<p>For the moment, I&#8217;m sticking with the previous winner; there&#8217;s still much to do to turn it into a usable API.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=317</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fixed-length semi-lockless queues&#8230;</title>
		<link>http://rusty.ozlabs.org/?p=302</link>
		<comments>http://rusty.ozlabs.org/?p=302#comments</comments>
		<pubDate>Mon, 17 Dec 2012 03:38:59 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=302</guid>
		<description><![CDATA[One of my vacation project was to look at a good queue implementation for ccan/antithread.  I read a few papers, which mainly deal with generic link-list-style queues (I got quite excited about one before I realized that it needed a 128-bit compare-and-swap for 64 bit machines).  I only really need a fixed-length queue of void [...]]]></description>
			<content:encoded><![CDATA[<p>One of my vacation project was to look at a good queue implementation for ccan/antithread.  I read a few papers, which mainly deal with generic link-list-style queues (I got quite excited about one before I realized that it needed a 128-bit compare-and-swap for 64 bit machines).  I only really need a fixed-length queue of void *, so I set about implementing one.</p>
<p>You can find the cleaned-up version of my explorations <a title="Github CCAN antithread branch" href="http://github.com/rustyrussell/ccan/tree/antithread">on github</a>.  For my implementation I use a tail counter, 32 void * entries, and a head counter, like so:</p>
<pre>#define QUEUE_ELEMS 32
struct queue {
    unsigned int head;
    unsigned int prod_waiting;
    unsigned int lock;
    void *elems[QUEUE_ELEMS];
    unsigned int tail;
    unsigned int cons_waiting;
};</pre>
<p>The head and tail counters are free running to avoid the empty-or-full problem, and the prod_waiting and cons_waiting are for a future implementation which actually does sleep and wakeup (I spin for my current tests).</p>
<p><a href="http://rusty.ozlabs.org/wp-uploads/2012/12/single-big-lock1.png"><img class="alignright size-medium wp-image-311" title="Single big lock" src="http://rusty.ozlabs.org/wp-uploads/2012/12/single-big-lock1-300x162.png" alt="" width="300" height="162" /></a>The simplest implementation is for both producers and consumers to grab the lock, do their work, then drop the lock.  On my 32-bit x86 dual core 2 HT laptop, with 1 producer on cpu0 and 1 producer on cpu1 (ie. two hyperthreads of same core), it takes about 179 usec to enqueue and dequeue each element (but hugely variable, from 73 to 439 ns).  You can see that (as expected) the 2 and 3 producers cases are quite expensive, though not so bad if there are 2 producers and 2 consumers.</p>
<p>Lockless dequeue is quite easy:</p>
<ol>
<li>Read tail counter, then read head counter (order matters!)</li>
<li>If it&#8217;s empty, wait until head changes).</li>
<li>Grab entry[tail % 32].</li>
<li>Try to compare and swap the tail to tail+1.  If not, we raced, so goto 1.</li>
</ol>
<p><a href="http://rusty.ozlabs.org/wp-uploads/2012/12/lockless-dequeue1.png"><img class="alignleft size-medium wp-image-310" title="lockless-dequeue" src="http://rusty.ozlabs.org/wp-uploads/2012/12/lockless-dequeue1-300x157.png" alt="" width="300" height="157" /></a>But lockless insert is harder, so I asked Paul McKenney who detailed a fairly complex scheme involving two offsets and some subtlety on both production and consumption side, and ended with &#8220;Now, are you -sure- locking is all that bad?  ;-)&#8221;.  So I went for a big lock around insertion to begin with.  It&#8217;s generally a little better, particularly for the common case of a single consumer and a single producer.</p>
<p><a href="http://rusty.ozlabs.org/wp-uploads/2012/12/lockless-dequeue-with-excl-produce1.png"><img class="alignright size-medium wp-image-309" title="lockless-dequeue-with-excl-produce" src="http://rusty.ozlabs.org/wp-uploads/2012/12/lockless-dequeue-with-excl-produce1-300x154.png" alt="" width="300" height="154" /></a>It&#8217;s worth noting that if you know you&#8217;re the only producer, you can skip the locks so I re-ran the benchmarks with a &#8220;queue_add_excl&#8221; implementation for the single-producer cases, as seen on the right.</p>
<p>You can similarly simplify the single consumer case, though it makes little difference in my tests.</p>
<p>However, you can do better than a straight naive lock: you can use the lower bit of the head counter to exclude other producers.  This means a production algorithm like so:</p>
<ol>
<li>Read head.  If it&#8217;s odd, wait.</li>
<li>Read tail.</li>
<li>If queue is full, wait for tail to change, then goto 1.</li>
<li>Compare and swap head to head + 1; if it fails, go to 1.</li>
<li>Store the element.</li>
<li>Then increment the head.</li>
</ol>
<p><a href="http://rusty.ozlabs.org/wp-uploads/2012/12/lockless-dequeue-with-odd-producer-lock1.png"><img class="alignleft size-medium wp-image-308" title="lockless-dequeue-with-odd-producer-lock" src="http://rusty.ozlabs.org/wp-uploads/2012/12/lockless-dequeue-with-odd-producer-lock1-300x154.png" alt="" width="300" height="154" /></a>For simplicity, I made the tail counter increment by 2 as well, and the consumer simply ignores the bottom bit of the head counter.  Avoiding a separate atomic operation on a &#8220;prod_lock&#8221; word seems to pay off quite well.</p>
<p><a href="http://rusty.ozlabs.org/wp-uploads/2012/12/lockless-dequeue-with-odd-producer-lock-excl-consume.png"><img class="alignright size-thumbnail wp-image-307" title="lockless-dequeue-with-odd-producer-lock-excl-consume" src="http://rusty.ozlabs.org/wp-uploads/2012/12/lockless-dequeue-with-odd-producer-lock-excl-consume-150x150.png" alt="" width="150" height="150" /></a>Finally, it&#8217;s worth noting that neither the exclusive producer nor exclusive consumer cases win much any more, so I can delete those altogether.</p>
<p>Before tying this into antithread, there are several things to do:</p>
<ol>
<li>Re-audit to make sure the barriers are correct.</li>
<li>Test on PowerPC (always good for finding missing barriers).</li>
<li>Add in a decent notification mechanism, ie. futexes or falling back to pipes.</li>
</ol>
<p>And that&#8217;s next&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=302</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Kernel Compilation Times</title>
		<link>http://rusty.ozlabs.org/?p=291</link>
		<comments>http://rusty.ozlabs.org/?p=291#comments</comments>
		<pubDate>Tue, 16 Oct 2012 01:56:55 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=291</guid>
		<description><![CDATA[David S. Miller complains that CONFIG_MODULE_SIG slows down builds, and he does hundreds of allmodconfig builds every day. This complaint falls apart fairly quickly in the comments; he knows he can simply turn it off, but what about others who he simply tells to test with allmodconfig?  One presumes they are not doing hundreds of [...]]]></description>
			<content:encoded><![CDATA[<p>David S. Miller <a title="David S Miller: RSA Signed Modules" href="https://plus.google.com/101384639386588513837">complains</a> that CONFIG_MODULE_SIG slows down builds, and he does hundreds of allmodconfig builds every day.</p>
<p>This complaint falls apart fairly quickly in the comments; he knows he can simply turn it off, but what about others who he simply tells to test with allmodconfig?  One presumes they are not doing hundreds of kernel builds a day.</p>
<p>linux-next had the same issue, and a similar complaint; I had less sympathy when I suggested they might want to also turn off CONFIG_DEBUG_INFO if they were worried about compile speed, and indeed, found out Stephen already did.  Now they turn off CONFIG_MODULE_SIG, too.</p>
<p>Here are some compile times on my i386 laptop, using v3.7-rc1-1-g854e98a as I turn options off:</p>
<ul>
<li>allmodconfig: 52 minutes</li>
<li>&#8230; without CONFIG_MODULE_SIG: 45 minutes</li>
<li>&#8230; without CONFIG_DEBUG_INFO: 40 minutes</li>
<li>&#8230; without CONFIG_MODVERSIONS and CONFIG_MODULE_SRCVERSION_ALL: 38 minutes</li>
<li>&#8230; without CONFIG_KALLSYMS: 37 minutes</li>
<li>&#8230; using -O1 instead of -Os: 24 minutes (not a good idea, since we lose CONFIG_DEBUG_STRICT_USER_COPY_CHECKS).</li>
</ul>
<p>In summary, the real problem is that people don&#8217;t really want &#8216;allmodconfig&#8217;.  They want something which would compile a kernel with as much coverage as possible with no intention of actually booting it; say &#8216;allfastconfig&#8217;?</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=291</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Latinoware 2012</title>
		<link>http://rusty.ozlabs.org/?p=288</link>
		<comments>http://rusty.ozlabs.org/?p=288#comments</comments>
		<pubDate>Sat, 06 Oct 2012 04:39:18 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=288</guid>
		<description><![CDATA[I&#8217;m keynoting at http://latinoware.org in Brazil in two weeks (assuming I get my visa in time! ).  Looking forward to my first trip to South America as well as delivering a remix of some of my favourite general hacking talks. And of course, catching up with maddog!]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m keynoting at <a href="http://latinoware.org">http://latinoware.org</a> in Brazil in two weeks (assuming I get my visa in time! ).  Looking forward to my first trip to South America as well as delivering a remix of some of my favourite general hacking talks. And of course, catching up with maddog!</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=288</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What Can I Do To Help?</title>
		<link>http://rusty.ozlabs.org/?p=282</link>
		<comments>http://rusty.ozlabs.org/?p=282#comments</comments>
		<pubDate>Wed, 03 Oct 2012 05:16:11 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=282</guid>
		<description><![CDATA[Enthusiasm is a shockingly rare resource, anywhere. The reason enthusiasm is a rare resource is because it&#8217;s fragile; I&#8217;ve seen potentially-great ideas abandoned because the initial response was a liturgy of reasons why it won&#8217;t work.  It&#8217;s not the criticism which kills, it&#8217;s the scorn. So when someone emails or approaches you with something they&#8217;re [...]]]></description>
			<content:encoded><![CDATA[<p>Enthusiasm is a shockingly rare resource, anywhere. The reason enthusiasm is a rare resource is because it&#8217;s fragile; I&#8217;ve seen potentially-great ideas abandoned because the initial response was a liturgy of reasons why it won&#8217;t work.  It&#8217;s not the criticism which kills, it&#8217;s the scorn.</p>
<p>So when someone emails or approaches you with something they&#8217;re excited about, please reply thinking &#8220;What can I do to help?&#8221;  Often I just provide an encouraging and thoughtful response: a perfectly acceptable minimum commitment.  If you offer pointers or advice, take extra care to fan that delicate flutter of enthusiasm without extinguishing it. Other forces will usually take care of that soon enough, but let it not be you.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=282</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>FAQ: CCAN as a shared library?</title>
		<link>http://rusty.ozlabs.org/?p=278</link>
		<comments>http://rusty.ozlabs.org/?p=278#comments</comments>
		<pubDate>Fri, 15 Jun 2012 04:48:20 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=278</guid>
		<description><![CDATA[This was asked of me again, by Adam Conrad of Canonical: &#8220;Why isn&#8217;t CCAN a shared library?&#8221;.  Distributions prefer shared libraries, for simplicity of updating (especially for security fixes), so I thought I&#8217;d answer canonically, once. Most CCAN modules are small; many are just headers. You can&#8217;t librify something which doesn&#8217;t have a stable API [...]]]></description>
			<content:encoded><![CDATA[<p>This was asked of me again, by Adam Conrad of Canonical: &#8220;Why isn&#8217;t <a title="The CCAN Webpage" href="http://ccodearchive.net">CCAN</a> a shared library?&#8221;.  Distributions prefer shared libraries, for simplicity of updating (especially for security fixes), so I thought I&#8217;d answer canonically, once.</p>
<ul>
<li>Most CCAN modules are small; many are just headers.</li>
<li>You can&#8217;t librify something which doesn&#8217;t have a stable API or ABI.</li>
<li>CCAN&#8217;s alternative is not a library, it&#8217;s cut-n-paste.</li>
</ul>
<p>To illustrate what I mean, consider ccan/hash: it&#8217;s a convenient wrapper around the Jenkins lookup3 code.  It could be a library, but in practice it&#8217;s not.  For something as simple as that, people cut &amp; paste the lookup3 code into their own.  It already exists in two places in Samba, for example.  It&#8217;s this level of code snippet which is served beautifully by CCAN: you drop it in a ccan/ dir in your project and you get nice, documented and tested code, with optional updates if you want them later.</p>
<p>You could still make ccan/hash into a shared library.  But if the upstream doesn&#8217;t do it for you, you have to check the ABI and update the version number every time it changes.  This, unfortunately, means you can no longer share it: if library A uses version 11 and library B uses version 12, you can&#8217;t link against both library A and library B.  Yet there&#8217;s nothing wrong with either: you have to change them because you librified it.</p>
<p>This kind of pain isn&#8217;t worth it for small snippets of code, so people cut &amp; paste instead, and that makes our code worse, not better.  That&#8217;s what CCAN tries to fix.</p>
<p>Now, there may one day be modules which could be shared libraries: that&#8217;s a good thing, if the maintainer is prepared to support the ABI and API.  I&#8217;m not going to kick a module out of CCAN for being too successful.  But I&#8217;d like to explicitly label such a module, and make sure ccanlint does the appropriate checks for ABI compatibility and symbol hiding.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=278</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>1 Week to Go, and Rusty Goes Offline</title>
		<link>http://rusty.ozlabs.org/?p=273</link>
		<comments>http://rusty.ozlabs.org/?p=273#comments</comments>
		<pubDate>Thu, 29 Mar 2012 06:03:26 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=273</guid>
		<description><![CDATA[Just as the Linux kernel merge window closes, I&#8217;m going offline.  My wedding is exactly a week away, but I&#8217;ll be entertaining guests and doing final preparation.  I&#8217;ll be back from our honeymoon and wading through mail on the 7 May. Alex&#8217;s &#8220;A Bald Target&#8221; campaign to raise awareness for TimeForKids has been a huge [...]]]></description>
			<content:encoded><![CDATA[<p>Just as the Linux kernel merge window closes, I&#8217;m going offline.  My wedding is exactly a week away, but I&#8217;ll be entertaining guests and doing final preparation.  I&#8217;ll be back from our honeymoon and wading through mail on the 7 May.</p>
<p>Alex&#8217;s &#8220;<a title="Alex: A Bald Target" href="http://baldalex.org">A Bald Target</a>&#8221; campaign to raise awareness for TimeForKids has been a huge success, even though we&#8217;re currently far short of the hair-shaving goal.  She&#8217;s been on one of the local radio stations, with newspaper coverage expected this weekend; two local TV stations want to cover the actual shave if it happens.  The charity is delighted with the amount of publicity they have received; given that they need local people to volunteer to mentor the disadvantaged children, that&#8217;s worth at least as much as the money.</p>
<p>Special thanks to a <a title="LWN comment on donating without hair removal" href="https://lwn.net/Articles/486104/">couple</a> of <a title="Sam Watkins" href="http://sam.nipl.net/">people </a>who donated direct to the charity, to avoid causing baldness!  And yes, if we were starting again, having competing &#8220;shave&#8221; vs &#8220;save&#8221; campaigns would have been awesome&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=273</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Sources of Randomness for Userspace</title>
		<link>http://rusty.ozlabs.org/?p=265</link>
		<comments>http://rusty.ozlabs.org/?p=265#comments</comments>
		<pubDate>Thu, 29 Mar 2012 05:52:43 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=265</guid>
		<description><![CDATA[I&#8217;ve been thinking about a new CCAN module for getting a random seed.  Clearly, /dev/urandom is your friend here: on Ubuntu and other distributions it&#8217;s saved and restored across reboots, but traditionally server systems have lacked sources of entropy, so it&#8217;s worth thinking about other sources of randomness.  Assume for a moment that we mix [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been thinking about a new CCAN module for getting a random seed.  Clearly, /dev/urandom is your friend here: on Ubuntu and other distributions it&#8217;s saved and restored across reboots, but traditionally server systems have lacked sources of entropy, so it&#8217;s worth thinking about other sources of randomness.  Assume for a moment that we mix them well, so any non-randomness is irrelevant.</p>
<p>There are three obvious classes of randomness: things about the particular machine we&#8217;re on, things about the particular boot of the machine we&#8217;re on, and things which will vary every time we ask.</p>
<h3>The Machine We&#8217;re On</h3>
<p>Of course, much of this is guessable if someone has physical access to the box or knows something about the vendor or the owner, but it might be worth seeding this into /dev/urandom at install time.</p>
<p>On Linux, we can look in /proc/cpuinfo for some sources of machine info: for the 13 x86 machines my friends on IRC had in easy reach, we get three distinct values for cpu cores, three for siblings, two for cpu family, eight for model, six for cache size, and twelve for cpu MHz.  These values are obviously somewhat correlated, but it&#8217;s a fair guess that we can get 8 bits here.</p>
<p>Ethernet addresses are unique, so I think it&#8217;s fair to say there&#8217;s at least another 8 bits of entropy there, though often devices have consecutive numbers if they&#8217;re from the same vendor, so this doesn&#8217;t just multiply by number of NICs.</p>
<p>The amount of RAM in the machine is worth another two bits, and the other kinds of devices eg. trolling /sys/devices, which can be expected to give another few bits, even in machines which have fairly standard hardware settings like laptops.  Alternately, we could get this information indirectly by looking at /proc/modules.</p>
<p>Installed software gives a maximum three bits, since we can assume a recent version of a mainstream distribution.  Package listings can also be fairly standard, but most people install some extra things so we might assume a few more bits here.  Ubuntu systems ask for your name to base the system name on, so there might be a few bits there (though my laptop is predictably &#8220;rusty-x201&#8243;).</p>
<p>So, let&#8217;s have a guess at 8 + 7 + 2 + 3 + 3 + 2 + 2, ie. 27 bits from the machine configuration itself.</p>
<h3>Information About This Boot</h3>
<p>I created an upstart script to reboot (and had to hack grub.conf so it wouldn&#8217;t set the timeout to -1 for next boot), and let it loop for a day: just under <a title="Spreadsheet of some statistics from every boot" href="http://ozlabs.org/~rusty/boot-stats.gnumeric">2000 times in all</a>. I eyeballed the graphs of each stat I gathered against each other, and there didn&#8217;t seem to be any surprising correlations.   /proc/uptime gives a fairly uniform range of uptime values within a range of 1 second, at least 6 bits there (every few dozen boots we get an fsck, which gives a different range of values, but the same amount of noise).  /proc/loadavg is pretty constant, unfortunately.  bogomips on CPU1 was fairly constant, but for the boot CPU it looks like a standard distribution within 1 bogomip, in increments of 0.01: say another 7 bits there.</p>
<p>So for each boot we can extract 13 bits from uptime and /proc/cpuinfo.</p>
<h3>Things Which Change Every Time We Run</h3>
<p>The pid of our process will change every time we&#8217;re run, even when started at boot.  My pid was fairly evenly divided on every value between 1220 and 1260, so there&#8217;s five bits there.  Unfortunately on both 64 and 32-bit Ubuntu, pids are restricted to 32768 by default.</p>
<p>We can get several more bits from simply timing the other randomness operations.  Modern machines have so much going on that you can probably count on four or five bits of unpredictability over the time you gather these stats.</p>
<p>So another 9 bits every time our process runs, even if it&#8217;s run from a boot script or cron.</p>
<h3>Conclusion</h3>
<p>We can get about 50 bits of randomness without really trying too hard, which is fine for a random server on the internet facing a remote attacker without any inside knowledge, but only about five of these bits (from the process&#8217; own timing) would be unknown to an attacker who has access to the box itself.  So /dev/urandom is still very useful.</p>
<p>On a related note, <a title="Paul McKenney's blog" href="http://paulmck.livejournal.com/">Paul McKenney</a> pointed me to a paper (<a title="Analysis of inherent randomness of the Linux kernel" href="https://www.osadl.org/?id=684">abstract</a>, <a title="Eleventh Real Time Linux Workshop" href="https://www.osadl.org/?id=706">presentation</a>, <a title="[PDF]  Analysis of inherent randomness of the Linux kernel" href="http://lwn.net/images/conf/rtlws11/random-hardware.pdf">paper</a>) indicating that even disabling interrupts and running a few instructions gives an unpredictable value in the TSC, and inserting a usleep can make quite a good random number generator.  So if you have access to a high-speed, high-precision timing method, this may itself be sufficient.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=265</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Oh, BTW, I Am Engaged!</title>
		<link>http://rusty.ozlabs.org/?p=258</link>
		<comments>http://rusty.ozlabs.org/?p=258#comments</comments>
		<pubDate>Fri, 09 Mar 2012 01:48:43 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=258</guid>
		<description><![CDATA[A few of my friends saw the LWN coverage of http://baldalex.org, and sent me a note of congratulations.  This reveals how incredibly slack I am in maintaining connections with my disparate and distributed friends. So: I met a wonderful lady, we fell in love, and I proposed on April the 8th last year, at Mt [...]]]></description>
			<content:encoded><![CDATA[<p>A few of my friends saw the LWN coverage of <a title="Alex: A Bald Target" href="http://baldalex.org">http://baldalex.org</a>, and sent me a note of congratulations.  This reveals how incredibly slack I am in maintaining connections with my disparate and distributed friends.</p>
<div id="attachment_260" class="wp-caption alignright" style="width: 170px"><a href="http://rusty.ozlabs.org/wp-uploads/2012/03/alex-and-rusty-plane.jpg"><img class="size-full wp-image-260" title="alex-and-rusty-plane" src="http://rusty.ozlabs.org/wp-uploads/2012/03/alex-and-rusty-plane.jpg" alt="" width="160" height="127" /></a><p class="wp-caption-text">Alex and Rusty (2009)</p></div>
<p>So: I met a wonderful lady, we fell in love, and I proposed on April the 8th last year, at Mt Lofty Gardens overlooking the scenery.  She was speechless, delighted, and said yes!  In related news, one year later, we are set to marry: 5th April 2012, and 3pm at the McLaren Vale Visitor&#8217;s centre.  All welcome!  (Yes, that&#8217;s Easter Thursday).</p>
<p>So I&#8217;ll be offline for April, except briefly to post pictures if we meet the target!</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=258</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A Plea For Help: Charity</title>
		<link>http://rusty.ozlabs.org/?p=251</link>
		<comments>http://rusty.ozlabs.org/?p=251#comments</comments>
		<pubDate>Mon, 27 Feb 2012 23:57:29 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=251</guid>
		<description><![CDATA[I&#8217;m getting married in just over five weeks! My fiancée is raising money for charity; if we raise $50,000 by the big day, she will shave her head at the wedding.  Alexandra has had long hair all her life: she&#8217;s terrified but determined, so I&#8217;m determined to help. We&#8217;re already asking for donations in lieu [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_252" class="wp-caption alignleft" style="width: 160px"><a href="http://rusty.ozlabs.org/wp-uploads/2012/02/alex-and-arabella.jpg"><img class="size-thumbnail wp-image-252" title="alex-and-arabella" src="http://rusty.ozlabs.org/wp-uploads/2012/02/alex-and-arabella-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">En-haired Fiancée Alex with my daughter Arabella</p></div>
<p>I&#8217;m getting married in just over five weeks!</p>
<p>My fiancée is raising money for <a title="Time For Kids Australia" href="http://timeforkids.com.au">charity</a>; if we raise $50,000 by the big day, she will shave her head at the wedding.  Alexandra has had long hair all her life: she&#8217;s terrified but determined, so I&#8217;m determined to help.</p>
<p>We&#8217;re already asking for donations in lieu of wedding presents, but if you&#8217;ve ever wanted to buy me a beer for ipchains, iptables, netfilter, module-init-tools, lguest, CCAN, Rusty&#8217;s Unreliable Guides, CALU, or any other reason, I&#8217;ll take a $100/$20/$5 <a title="Givenow - Alex A Bald Target!" href="http://www.givenow.com.au/timeforkidsalexbaldtarget">donation here </a>instead :)</p>
<p>(Compulsory <a title="Facebook: Alex - Setting A Bald Target" href="https://www.facebook.com/pages/Setting-a-bald-target/162899967160468">Facebook page</a> here).</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=251</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Why Everyone Must Oppose The Merging of /usr and /</title>
		<link>http://rusty.ozlabs.org/?p=236</link>
		<comments>http://rusty.ozlabs.org/?p=236#comments</comments>
		<pubDate>Sat, 28 Jan 2012 05:04:07 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=236</guid>
		<description><![CDATA[As co-editor of the last edition of the File Hierarchy Standard before it merged into the Linux Standard Base, I&#8217;ve been following the discussion about combining the directories  /bin, /sbin and /lib into /usr/bin, /usr/sbin and /usr/lib respectively.  You can follow it too, via the LWN discussion. To summarize, there are two sides to the [...]]]></description>
			<content:encoded><![CDATA[<p>As co-editor of the last edition of the File Hierarchy Standard before it merged into the Linux Standard Base, I&#8217;ve been following the discussion about combining the directories  /bin, /sbin and /lib into /usr/bin, /usr/sbin and /usr/lib respectively.  You can follow it too, via the <a title="LWN: The case for the /usr merge" href="https://lwn.net/Articles/477467/">LWN discussion</a>.</p>
<p>To summarize, there are two sides to the debate.  The &#8220;pro&#8221; side points out:</p>
<ol>
<li>Nothing will really change for users, as symlinks will make old stuff still work.</li>
<li>There are precedents in Solaris and Fedora.</li>
<li>The weak reasonings used previously to separate / and /usr no longer apply.</li>
<li>Separate /usr has become increasingly unsupported anyway.</li>
<li>Moving to /usr will enable genuine R/O root filesystem sharing.</li>
</ol>
<p>The &#8220;anti&#8221; side, however, raises very salient points:</p>
<ol>
<li>Lennart Poettering supports it.</li>
<li>Lennart Poettering is an asshole.</li>
</ol>
<p>Fellow Anti-mergers, I understand the pain and anguish that systemd has caused you personally, and your families.  Your hopes and dreams crushed, by someone with all the charm of a cheese grater across the knuckles.  Your remaining life tainted by this putrescent subhuman who forced himself upon your internet.</p>
<p>Despite the privation we have all endured, please find strength to stop this nightmarish ravaging of our once-pure filesystems.  For if he&#8217;s not stopped now, what hope for  /usr/sbin vs /usr/bin?</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=236</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>The Power of Undefined Values</title>
		<link>http://rusty.ozlabs.org/?p=232</link>
		<comments>http://rusty.ozlabs.org/?p=232#comments</comments>
		<pubDate>Mon, 21 Nov 2011 06:04:56 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=232</guid>
		<description><![CDATA[Tools shape the way we work, because they change where we perceive risk when we write code.  If common compilers warn about something, I&#8217;ll code in a way that will trigger it in case of mistakes.  eg: instead of: int err = -EINVAL; if (something()) goto out; err = -ENOSPC; if (something_else()) goto cleanup_something; ... [...]]]></description>
			<content:encoded><![CDATA[<p>Tools shape the way we work, because they change where we perceive risk when we write code.  If common compilers warn about something, I&#8217;ll code in a way that will trigger it in case of mistakes.  eg: instead of:</p>
<pre>    int err = -EINVAL;
    if (something())
         goto out;
    err = -ENOSPC;
    if (something_else())
         goto cleanup_something;
...
cleanup_something:
    undo_something();
out:
    return err;</pre>
<p>I would now set err in every branch:</p>
<pre>    int err;
    if (something()) {
        err = -EINVAL;
        goto out;
    }
    if (something_else()) {
        err = -ENOSPC;
        goto out;
    }</pre>
<p>Because when I add another clause to the initialization and forget to set err, gcc will warn me about it being uninitialized.  This bit me once, and it can be hard to spot the problem when you&#8217;re only reviewing a patch, not the code as a whole.</p>
<p>These days, we have valgrind, and despite its fame as a use-after-free debugger, it really shines at telling you when you rely on the results of an uninitialized field.  So, I&#8217;ve adapted to lean on it.  I explicitly don&#8217;t initialize structure members I don&#8217;t use in a certain path.  I avoid calloc(): while 0 is often less harmful than any other value, I&#8217;d much rather know that I&#8217;ve thought about and set up every field I actually use.  When changing code this is particularly important, and I spend a lot of my time changing code.  I have even changed to doing malloc() in some cases where I previously used on-stack or file-scope variables.  Valgrind doesn&#8217;t track on-stack usage very well, and static variables are defined to be zeroed, so valgrind can&#8217;t tell when I wander into the weeds.  I think these days, that&#8217;s a misfeature.</p>
<p>So, if I were designing a C-like language today, I&#8217;d bake in the concept of undefined values, knowing that the tools to leverage it are widely available.  10 years ago, I&#8217;d have said 0-by-default is safest, but times change.  I think Go chose wrong here, but it may not be as bad as C for other reasons.  I&#8217;d have to code in it for a few years to really tell.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=232</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>PLUG: Coding: let&#8217;s have fun!</title>
		<link>http://rusty.ozlabs.org/?p=229</link>
		<comments>http://rusty.ozlabs.org/?p=229#comments</comments>
		<pubDate>Thu, 22 Sep 2011 03:16:54 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=229</guid>
		<description><![CDATA[The Perth Linux User Group are flying me across next month to speak, complete with on-couch accommodation! But since I can&#8217;t find an easily-linkable synopsis of my talk, here are the details: It&#8217;s hard to describe the joy of coding, if you haven&#8217;t experienced it,  but in this talk will try to capture some of [...]]]></description>
			<content:encoded><![CDATA[<p>The <a title="PLUG" href="http://plug.org.au">Perth Linux User Group</a> are flying me across <a href="http://www.plug.org.au/sites/default/files/rusty-banner.jpg">next month to speak,</a> complete with on-couch accommodation! But since I can&#8217;t find an easily-linkable synopsis of my talk, here are the details:</p>
<p style="padding-left: 30px;">It&#8217;s hard to describe the joy of coding, if you haven&#8217;t experienced it,  but in this talk will try to capture some of it.  Free/Open Source lets us remove the cruft which forecloses on the joy of coding: seize this chance!</p>
<p>I&#8217;ll talk about some of my favourite projects over the last 15 years of  Free Software coding: what I did, how much fun it was and some surprising results which came from it.  I&#8217;ll also discuss some hard lessons learned about joyless coding, so you can avoid it.  There will also be a sneak peak from my upcoming linux.conf.au talk.</p>
<p>There&#8217;ll be some awesome code to delight us.  And if you&#8217;re not a programmer we&#8217;ll take you our journey and show you the moments of  brilliance which keep us coding.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=229</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>linux.conf.au: Hacking your badge for lca2012</title>
		<link>http://rusty.ozlabs.org/?p=226</link>
		<comments>http://rusty.ozlabs.org/?p=226#comments</comments>
		<pubDate>Tue, 20 Sep 2011 06:17:12 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=226</guid>
		<description><![CDATA[Someone mentioned that you had to look at the source code if you wanted to hack your badge this year; I would have considered that cheating if I hadn&#8217;t known.  (It&#8217;s been a few years since I last hacked my badge).  But it helps if you look in the right place: http://lca2012.blogspot.com/2011/09/feeling-silly.html Thanks to Tony [...]]]></description>
			<content:encoded><![CDATA[<p>Someone mentioned that you had to look at the source code if you wanted to hack your badge this year; I would have considered that cheating if I hadn&#8217;t known.  (It&#8217;s been a few years since I last hacked my badge).  But it helps if you look in the right place: <a title="An important LCA2012 note" href="http://lca2012.blogspot.com/2011/09/feeling-silly.html">http://lca2012.blogspot.com/2011/09/feeling-silly.html</a></p>
<p>Thanks to <a title="Tony Breeds on Google+.  Not that you can see much..." href="https://plus.google.com/100601843177630672041">Tony Breeds</a> for pointing me at that after I&#8217;d given up with the github upstream source&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=226</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Speeding CCAN Testing (By Not Optimizing)</title>
		<link>http://rusty.ozlabs.org/?p=220</link>
		<comments>http://rusty.ozlabs.org/?p=220#comments</comments>
		<pubDate>Thu, 25 Aug 2011 07:50:52 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=220</guid>
		<description><![CDATA[So, ccanlint has accreted into a vital tool for me when writing standalone bits of code; it does various sanity checks (licensing, documentation, dependencies) and then runs the tests, offers to run the first failure under gdb, etc.   With the TDB2 work, I just folded in the whole TDB1 code and hence its testsuite, which [...]]]></description>
			<content:encoded><![CDATA[<p>So, ccanlint has accreted into a vital tool for me when writing standalone bits of code; it does various sanity checks (licensing, documentation, dependencies) and then runs the tests, offers to run the first failure under gdb, etc.   With the TDB2 work, I just folded in the whole TDB1 code and hence its testsuite, which made it blow out from 46 to 71 tests.  At this point, ccanlint takes over ten minutes!</p>
<p>This is for two reasons: firstly because ccanlint runs everything serially, and secondly because ccanlint runs each test <em>four</em> times: once to see if it passes, once to get coverage, once under valgrind, and once with all the platform features it tests turned off (eg. HAVE_MMAP).  I balked at running the reduced-feature variant under valgrind, though ideally I&#8217;d do that too.</p>
<p>Before going parallel, I thought I should cut down the compile/run cycles.  A bit of measurement gives some interesting results (on the initial TDB2 with 46 tests):</p>
<ol>
<li>Compiling the tests takes 24 seconds.</li>
<li>Running the tests takes 12 seconds.</li>
<li>Compiling the tests with coverage support takes 32 seconds.</li>
<li>Running the tests with coverage support takes 32 seconds.</li>
<li>Running the tests under valgrind takes 204 seconds (17x slowdown)</li>
<li>Running the tests with coverage under valgrind takes 326 seconds.</li>
</ol>
<p>It&#8217;s no surprise that valgrind is the slowest step, but I was surprised that compiling is slower than running the tests.  This is because CCAN &#8220;run&#8221; tests actually #include the entire module source so they can do invasive testing.</p>
<p>So the simple approach of compiling up once, with -fprofile-arcs -ftest-coverage, and running that under valgrind to get everything in one go is much slower (from 325 up to 407 seconds!).  The only win is to skip running the tests without valgrind, shaving 11 seconds off (about 2%).</p>
<p>One easy thing to do would be to compile with optimization to speed the tests up. Valgrind documentation (and my testing) confirms that using &#8220;-O&#8221; doesn&#8217;t effect the results on any CCAN module, so that should make it run faster, for very little effort.  When I actually measured, total test time increases from 407 seconds to 495, because compiling with optimization is so slow.  Here are the numbers:</p>
<ol>
<li>Compiling the tests with optimization (-O/-O2/-O3) takes 54/77/130 seconds.</li>
<li>Running the tests with optimization takes 11/11/11 seconds.</li>
<li>Running the tests under valgrind with optimization takes 201/208/208 seconds</li>
</ol>
<p>So no joy there. Time to go and fix up my tests to run faster, and make ccanlint run (and compile!) them in parallel&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=220</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Professional Photographers and Licensing: Copyright Sucks</title>
		<link>http://rusty.ozlabs.org/?p=217</link>
		<comments>http://rusty.ozlabs.org/?p=217#comments</comments>
		<pubDate>Sun, 14 Aug 2011 01:57:03 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=217</guid>
		<description><![CDATA[So, Alex scoured through wedding photographers, we chose one, met them, got the contract&#8230; and it stipulates that they own the copyright, and will license the images to us &#8220;for personal use&#8221;.  So you pay over $3,000 and don&#8217;t own the images at the end (without a contract, you would).  That means no Wikipedia of [...]]]></description>
			<content:encoded><![CDATA[<p>So, Alex scoured through wedding photographers, we chose one, met them, got the contract&#8230; and it stipulates that they own the copyright, and will license the images to us &#8220;for personal use&#8221;.  So you pay over $3,000 and don&#8217;t own the images at the end (without a contract, you would).  That means no Wikipedia of course, but also no Facebook; they&#8217;re definitely a commercial organization.  No blogs with ads.  In the unlikely event that Alex or I change careers and want to use a shot for promotional materials, and the photographer has died, gone out of business or moved overseas, we&#8217;re out of luck even if we&#8217;re prepared to pay for it.</p>
<p>The usual answer (as always with copyright) is to ignore it and lie when asked.  But despite my resolution a few years ago to care less about copyright, this sticks in my craw.  So I asked: it&#8217;s another $1,000 for me to own the copyright.  I then started emailing other photographers, and that seems about standard.  But why?  Ignoring the obvious price-differentiation for professional vs amateur clients, photographers are in a similar bind to me: they want to use the images for promotion, say, in a collage in a wedding magazine.  And presumably, the magazine insists they own the copyright.  Since the photographers I emailed had varying levels of understanding of copyright, I can totally understand that simplification.</p>
<div>Fortunately, brighter minds than I have created a solution for this already: Creative Commons licensing.  On recommendation of one of Alex&#8217;s friends, we found <a title="Andre Goosen" href="http://iamandregoosen.com/">a photographer</a> who agreed to license the images to us under <a title="Creative Commons Attribution 3.0 AU" href="http://creativecommons.org/licenses/by/3.0/au/">Creative Commons Attribution </a><em>without additional charge</em>; in fact, he was delighted to find out about CC, since the clear deeds make it easier for him to explain to <em>his</em> clients what rights they have.  All win!</div>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=217</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>License Boilerplates</title>
		<link>http://rusty.ozlabs.org/?p=212</link>
		<comments>http://rusty.ozlabs.org/?p=212#comments</comments>
		<pubDate>Thu, 21 Jul 2011 03:02:50 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=212</guid>
		<description><![CDATA[CCAN is supposed to be about the code, so I&#8217;ve avoided the standard GPL boilerplate comment at the top of each source file.  I reluctantly include a symlink to the full license text in each directory now, since lawyers approached me to clarify the single &#8220;License:&#8221; line in _info.  A useful discussion on the samba-technical [...]]]></description>
			<content:encoded><![CDATA[<p>CCAN is supposed to be about the code, so I&#8217;ve avoided the standard GPL boilerplate comment at the top of each source file.  I reluctantly include a symlink to the full license text in each directory now, since lawyers approached me to clarify the single &#8220;License:&#8221; line in _info.  A <a title="ccan code breaks older build farm systems" href="http://lists.samba.org/archive/samba-technical/2011-July/078439.html">useful discussion</a> on the samba-technical mailing list has reinforced my view that it&#8217;s marginal clutter, but most CCAN modules now have a one-line courtesy comment such as &#8220;/* Licensed under LGPLv2.1+ &#8211; see LICENSE file for details */&#8221; at the top of each .c and .h file.</p>
<p>Please make a conscious choice here: if license enforcement is a high priority for your project you probably want copyright assignments, license boilerplates and click-through agreements for everyone who downloads your source code.  But if you&#8217;re spending significant time or effort on legal issues for your little coding project, you&#8217;re probably doing it wrong&#8230;</p>
<p>(ccanlint now scans for common license boilerplates, as well as those comments; this means we can also detect use of incompatible licenses inside modules, or dependent modules.  The former test noticed that I&#8217;d labelled the md4 module as LGPL, yet it&#8217;s actually GPL.  The latter spotted that ccan/likely (LGPL) depends on ccan/htable (GPL): legal (the whole thing is actually GPL), but misleading, as Michael Adam noted).  Automating this stuff is a clear win for a project like CCAN.  I also re-licensed a bunch of useful-but-trivial modules from LGPL to public domain, as I want the BSD modules to use them).</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=212</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Bitcoin for something useful.</title>
		<link>http://rusty.ozlabs.org/?p=206</link>
		<comments>http://rusty.ozlabs.org/?p=206#comments</comments>
		<pubDate>Fri, 15 Jul 2011 13:16:46 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=206</guid>
		<description><![CDATA[I wanted a scalable version of this poster: so I offered 1BTC on the bitcoin forum and someone produced a version I can print and put on my wall in my home office. Here is the SVG. Enjoy!.]]></description>
			<content:encoded><![CDATA[<p>
I wanted a scalable version of this poster: <a href="http://i.imgur.com/coeUe.jpg"><img src="http://ozlabs.org/~rusty/images/coeUe.jpg"></a> so I <a href="http://forum.bitcoin.org/index.php?topic=25861.0">offered 1BTC on the bitcoin forum</a> and someone produced a version I can print and put on my wall in my home office.
</p>
<p><a href="http://ozlabs.org/~rusty/images/Van%20Poster.svg">Here is the SVG.  Enjoy!</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=206</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Waiting For The Great Bitcoin Crash (GBC)</title>
		<link>http://rusty.ozlabs.org/?p=200</link>
		<comments>http://rusty.ozlabs.org/?p=200#comments</comments>
		<pubDate>Mon, 06 Jun 2011 10:43:36 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=200</guid>
		<description><![CDATA[I like bitcoins.  A simple open source client, a well-run developer community, clever algorithms, decentralized assurance model, and of course near-zero transaction fees.  For all the economic arguments (some of which sound like early anti-Wikipedia arguments, though I hesitate to argue by analogy), when I first used it to tip a website, I fell in [...]]]></description>
			<content:encoded><![CDATA[<p>I like <a href="http://bitcoin.org">bitcoins</a>.  A simple open source client, a well-run developer community, clever algorithms, decentralized assurance model, and of course near-zero transaction fees.  For all the economic arguments (some of which sound like early anti-Wikipedia arguments, though I hesitate to argue by analogy), when I first used it to tip a website, I fell in love.  It took me about 3 minutes to transfer $50 from my bank account to a stranger&#8217;s via my bank&#8217;s website, with 2 days latency.  It took me about 5 seconds to send 0.1BTC to a stranger, with about 10 minute latency.  It was a revelation.</p>
<p>But, while bitcoins rock, volatility doesn&#8217;t.  It&#8217;s currently a bit hard to get some bitcoins, and the price has rocketed by speculation.  It&#8217;s not just a cute FOSS project, it&#8217;s becoming a real market, and surely those piling in now are susceptible to hacking, scams and the inevitable hiccups that go with any project ramping up.  It&#8217;s all going to come crashing down to earth.</p>
<p>Good.  My hope is that after the GBC the speculators will move on.  Volatility will settle.  The boring work of accreting trust in this new tool will continue.  I fervently hope that it we will appreciate its true utility once the dust has settled and the <em>Man Loses A Million Dollars and House in Virtual Currency</em> headlines have faded.</p>
<p>[Yes, you can tip me in bitcoins!  I think it's a good habit, fun to do, and better than ads as I get a warm fuzzy feeling of appreciation.  I'll be using any tips I get to tip other sites which take BTC].</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=200</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>&#8220;If you didn&#8217;t run code written by assholes, your machine wouldn&#8217;t boot&#8221;</title>
		<link>http://rusty.ozlabs.org/?p=196</link>
		<comments>http://rusty.ozlabs.org/?p=196#comments</comments>
		<pubDate>Thu, 19 May 2011 05:39:05 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=196</guid>
		<description><![CDATA[This was passed on to me by Ben Elliston, ex-gcc hacker and good guy.  Amusing in context, but the corollary is that working on free software means you&#8217;ll encounter such people.  You may have to work with them.  You may have to argue with them (and they may be right). Quite some time ago I [...]]]></description>
			<content:encoded><![CDATA[<p>This was passed on to me by Ben Elliston, ex-gcc hacker and good guy.  Amusing in context, but the corollary is that working on free software means you&#8217;ll encounter such people.  You may have to work with them.  You may have to argue with them (and they may be right).</p>
<p>Quite some time ago I was horrified by the private behaviour of a hacker I deeply respected: malicious, hypocritical stuff.  And it caused an internal crisis for me: I thought we were all striving together to make the world a better place.  Here are the results I finally derived:</p>
<ol>
<li>Being a great hacker does not imbue moral or ethical characteristics.</li>
<li>Being a great coder doesn&#8217;t mean you&#8217;re not a crackpot.</li>
<li>Working on a great project doesn&#8217;t mean you share my motivations about it.</li>
</ol>
<p>This wasn&#8217;t obvious to me, and it seems it&#8217;s not obvious to others.  A-list actors endorsing Scientology doesn&#8217;t make it a good idea.  Great FOSS political work was done by a certain obnoxious LWN-haunting nutball.  Julian Assange may or may not be guilty of crimes in Sweden. Many of my kernel coworkers believed that GPLv3 was somehow a radical change from GPLv2.  Some sweet code has been written by gun nuts, lechers, holocaust deniers and (in at least once case) someone who believes that fasting will cure cancer.</p>
<p>In any walk of life you have to work with all kinds; having to do so in my dream job as FOSS hacker was a hard lesson for me.  It&#8217;s great to work with people whose skills you respect, but don&#8217;t expect to like them all.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=196</wfw:commentRss>
		<slash:comments>44</slash:comments>
		</item>
		<item>
		<title>A small success: LWN Supporter Option.</title>
		<link>http://rusty.ozlabs.org/?p=193</link>
		<comments>http://rusty.ozlabs.org/?p=193#comments</comments>
		<pubDate>Tue, 10 May 2011 01:12:47 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=193</guid>
		<description><![CDATA[I was delighted that Jon Corbet pinged me to say he was finally implementing a supporter option for LWN.  It&#8217;s been about 12 months since I started asking about it, and 6 since I started asking publicly.  When it finally arrived, in classical FOSS brand-suicide style, it was named the &#8220;Maniacal supporter&#8221; option.  I don&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>I was delighted that Jon Corbet pinged me to say he was finally implementing a <a href="https://lwn.net/Articles/440355/">supporter option for LWN</a>.  It&#8217;s been about 12 months since I started asking about it, and 6 since I started <a title="LWN Supporter Subscription: Take My Money!" href="http://rusty.ozlabs.org/?p=145">asking publicly</a>.  When it finally arrived, in classical FOSS brand-suicide style, it was named the &#8220;Maniacal supporter&#8221; option.  I don&#8217;t think Jon believed anyone would actually pay more &#8220;for nothing&#8221;, but curiosity finally won out.</p>
<p>But he&#8217;s wrong: people want the consistent commentry and in-depth analysis that only dedicated experts like Jon can provide.  And we know that if they don&#8217;t get enough money, they&#8217;ll have to stop writing and take day jobs; this is not some abstract charity.  I want Jon to be comfortable and LWN financially secure and able to concentrate on what they do best, which seems to be a rare skill in our community.  This is a start in that direction; I welcome your suggestions on what to do next&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=193</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>On Conference Preparation Time&#8230;</title>
		<link>http://rusty.ozlabs.org/?p=189</link>
		<comments>http://rusty.ozlabs.org/?p=189#comments</comments>
		<pubDate>Mon, 07 Feb 2011 02:31:24 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=189</guid>
		<description><![CDATA[Jokes aside, I don&#8217;t prepare my conference talks the night before.  I took a week off of work to prepare my linux.conf.au talk this year (two weeks before the conference, and I still spent a couple of work days in the week after completing it).  That kind of spontaneity takes preparation! Here&#8217;s a rough calculator [...]]]></description>
			<content:encoded><![CDATA[<p>Jokes aside, I don&#8217;t prepare my conference talks the night before.  I took a week off of work to prepare my linux.conf.au talk this year (two weeks before the conference, and I still spent a couple of work days in the week after completing it).  That kind of spontaneity takes preparation!</p>
<p>Here&#8217;s a rough calculator of preparation time for an LCA-style talk.  Make sure you finish at least a week before, to allow slippage!</p>
<h3>Preparation Time for Standard Talk (~45 minutes)</h3>
<p>If you have given it before:</p>
<ul>
<li>If you were happy with it and not changing it: <strong>15 minutes</strong> to re-check, change conference name and date.</li>
<li>If you were happy with it and changing it slightly: <strong>+1 hour</strong> for a complete run-through.</li>
<li>If you were a little unhappy with it, but content will not change: <strong>+5 hours</strong> for reviewing previous video and googling for feedback and taking notes, then running through changed sections twice and complete run-through once.</li>
</ul>
<p>Prior work:</p>
<ul>
<li>If you&#8217;re not the world expert on what you&#8217;re talking about, allow at least <strong>a week</strong> of research time.</li>
<li>If the topic is vague allow at least a month of mulling time, where the topic sits in your brain.  For longer periods I recommend jotting down your ideas.  (I did this for an entire year before my OLS keynote, and I knitted a theme from the contents of that text file full of thoughts and examples).</li>
<li><strong>One hour </strong>to <strong>a day</strong> to plan your talk structure: what are your main points, what&#8217;s the extra magic?</li>
</ul>
<p>Writing the talk:</p>
<ul>
<li><strong>10 minutes</strong> per basic slide.  Usually I&#8217;d expect 25 slides, so say <strong>4 hours.</strong></li>
<li><strong>30 minutes</strong> per diagram (five minutes of this will be trying to figure out if you really <em>need</em> a diagram: you probably do!).  I&#8217;d expect five to ten diagrams, so say <strong>5 hours.</strong></li>
<li><strong>Five hours</strong> per demo.  Not just setting it up in the first place, but making it robust and repeatable and practicing switching to and from your presentation adds time.</li>
<li><strong>Two hours</strong> per run-through (since you tend to stop and mod the first few times).  You&#8217;ll want at least one more of these than you have time for, but I&#8217;d expect <strong>8 hours</strong> for this.</li>
</ul>
<p>Additional overheads:</p>
<ul>
<li>Using new software: <strong>+4 hours</strong> if you&#8217;re on your own, <strong>+1 hour</strong> if you have an expert available.</li>
<li>Any project work where you have to document the steps for your talk: <strong>double</strong> your normal project time for the overhead, to ensure it&#8217;s comprehensible and maximally useful to the audience (vs. works).</li>
<li>Any new presentation technique you haven&#8217;t used before, add <strong>4 hours</strong> for two additional run-throughs.</li>
</ul>
<h3>Preparation Time for A Tutorial (~1.5 hours)</h3>
<p>Similar calculations, but you&#8217;ll have many more demos so it&#8217;ll be more than twice as long.  The real killer is that you have to practice timings with real people who are similar to your target audience.  This means in addition to everything else, you&#8217;ll want to give it for some local group at least twice, because there&#8217;s no way you can know what the timing will be like until you&#8217;ve done that.  Say <strong>+2 hours</strong> to organize the practice sessions, and <strong>+6 hours</strong> to run them (this includes transport, setup, testing and time overruns for each one).</p>
<h3>Testing Time</h3>
<p>Testing time happens standing in the venue, at the podium with your  setup ready to go.  I allow <strong>5 minutes<em> </em></strong>for video setup.  If you&#8217;ve not presented on the laptop before, <strong>+15 minutes</strong>.  If you&#8217;re not always running 1024&#215;768, <strong>+10 minutes</strong>.  If you want audio, <strong>+5 minutes.</strong> If you have a video to show, <strong>+5 minutes.</strong> If you have an interactive demo, <strong>+5 minutes</strong> to find a practice volunteer, <strong>+20 minutes</strong> to run through the demo with them.</p>
<p>In general, allow half your testing time the day before (ie. you&#8217;ll need to access the venue), the rest in the space before your talk.</p>
<h3>An Example</h3>
<p>So, this gives a preparation time for my LCA 2011 talk as:</p>
<ul>
<li><strong>1 day</strong> planning.</li>
<li><strong>6 hours</strong> for 35 basic slides.</li>
<li><strong>2 hours</strong> for 4 diagrams.</li>
<li><strong>15 hours</strong> for 3 demos.</li>
<li><strong>8 hours</strong> for run-throughs.</li>
<li><strong>4 hours</strong> for messing with svgslides, even though I didn&#8217;t really use it in the end.</li>
<li><strong>3 days</strong> for coding up the example project, and documenting that code.</li>
<li><strong>4 hours</strong> for additional run-throughs because I hadn&#8217;t presented using a side-bar and emacs before.</li>
</ul>
<p>Giving a total time of of <strong>71 hours</strong> (assuming 8 hour days).  That&#8217;s probably about right.  And the required <strong>30+ minutes</strong> of testing time explains why I didn&#8217;t end up having people telnet into my laptop for the demos; if I&#8217;d tested that the day before, we might have been able to organize something.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=189</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Summary of &#8220;Advanced C Coding For Fun!&#8221;</title>
		<link>http://rusty.ozlabs.org/?p=186</link>
		<comments>http://rusty.ozlabs.org/?p=186#comments</comments>
		<pubDate>Thu, 03 Feb 2011 04:04:06 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=186</guid>
		<description><![CDATA[Perhaps there was too much fun, and not enough advanced C coding, as one attendee implied.  My original intent is to walk through a real implementation in the order I coded it, warts and all, but over 50% got cut for time.  After all, it took me 15 minutes in my BoF session just to [...]]]></description>
			<content:encoded><![CDATA[<p>Perhaps there was too much fun, and not enough advanced C coding, as one <a href="http://blogs.gnome.org/danni/2011/01/31/linux-conf-au-roundup/">attendee implied</a>.  My original intent is to walk through a real implementation in the order I coded it, warts and all, but over 50% got cut for time.  After all, it took me 15 minutes in my <a href="https://conf.linux.org.au/wiki/BoFSchedule">BoF</a> session just to run through the implementation of <a href="http://ccan.ozlabs.org/info/foreach.html">ccan/foreach</a>.  (Hi to the three people who attended!).</p>
<p>So I ended up doing a fair bit of waving at other code (yes, mainly in CCAN: if I have a useful trick, I tend to put it there).  Here&#8217;s the bullet-point version of my talk with links:</p>
<ul>
<li><a href="http://ccan.ozlabs.org">CCAN</a> is a CPAN-wannabe project for snippets of C code.</li>
<li>Your headers should be a readable and complete reference on your API.</li>
<li>Code  documentation should be human readable and machine processable (eg.  kerneldoc), but extracting it is a waste of time.  See above.</li>
<li>Your headers should contain example code, and this should be compile tested and even executed (ccanlint does this).</li>
<li>Perl&#8217;s TAP (<a href="http://testanything.org/">Test Anything Protocol</a>) has a <a href="http://ccan.ozlabs.org/info/tap.html">C implementation</a> which is easy to use.</li>
<li>You can write a <a href="http://ccan.ozlabs.org/info/array_size.html">better ARRAY_SIZE(arr)</a> macro than &#8220;sizeof(arr)/sizeof((arr)[0])&#8221;, using gcc extensions to warn if the argument is actually a pointer, not an array.</li>
<li>I got bitten by strcmp()&#8217;s usually-wrong return value after coding in C for ten years.  I suggest <a href="http://ccan.ozlabs.org/info/str.html">defining a streq() macro</a>.</li>
<li>It is possible, though quite difficult, to implement a fixed-values iterator macro, aka. <a href="http://ccan.ozlabs.org/info/foreach.html">foreach</a>.  It&#8217;s even efficient if you have C99.</li>
<li>Making functions return false rather than exit, even if the caller can&#8217;t really handle the failure, makes for easier testing.</li>
<li>Making your functions use errno is a bonus, though its semantic limitations are definitely a two-edged sword.</li>
<li>A common mistake is to call close, fclose, unlink or free in error paths, not realizing that <a href="http://ccan.ozlabs.org/info/noerr.html">they can alter errno</a> even if they succeed.</li>
<li>Never think to write malloc-fail-proof code without testing it thoroughly, otherwise you haven&#8217;t written malloc-fail-proof code.</li>
<li>You can test such &#8220;never-happen&#8221; failure paths <a href="http://ccan.ozlabs.org/info/failtest.html"><em>automatically</em> by forking</a>; make sure you give a nice way to get a debugger to the fail point though, and terminate failing tests as early as possible.</li>
<li>There are libraries to make option parsing easier than getopt; <a href="http://directory.fsf.org/project/popt/">popt</a> and <a href="http://ccan.ozlabs.org/info/opt.html">ccan/opt</a> are two.</li>
<li>You can use macros to provide <a href="http://ccan.ozlabs.org/info/typesafe_cb.html">typesafe callbacks</a> rather than forcing callbacks to take void * and cast internally; the compiler will warn you if you change the type of the callback or callback parameter so they no longer match.</li>
<li>Do not rely on the user to provide zero&#8217;d terminators to tables: use a non-zero value so you&#8217;re much more likely to catch a missing terminator.</li>
<li>Use <a href="http://talloc.samba.org">talloc</a> for allocation.</li>
<li>Don&#8217;t return a void * as a handle, even if you have to make up a type.  Your callers&#8217; code will be more typesafe that way.</li>
<li>Don&#8217;t use global variables in routines unless it&#8217;s clearly a global requirement: keep everything in the handle pointer.</li>
<li>Valgrind is awesome.  Valgrind with failtesting is invaluable for finding use-after-free and similar exit-path bugs.</li>
<li>Fixing a test doesn&#8217;t mean your program doesn&#8217;t suck.  I &#8220;fixed&#8221; a one-client-dies-while-another-is-talking-to-it by grabbing another client; that&#8217;s stupid, though my test now passes.</li>
<li>Don&#8217;t do anything in a signal hander; write to a nonblocking pipe and handle it in your event loop.</li>
<li>The best way to see why your program is getting larger over time is to use talloc_report() and see your allocation tree (you can use gdb if you need, <a href="http://permalink.gmane.org/gmane.network.samba.internals/53378">a-la Carl Worth</a>.</li>
<li>You might want to do something time-consuming like that in a child; remember to use _exit() in the child to avoid side-effects.</li>
<li>There are at least two tools which help you dump and restore C structures: <a href="http://samba.org/~tridge/junkcode/genstruct/">genstruct</a> and <a href="http://ccan.ozlabs.org/info/cdump.html" class="broken_link" >cdump</a> (coming soon, it&#8217;s in the talk&#8217;s <a href="http://git.ozlabs.org/?p=ccan-lca-2011.git">git tree</a> for the moment).  Both are very limited, though cdump is still being developed.</li>
<li>You can use a dump/exec/restore pattern to live-upgrade processes; forking a child to test dump and restore is recommended here!</li>
<li>If your restore code is well-defined for restoring fields that weren&#8217;t dumped, you can make significant code modifications using this pattern.</li>
<li>You can use C as a scripting language with a little boilerplate.  Use &#8220;#if 0&#8243; as the first line, followed by the code to recompile and exec, then &#8220;#else&#8221; followed by  the actual code.  Make it executable, and the shell will do the right thing.</li>
<li>You can use gdb to do just about anything to a running program; script it if you can&#8217;t afford to have it stopped for long.</li>
<li>The best hash algorithm to use is the Jenkins <a href="http://burtleburtle.net/bob/c/lookup3.c">lookup3</a> hash (there&#8217;s a <a href="http://ccan.ozlabs.org/info/hash.html">ccan/hash</a> convenient wrapper too).</li>
<li>The best map/variable array algorithm to use is <a href="http://judy.sourceforge.net/">Judy arrays</a> (much nicer with the <a href="http://ccan.ozlabs.org/info/jmap.html">ccan/jmap </a>wrapper).</li>
</ul>
<p>That was all I had room for; there was none for questions, and even the last two points were squished onto the final &#8220;Questions?&#8221; slide.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=186</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>The LCA Dinner Rule</title>
		<link>http://rusty.ozlabs.org/?p=184</link>
		<comments>http://rusty.ozlabs.org/?p=184#comments</comments>
		<pubDate>Thu, 27 Jan 2011 21:57:02 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=184</guid>
		<description><![CDATA[Dinner was great as only a room full of well-fed FOSS geeks can be, but I felt that that my time on-stage was too long and too chaotic; I apologise.  The LCA team have done such a thorough job of recovering from events that it&#8217;s a surprise when things don&#8217;t magically come together. So I [...]]]></description>
			<content:encoded><![CDATA[<p>Dinner was great as only a room full of well-fed FOSS geeks can be, but I felt that that my time on-stage was too long and too chaotic; I apologise.  The LCA team have done such a thorough job of recovering from events that it&#8217;s a surprise when things <strong>don&#8217;t </strong>magically come together.</p>
<p>So I propose an &#8220;<em>LCA Dinner Rule</em>&#8221; for future conferences: that dinner activities span no more than 1 hour.  Preferably combining wit with its brevity.<em><br />
</em></p>
<p>(Oh, and I have a strong feeling that next year&#8217;s dinner is going to be a superb event&#8230;)</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=184</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Source from &#8220;Advanced C Programming for Fun!&#8221;</title>
		<link>http://rusty.ozlabs.org/?p=182</link>
		<comments>http://rusty.ozlabs.org/?p=182#comments</comments>
		<pubDate>Thu, 27 Jan 2011 07:28:12 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=182</guid>
		<description><![CDATA[Putting &#8220;Advanced&#8221; in the title did not have the desired effect of scaring people off.  Nonetheless, it went well: maybe because I was on the wired network so noone could access my server to find the bugs :) There wasn&#8217;t anywhere obvious to place a link about my talk, so here&#8217;s the git repository.]]></description>
			<content:encoded><![CDATA[<p>Putting &#8220;Advanced&#8221; in the title did not have the desired effect of scaring people off.  Nonetheless, it went well: maybe because I was on the wired network so noone could access my server to find the bugs :)</p>
<p>There wasn&#8217;t anywhere obvious to place a link about my talk, so here&#8217;s the <a href="http://git.ozlabs.org/?p=ccan-lca-2011.git">git repository</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=182</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>On C Linked Lists</title>
		<link>http://rusty.ozlabs.org/?p=168</link>
		<comments>http://rusty.ozlabs.org/?p=168#comments</comments>
		<pubDate>Sun, 12 Dec 2010 04:31:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=168</guid>
		<description><![CDATA[There are two basic styles of double-linked lists in C; I&#8217;ll call them ring style and linear style. The Linux kernel has ring-style, defined in include/linux/list.h.  You declare a &#8216;struct list_head&#8217; and everyone who wants to be in the list puts a &#8216;struct list_head list&#8217; in their structure (struct list_node in CCAN&#8217;s version).  This forms [...]]]></description>
			<content:encoded><![CDATA[<p>There are two basic styles of double-linked lists in C; I&#8217;ll call them ring style and linear style.</p>
<p>The Linux kernel has ring-style, defined in include/linux/list.h.  You declare a &#8216;struct list_head&#8217; and everyone who wants to be in the list puts a &#8216;struct list_head list&#8217; in their structure (struct list_node in <a href="http://ccan.ozlabs.org/info/list.html">CCAN&#8217;s version</a>).  This forms a ring of pointers in both the forward and reverse directions.</p>
<p>SAMBA uses linear-style, defined in lib/util/dlinklist.h.  You simply declare a &#8216;struct foo *&#8217; as your list, and everyone who wants to be in the list puts a &#8216;struct foo *prev, *next&#8217; in their structure.  This forms a NULL-terminated list in the forward direction (the reverse direction became a ring recently to facilitate tail access).  (Linux&#8217;s hlist.h datastructure is similar, only done in list.h style).</p>
<p>Points in favor of ring-style lists:</p>
<ol>
<li>Insertion and deletion are branchless, as the elements and head are homogeneous:
<pre> head-&gt;next-&gt;prev = new;
 new-&gt;next = head-&gt;next;
 new-&gt;prev = head;
 head-&gt;next = new;</pre>
<p>vs:</p>
<pre>if (!head) {
    new-&gt;prev = head = new;
    new-&gt;next = NULL;
} else {
    new-&gt;prev = head-&gt;prev;
    head-&gt;prev = new;
    new-&gt;next = head;
    head = new;
}</pre>
</li>
<li>list_add, list_del are inline functions, not macros, since the types are known.</li>
</ol>
<p>Points in favor of linear-style lists:</p>
<ol>
<li>They&#8217;re typesafe, since the head pointer and internal pointers are all the correct type.</li>
<li>Forward iteration is simpler, since the list ends at NULL rather than back at the head. In theory this could free a register, but the bigger difference is that it&#8217;s often useful to have NULL in your iterator once the loop is done.</li>
<li>As a corollary, iteration, initialization and emptiness testing don&#8217;t need some tricky macros:
<pre>  struct foo *head = NULL;
  if (head == NULL) ...
  for (i = head; i; i = i-&gt;next) ...
</pre>
<p>vs</p>
<pre>  LIST_HEAD(head);
  if (list_empty(&amp;head)) ...
  list_for_each(i, head, list) ...
</pre>
</li>
<li>Uses slightly less space for the head pointer (one pointer, vs two).</li>
</ol>
<p>So how important is efficiency of insert and delete in a real project?  To provide some data on this, I first annotate the linux kernel so each list.h operation would increment a counter which I could dump out every so often.  Then I booted the kernel on my laptop and ran as normal for three days.</p>
<table border="1">
<tbody>
<tr>
<th> Operation</th>
<th> Frequency</th>
</tr>
<tr>
<th> Empty Test</th>
<td>45%</td>
</tr>
<tr>
<th> Delete</th>
<td>25%</td>
</tr>
<tr>
<th> Add</th>
<td>23%</td>
</tr>
<tr>
<th> Iterate Start</th>
<td>3.5%</td>
</tr>
<tr>
<th> Iterate Next</th>
<td>2.5%</td>
</tr>
<tr>
<th> Replace</th>
<td>0.76%</td>
</tr>
<tr>
<th> Other Manipulation</th>
<td>0.0072%</td>
</tr>
</tbody>
</table>
<p>Firstly, I was surprised that we add and remove from lists much more than we look through them.  On reflection, this makes sense: if lookups are really common we don&#8217;t use a linked list.  And note how often we check for whether the list is empty: this looks like a &#8220;list as a slow path&#8221; pattern. I wonder if SAMBA (or other projects) list usage looks the same&#8230; anyone?</p>
<p>Secondly, we delete more than we add, but we could be &#8220;deleting&#8221; initialized-but-unadded elements.  I didn&#8217;t chase this beyond re-reading and enhancing my patch to measure &#8220;other manipulations&#8221; to see if they could explain it (no).</p>
<p>Thirdly, when we iterate it&#8217;s short: the list is empty or we break out on the first element 28% of the time (I didn&#8217;t differentiate).  I wonder if a single-linked list would be an interesting micro-space-optimization for many of these lists.</p>
<p>Summary: I like the safety of SAMBA&#8217;s lists, but there&#8217;s clearly real merit in eliminating those branches for add and delete.  It&#8217;s a genuine performance-usability trade-off, so I I think we&#8217;ll still have both in CCAN&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=168</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>On Conference Harrassment&#8230;</title>
		<link>http://rusty.ozlabs.org/?p=172</link>
		<comments>http://rusty.ozlabs.org/?p=172#comments</comments>
		<pubDate>Mon, 06 Dec 2010 04:06:53 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=172</guid>
		<description><![CDATA[The recent attention given to harassment at conferences was sparked by the  sexual assault described of Noirin Shirley at ApacheCon; her particular attacker&#8217;s actions were deranged and criminal, but it&#8217;s clearly a variation on an ongoing theme of harassment. This issue raises two questions for future conferences: how do we prevent an atmosphere which encourages [...]]]></description>
			<content:encoded><![CDATA[<p>The recent attention given to harassment at conferences was sparked by the  <a href="http://geekfeminism.org/2010/11/07/noirins-hell-of-a-time/" class="broken_link" >sexual assault</a> described of Noirin Shirley at ApacheCon; her particular attacker&#8217;s actions were deranged and criminal, but it&#8217;s clearly a variation on an <a href="http://geekfeminism.wikia.com/index.php?title=Timeline_of_incidents">ongoing theme of harassment</a>.</p>
<p>This issue raises two questions for future conferences: how do we prevent an atmosphere which encourages this, and how do we make sure everyone knows that we don&#8217;t have such an atmosphere at the conference?  The two are related, but we need both.</p>
<p>Atmosphere matters; let&#8217;s not discount its power because it&#8217;s intangible.  It is the atmosphere at <a href="http://conf.linux.org.au/">linux.conf.au</a> which inspires new project and enlivens existing ones among the attendees.  So let&#8217;s ensure it&#8217;s a positive one, and let&#8217;s talk about it.  I&#8217;m confident the much-harried LCA organizers will integrate an <a href="http://geekfeminism.org/2010/11/29/get-your-conference-anti-harassment-policy-here/" class="broken_link" >anti-harassment policy</a>, but I encourage them to do so boldly, loudly and soon. <strong>[Correction: They already have. </strong>Front page, first paragraph has "LCA2011 is dedicated to a harassment-free conference experience for everyone. See our <a href="http://lca2011.linux.org.au/about/harassment">anti-harassment policy</a> for details."]</p>
<p>It is worth expending serious effort addressing this problem.  I&#8217;ve only experienced prolonged negative sexual stereotyping once; the only help was someone who was unrelentingly positive and set a clear example of welcome, which others followed.  Let&#8217;s <strong>all </strong>try to be like that.</p>
<p>There are two things I promise to try to do this time around:</p>
<ol>
<li>Assume everyone is a delegate; a far lesser error than being the tenth person who assumes you are a tech-uninterested partner.</li>
<li>Welcome a newcomer, ask about what they hack on and listen, introduce them to someone else, then leave them to it. When I do this, I always learn something.</li>
</ol>
<p>(This post inspired by Alex, who is encouraging me to be more self-aware, by example).</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=172</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Not Buying Another HTC</title>
		<link>http://rusty.ozlabs.org/?p=166</link>
		<comments>http://rusty.ozlabs.org/?p=166#comments</comments>
		<pubDate>Wed, 17 Nov 2010 00:50:18 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=166</guid>
		<description><![CDATA[Sent back my HTC Magic for warranty repair (wouldn&#8217;t charge) and they upgraded firmware; I can&#8217;t install cyanogenmod on it any more, making it fairly useless to me.  I spent two days of my holiday time trying and failing the goldcard lottery. I just dropped my other HTC Magic and shattered the glass, so I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>Sent back my HTC Magic for warranty repair (wouldn&#8217;t charge) and they upgraded firmware; I can&#8217;t install cyanogenmod on it any more, making it fairly useless to me.  I spent two days of my holiday time trying and failing the goldcard lottery.</p>
<p>I just dropped my other HTC Magic and shattered the glass, so I&#8217;m in the market for a new Android phone via ebay.  Given my phones only last about 6-12 months, any advice for older cyanogenmod-friendly phones?  Or should I just give in and pay $500 for a <a href="http://laforge.gnumonks.org/weblog/2010/08/21/">Samsung Galaxy S</a>?</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=166</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>The Art of Community (TAoC)</title>
		<link>http://rusty.ozlabs.org/?p=162</link>
		<comments>http://rusty.ozlabs.org/?p=162#comments</comments>
		<pubDate>Thu, 11 Nov 2010 01:53:20 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=162</guid>
		<description><![CDATA[Fuzzy topics annoy me, and hurt my brain as I struggle to quantitify them.  People who talk on these topics grate on my nerves; it&#8217;s a kind of geek gag reflex. So I really didn&#8217;t like Jono Bacon&#8217;s The Art of Community.  It was like a counseling session where all the faults you half-suspected you [...]]]></description>
			<content:encoded><![CDATA[<p>Fuzzy topics annoy me, and hurt my brain as I struggle to quantitify them.  People who talk on these topics grate on my nerves; it&#8217;s a kind of geek gag reflex.</p>
<p>So I really didn&#8217;t like Jono Bacon&#8217;s <a href="http://www.artofcommunityonline.org/about/">The Art of Community</a>.  It was like a counseling session where all the faults you half-suspected you had get laid out in a massive TODO list with cogent reasoning which makes you squirm.  By the second chapter, I really wanted to knee Jono in the nuts.  My mind kept returning to <a href="http://ccan.ozlabs.org">CCAN</a>, my half forgotten could-be-great-oneday project.  It got so distracting that by halfway through the fourth chapter I put it down and haven&#8217;t picked it up again.</p>
<p>But I will return.  And I will re-read it from the start, for one reason: it reshaped my thinking about building community projects, and that has lead directly to the increase in activity in the past months around CCAN.  Jono has thought really hard and long about this topic, and provides a framework which the rest of us can map our projects onto.  That alone is a serious intellectual feat, the clear friendly prose is just a bonus.</p>
<p>Next time, I just hope I can tick enough of TAoC boxes that I don&#8217;t feel like I&#8217;ve doomed my pet project like a puppy chained to a submarine.</p>
<p>[Footnote: Jono's one of those annoying "doers".  I find his <a href="http://openrespect.org/">http://openrespect.org/</a> self-evident: I want to be respected while corrected, but I only recently figured that out and I suspect others might have missed it too.]</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=162</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hashtables vs Judy Arrays, Round 1</title>
		<link>http://rusty.ozlabs.org/?p=153</link>
		<comments>http://rusty.ozlabs.org/?p=153#comments</comments>
		<pubDate>Mon, 08 Nov 2010 11:06:08 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=153</guid>
		<description><![CDATA[I spent some of Friday and yesterday working on my CCAN hashtable module (renamed to htable); I wrote a set of benchmarks and ran them until my laptop steamed and I had burnished the implementation into a sleek shining bundle of awesome. Then it was time to run the same benchmark on Judy Arrays; code [...]]]></description>
			<content:encoded><![CDATA[<p>I spent some of Friday and yesterday working on my CCAN hashtable module (renamed to htable); I wrote a set of benchmarks and ran them until my laptop steamed and I had burnished the implementation into a sleek shining bundle of awesome.</p>
<p>Then it was time to run the same benchmark on Judy Arrays; code I had only become aware of via <a href="http://www.fi.muni.cz/~kas/blog/">Yenga</a>&#8216;s <a href="http://rusty.ozlabs.org/?p=125#comment-377">comment</a> on my blog.  A few weeks back I wrote some friendly wrappers for libJudy, since I found the raw interface made my eyes bleed.  Fortunately, that proved <a href="http://ccan.ozlabs.org/info/jmap.html">quite simple</a>, but it&#8217;s worth making a note for those who (like me three weeks ago) aren&#8217;t familiar with Judy Arrays.  The theory is that different datastructures should be used for different key layouts: high density or sparse, many or few, always concentrating on reducing cache impact.  The result is a serious amount of code for all the different cases: a risky, full-frontal assault on the problem rather than the normal cautious approach of using a single data structure then ignoring or special-casing a few corner cases.</p>
<p>Anyway, my initial benchmark was designed to push hashtables pretty hard, particularly as I used delete markers in my original implementation.  That tends to make performance suck after a great deal of churn, so I churn the hashtable in the middle of the benchmark.  It used consecutive keys, but I switched to spacing them out some more after that proved to be incredibly performant with Judy (which is ordered, unlike a hashtable).</p>
<p>I compared the JudyL implementation with my htable implementation; in fact I ran it at both 75% full (dense), 37% full (sparse) and 37% full with bitstealing disabled (dumb).  75% is high for a typical hashtable, but my implementation seems quite happy operating at that point.  I was interested in mapping an int to an object: for the hash table the object contained the int key as well as a payload pointer (to self, for consistency checking).  For Judy the object simply contained a payload pointer; a Judy array itself contains the key.  In both cases I used 50,000,000 objects, and divided the total time by the number of objects to give nanoseconds per operation.</p>
<h3>The Good: Ordered, Dense Keys</h3>
<p>First, doing things Judy is good at: the initial insertion of keys 0 to 49,999,999 in order, looking them up in order, looking up keys 50,000,000 to 99,999,999 in order.  Note to be fair, you have to add about 150 and 300M to the hashtable memory usage to get the peak usage, since they double-allocate-and-copy, then free the old table.</p>
<table border="1">
<tbody>
<tr>
<th> Measure</th>
<th> Judy</th>
<th> Dense hash</th>
<th> Sparse hash</th>
<th> Dumb hash</th>
</tr>
<tr>
<th> Memory</th>
<td>420M</td>
<td>640M</td>
<td>895M</td>
<td>895M</td>
</tr>
<tr>
<th> Initial insert (ns)</th>
<td>137</td>
<td>332</td>
<td>471</td>
<td>482</td>
</tr>
<tr>
<th> Linear hit (ns)</th>
<td>19</td>
<td>174</td>
<td>176</td>
<td>214</td>
</tr>
<tr>
<th> Linear miss (ns)</th>
<td>14</td>
<td>234</td>
<td>184</td>
<td>286</td>
</tr>
</tbody>
</table>
<p>The main story here is that Judy in order is unbeatably cache-friendly.  It&#8217;s nice to notice that bitstealing optimization pays off for hashtables as fewer buckets need to be dereferenced, and similarly with lower density, but Judy wins hands down here.</p>
<p>OK, now we lookup random elements <em>and access the elements</em>: the latter is important, since it&#8217;s more realistic and hash has to access the element to verify it anyway.  But since our elements are allocated as a huge array, that&#8217;s why random accessing them (even via a hash table) costs us more.  Oh, and our &#8220;random&#8221; is actually &#8220;10007 apart&#8221; meaning it&#8217;s harder on caches than random would be, which might occasionally be cache hot.</p>
<table border="1">
<tbody>
<tr>
<th> Measure</th>
<th> Judy</th>
<th> Dense hash</th>
<th> Sparse hash</th>
<th> Dumb hash</th>
</tr>
<tr>
<th> Random hit (ns)</th>
<td>361</td>
<td>330</td>
<td>357</td>
<td>375</td>
</tr>
</tbody>
</table>
<p>The hashtable&#8217;s doesn&#8217;t often cache miss, and the denser hash seems to win more than it loses from having to look at more buckets, but with this kind of key density Judy is very competitive anyway.</p>
<p>Now we delete everything and reinsert them all (in order):</p>
<table border="1">
<tbody>
<tr>
<th> Measure</th>
<th> Judy</th>
<th> Dense hash</th>
<th> Sparse hash</th>
<th> Dumb hash</th>
</tr>
<tr>
<th> Delete (ns)</th>
<td>199</td>
<td>171</td>
<td>200</td>
<td>172</td>
</tr>
<tr>
<th> Reinsert (ns)</th>
<td>148</td>
<td>191</td>
<td>197</td>
<td>175</td>
</tr>
</tbody>
</table>
<p>As my hashtable doesn&#8217;t shrink it gets an artificial benefit, yet Judy again stays very competitive.  Our dumb hash does surprisingly well here, too; there&#8217;s no reason for it to be different from the &#8220;smart&#8221; sparse hash, but it was a repeatable effect.  Perhaps the CPU is doing the noop bit manipulations (anding with all 1s, etc) faster?</p>
<h3>The  Bad: Unordered Sparse Keys</h3>
<p>Now let&#8217;s look at churn.  Fresh datastructures are easy, but over time we want to see what happens as elements are added and deleted.  In my case, I iterate through the keys and delete each object then re-add it with the key increased by 50,000,000.  With a hashtable using delete markers, this can reveal a weaknesses in the way they are garbage collected.  Then I iterate one last time and space the keys out 9 values apart.  The objects themselves are still dense, but the keys are far less so (ranging from 0 to 449,999,991: I chose 9 because I was originally playing with a few hundred million objects and didn&#8217;t want to overflow).</p>
<p>So with sparser keys and a worn-in datastructure, we do our three kinds of lookups again:</p>
<table border="1">
<tbody>
<tr>
<th> Measure</th>
<th> Judy</th>
<th> Dense hash</th>
<th> Sparse hash</th>
<th> Dumb hash</th>
</tr>
<tr>
<th> Memory</th>
<td>607M</td>
<td>640M</td>
<td>895M</td>
<td>895M</td>
</tr>
<tr>
<th> Linear Hit (ns)</th>
<td>61</td>
<td>215</td>
<td>202</td>
<td>265</td>
</tr>
<tr>
<th> Linear Miss</th>
<td>60</td>
<td>301</td>
<td>223</td>
<td>278</td>
</tr>
<tr>
<th> Random Hit</th>
<td>736</td>
<td>405</td>
<td>386</td>
<td>445</td>
</tr>
</tbody>
</table>
<p>Note that Judy consumes a little more memory at this point, though it&#8217;s still ahead of the densest hash.</p>
<p>But finally we see a case where a good hashtable is clearly superior: random hits on a full range of keys.  The hashtable has suffered a little (there are quite a few deleted records there after all the churn), but 10-20% penalty for churn is not as bad as Judy&#8217;s 100% penalty for sparser keys.</p>
<p>Last of all, we delete every second object and then re-add with modified keys:</p>
<table border="1">
<tbody>
<tr>
<th> Measure</th>
<th> Judy</th>
<th> Dense hash</th>
<th> Sparse hash</th>
<th> Dumb hash</th>
</tr>
<tr>
<th> Delete Half (ns)</th>
<td>266</td>
<td>120</td>
<td>103</td>
<td>103</td>
</tr>
<tr>
<th> Add Half (ns)</th>
<td>205</td>
<td>200</td>
<td>103</td>
<td>105</td>
</tr>
</tbody>
</table>
<p>Judy is still suffering from those sparse keys, though add is competitive with the dense hash (made even denser by those deleted elements).</p>
<h3>Summary</h3>
<p>Judy allows for ordered access and let you have an external key rather than putting it into your structure.  If those matter, the choice is clear.  Other times you don&#8217;t want a latency spike as the hash table grows and rehashes, or you&#8217;re concerned about malicious insertion patterns bombing a hashchain, which again favors using Judy arrays.</p>
<p>If you have adjacent access patterns, Judy will win.  If you have dense keys, Judy will be competitive.  If you have random access and sparse keys, Judy lookups and deletes could be twice as slow as an optimized hash table, but using 20% to 100% less memory.</p>
<p>And one final note on random access: if it&#8217;s not quite random, such as if every second lookup is near the previous one, time drops from 736 to 410 nanoseconds, back competitive with the hashtable result.  It&#8217;s quite impressive.</p>
<p>[Here are the URLs: <a href="http://judy.sourceforge.net/">the Judy arrays homepage</a> (but your distro probably has a package, Ubuntu does), the <a href="http://ccan.ozlabs.org/info/jmap.html">ccan wrapper module</a>, and the ccan <a href="http://ccan.ozlabs.org/info/htable.html">htable module</a>.]</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=153</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>A nomenclature anecdote</title>
		<link>http://rusty.ozlabs.org/?p=150</link>
		<comments>http://rusty.ozlabs.org/?p=150#comments</comments>
		<pubDate>Sun, 07 Nov 2010 01:01:44 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=150</guid>
		<description><![CDATA[&#8220;&#8230;an author, with thesaurus in hand, chooses the names of variables carefully&#8230;&#8221; &#8212; Knuth, Literate Programming The Elements of Style&#8216;s invaluable advice for prose (&#8220;Omit needless words&#8221;) is mapped into C coding as &#8220;Curt names win&#8221;: I crave descriptive, short, punchy names. Though perhaps not to the extent of K&#38;R, whose approach might be described [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>&#8220;&#8230;an author, with thesaurus in hand, chooses the names of variables carefully&#8230;&#8221; &#8212; Knuth, <a href="http://www.literateprogramming.com/"><em>Literate Programming</em></a></p></blockquote>
<p><a href="http://en.wikipedia.org/wiki/The_Elements_of_Style"><em>The Elements of Style</em></a>&#8216;s invaluable advice for prose (&#8220;Omit needless words&#8221;) is mapped into C coding as &#8220;Curt names win&#8221;: I crave descriptive, short, punchy names. Though perhaps not to the extent of K&amp;R, whose approach might be described as &#8220;Omit needless vowels&#8221;.</p>
<p>Sometimes though, I get baffled by my own bullshit.  Yesterday I was benchmarking Judy arrays vs hash tables (more in another post) and I noticed that I had named two equivalent functions &#8220;htable_find&#8221; vs &#8220;jmap_get&#8221;.  In my mind <em>find</em> has overtones of searching and<em> get</em> has more direct connotations: say, a simple dereference. So why did I name them differently?  I had to implement that htable_find myself, whereas for jmap_get I only implemented a one-line wrapper :)</p>
<p>Since the operations are very fast, <a href="http://ccan.ozlabs.org/info/jmap.html">jmap</a> is already a published CCAN module, and get is one letter shorter than find, I renamed htable_find to htable_get.  Consistent naming has benefits of its own&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=150</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LWN Supporter Subscription: Take My Money!</title>
		<link>http://rusty.ozlabs.org/?p=145</link>
		<comments>http://rusty.ozlabs.org/?p=145#comments</comments>
		<pubDate>Wed, 27 Oct 2010 23:42:48 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=145</guid>
		<description><![CDATA[I&#8217;ve been quietly lobbying Linux Weekly News to offer a $500 &#8211; $1000 &#8220;Supporter&#8221;-level subscription option; LWN has saved my sanity for the last two years as my conference schedule has been severely restricted. But one problem with LWN is that they spend all their time writing and editing quality articles, instead of the boring [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been quietly lobbying <a href="http://lwn.net">Linux Weekly News</a> to offer a $500 &#8211; $1000 &#8220;Supporter&#8221;-level subscription option; LWN has saved my sanity for the last two years as my conference schedule has been severely restricted.</p>
<p>But one problem with LWN is that they spend all their time writing and editing quality articles, instead of the boring stuff: ie. taking money from people.  The base rate finally increased this year after 8 years at $5/month (to $7), but I worry that Jon and co will look back at the years of service and lack of retirement savings and wish they&#8217;d had secure well-paying jobs like the rest of us.</p>
<p>After numerous monthly reminder emails and face-to-face lobbying at LinuxCon Japan, I&#8217;m giving up on &#8220;quietly&#8221; and asking your for your help.  Please: next time you comment on LWN, could you add some sig-line lobbying for the Supporter-level subscription?  Even if you have no intention of ever buying such a thing, at least you know one person will&#8230;</p>
<p>What Do We Want? <strong><a href="http://rusty.ozlabs.org/?p=145">LWN Supporter Subscription</a>!</strong><br />
When Do We Want it? <strong>Before <a href="http://lca2011.linux.org.au/">LCA 2011</a>!</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=145</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>On C Library Implementation</title>
		<link>http://rusty.ozlabs.org/?p=140</link>
		<comments>http://rusty.ozlabs.org/?p=140#comments</comments>
		<pubDate>Thu, 14 Oct 2010 06:50:17 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=140</guid>
		<description><![CDATA[I recently came across the Judy library which seems like an impressive set of data structures to implement mappings (think variable length arrays or hash indexed by simple key).  I also looked through the codec2 sources recently, and I saw some of the same API issues, so I thought I&#8217;d crystalize some of them here: [...]]]></description>
			<content:encoded><![CDATA[<p>I recently came across the <a href="http://judy.sourceforge.net">Judy library</a> which seems like an impressive set of data structures to implement mappings (think variable length arrays or hash indexed by simple key).  I also looked through the <a href="http://codec2.org">codec2</a> sources recently, and I saw some of the same API issues, so I thought I&#8217;d crystalize some of them here:</p>
<ol>
<li>Packaging code libraries is a pain. There&#8217;s an obscene amount of clutter around the code itself. Some can be blamed on autoconf, but common practices like putting the source under src/ make it worse. In Judy there are 29 actual core code files, but 33 infrastructure files (automake et al) and AUTHORS, ChangeLog, INSTALL, COPYING and 13 README files.</li>
<li>Typedefs which are always the same are silly. Don&#8217;t typedef long or void * or const void *, you&#8217;re confusing documentation with real typesafety. Undefined structs are your friend. If your functions take a context, make it a &#8220;struct mylib&#8221; (or union) and don&#8217;t expose the definition in the public header. Your code will be clearer and more typesafe and so will the library users&#8217;.</li>
<li>Context creation and destruction are common patterns, so stick with &#8220;mylib_new()&#8221; and &#8220;mylib_free()&#8221; and everyone should understand what to do.  There&#8217;s plenty of bikeshedding over the names, but these are the shortest ones with clear overtones to the user.</li>
<li>If your library needs initialization use &#8220;mylib_init()&#8221; or &#8220;mylib_setup()&#8221;.</li>
<li>Try to make your API impossible to misuse (ie. no mylib_init() at all if you can manage it), but if that fails assert(), abort() or crash. You are not doing developers a favor by making misuse easy to ignore. If you worry about crashing on users, and can handle an API error gracefully, put that handling under #ifdef NDEBUG, like assert does. But this is not where you should be spending your development effort!</li>
<li>If your only possible error is out-of-memory, consider not handling it at all. It&#8217;s pretty certain none of your library users will handle it (remember Tridge&#8217;s Law: untested code is broken code). If it&#8217;s convenient to return NULL, do so. Otherwise offer a way of registering an error function and let the user deal with setjmp etc. Do not complicate your API to handle this case.</li>
<li>Always return the error. If you return a pointer, NULL is standard. Magic pointers for different errors can work too, but at that point some other method might be preferable.</li>
<li>Think hard before implementing multiple levels of interface. It&#8217;s better to have everyone understand your interface and have 10% not use it (or hack it!) because it&#8217;s incomplete, than have 50% reinvent it because yours is too complicated.</li>
<li>There&#8217;s a standard naming for &#8220;I know what I&#8217;m doing&#8221; low-level alternate functions: the single-underscore prefix (eg. _exit()).  That&#8217;s your one extra level of interface, and if you need more see the previous point.  Perhaps another library is in order, on top of this one? <strong>This is a standard violation: see Glen&#8217;s comment below.</strong></li>
<li>Don&#8217;t worry about namespace issues too much.  Avoid the standard namespace and settle on a short prefix (eg. opt_, judy_, talloc_), but there&#8217;s little you can do if your name hits someone else&#8217;s so don&#8217;t make your code a pain to use just to try to uniquify the names (ccan_rusty_russell_opt_ prefixes, for example).</li>
<li>Your header(s) should be readable, and in a readable order.  I consider <em>extracting</em> comments a complete waste of time, but kerneldoc and doxgen et. al. provide a consistent model for documenting your API in the headers, and should be used as such.</li>
<li>Don&#8217;t sweat portability too much.  Try not to paint yourself into a corner, but if you&#8217;re not going to test on other platforms leave the serious effort until someone does.</li>
<li>I do consider use of C++ keywords in headers overly unfriendly to our C++ cousins, but in the code it&#8217;s fine; I avoid putting extern &#8220;C&#8221; in my headers, as C++ people can do that (and whatever else they need) before #including the header.  Again, if you&#8217;re not going to test it, don&#8217;t work up a sweat about it.</li>
<li>There&#8217;s a standard naming scheme for C, and it&#8217;s all lower case with underscores as separators.  Don&#8217;t BumpyCaps.</li>
</ol>
<p>On some level, each of these influenced CCAN as we thought &#8220;how do we encourage people to reuse this code?&#8221;   Many are specific applications of the CCAN Golden Rule (aka. <a href="http://ccan.ozlabs.org/Wiki/GoldenRule" class="broken_link" >&#8220;our code should not be ugly&#8221;</a>) which drives that attempt to make code reusable.</p>
<p>Packaging cruft in CCAN is sidestepped entirely; since people are expected to include ccan/ in their own code, we leave that to them, with some guidelines on how to use the code:</p>
<ul>
<li>You supply a &#8220;config.h&#8221; somewhere we can #include it, with various #define HAVE_FOO in it.</li>
<li>The _info file is actually a C program: the header contains (trivial-to-parse kerneldoc style) metainformation such as author, description, and example program(s).  These are aimed at human consumption: compiling and executing the code gives dependencies in a parsable form (still, only the ccan/ dependencies are the only ones really amenable to machine use).</li>
<li>The (main?) header will be the same name as the module, with &#8220;.h&#8221; appended, eg &#8220;ccan/foo/foo.h&#8221;.  The kerneldoc-style comments are the module API documentation.</li>
<li>The test/ subdir contains tests of standard forms (eg. run-* test are to be executed).</li>
<li>DEBUG can be defined for &#8220;give me extra debugging on this module, performance cost be damned&#8221;.  This is separate from normal sanity checks which would be disabled by defining NDEBUG.</li>
</ul>
<p>In other words, you see the code first and foremost when you look in a CCAN module.</p>
<p>We also have a &#8220;namespacize&#8221; tool (very primitive, needs love) which is designed to rewrite the code in case of namespace clashes (currently it prepends ccan_, and scans dependent modules and fixes them up too).  This allows us to ignore namespace issues :)</p>
<p>The &#8220;ccanlint&#8221; tool is CCAN&#8217;s always-too-primitive checker/scorer tool, which ideally would judge a module on all of the complaints above.  It currently runs the test cases, checks their coverage and the like, but of course it&#8217;ll never be sophisticated enough to judge interfaces.  However, it does check for the existence of kerneldoc comments, and even extract and compile Example: code fragments (using some fun heuristics) to make sure they haven&#8217;t bitrotted.  And I keep adding new checks which make it more useful.</p>
<p>This probably explains why I stay up late writing CCAN modules: I can concentrate on writing the code (and tests!) without the other cruft.  And I don&#8217;t even need to stick to an API or ABI for my modules (api* tests indicate an API guarantee, and only three modules have those!).  And because it&#8217;s source-level, you don&#8217;t have to stretch your interface to cover all the cases; users with weird needs can simply use the code as a basis for their own.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=140</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Being Sampled for The Genographic Project</title>
		<link>http://rusty.ozlabs.org/?p=138</link>
		<comments>http://rusty.ozlabs.org/?p=138#comments</comments>
		<pubDate>Mon, 11 Oct 2010 00:44:49 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=138</guid>
		<description><![CDATA[IBM are involved with the Genographic Project, which is an attempt to &#8220;chart new knowledge about the migratory history of the human species&#8221;, by cheekswabbing hundreds of thousands of people around the world.  You get swabbed, you get an id to access your history, and they get the consolidated data from the results. My initial [...]]]></description>
			<content:encoded><![CDATA[<p>IBM are involved with the <a href="https://genographic.nationalgeographic.com/genographic/index.html">Genographic Project</a>, which is an attempt to &#8220;chart new knowledge about the migratory history of the human species&#8221;, by cheekswabbing hundreds of thousands of people around the world.  You get swabbed, you get an id to access your history, and they get the consolidated data from the results.</p>
<p>My initial reaction was that I wasn&#8217;t personally interested, but I <strong>am</strong> interested in the project overall, so when I was told they were doing an event in Adelaide on <a href="http://www.adelaide.edu.au/environment/event/2010/genographics/">Friday at the Central Markets</a>, I decided I&#8217;d go along and get swabbed (or have Arabella do it, since she&#8217;ll be with me).</p>
<p>The deal is that the first 100 volunteers can be tested for free, so if you&#8217;re interested now is your chance!</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=138</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ccan/opt</title>
		<link>http://rusty.ozlabs.org/?p=135</link>
		<comments>http://rusty.ozlabs.org/?p=135#comments</comments>
		<pubDate>Fri, 08 Oct 2010 04:39:47 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=135</guid>
		<description><![CDATA[I reviewed the code in popt a while back, and got a mail from Jeff Johnson on whether I thought the library worth revisiting (ie. popt2).  I replied that it was, then didn&#8217;t hear anything since. There are so many option-parsing libraries around, but I really wanted something simple and yet powerful enough for the [...]]]></description>
			<content:encoded><![CDATA[<p>I <a href="http://rusty.ozlabs.org/?p=55">reviewed</a> the code in <a href="http://freshmeat.net/projects/popt/">popt</a> a while back, and got a mail from Jeff Johnson on whether I thought the library worth revisiting (ie. popt2).  I replied that it was, then didn&#8217;t hear anything since.</p>
<p>There are so many option-parsing libraries around, but I really wanted something simple and yet powerful enough for the popt use cases.  Particularly, I wanted it avoid the getopt() loop and just use typesafe callbacks (yeah, I have a hammer&#8230;) so it could be arbitrarily extended by the user.  The result is the latest CCAN module, &#8220;<a href="http://ccan.ozlabs.org/info/opt.html">opt</a>&#8220;, which is very much popt-inspired (popt-lite?).</p>
<p>Beware the API which isn&#8217;t used! It originally had a popt-style struct table, with first entry being the long option (or NULL), and the second being the short option (or &#8216;\0&#8242;).  While writing tests, I used &#8220;&#8211;foobar&#8221; as the long option, instead of (the correct) &#8220;foobar&#8221;.  If I can&#8217;t use my own API, what hope is there?</p>
<p>So I rewrote it: the option name is now a /-separated string, like &#8220;&#8211;foobar/-f&#8221;. This is much more intuitive, more grep-friendly, and gives us obvious aliases.  Its format is also checked when you register the option or option table.</p>
<p>Another subtlety worth mentioning: the end-of-table-marker <strong>isn&#8217;t</strong> a zero entry.  It&#8217;s too easy to miss that and have your code still &#8220;work&#8221; because the next patch of memory happens to be zeroed.  On your platform.</p>
<p>I converted (the admittedly-trivial) ccanlint from getopt() to ccan/opt; it gained long options, as well as losing 24 lines (16 of which was losing the hand-rolled usage() function.</p>
<p>It&#8217;s not worth converting existing popt code IMHO (though I&#8217;d be interested in the feedback!), but if you&#8217;re still using getopt/getopt_long, you should probably take a look.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=135</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Back To Cacheline Tree Hash Tables</title>
		<link>http://rusty.ozlabs.org/?p=125</link>
		<comments>http://rusty.ozlabs.org/?p=125#comments</comments>
		<pubDate>Tue, 21 Sep 2010 04:45:54 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=125</guid>
		<description><![CDATA[After my previous conclusion that doubling linear hash tables were good enough, it turns out that they don&#8217;t work for TDB: enlarging or moving the hash table in the presence of tdb_chainlock is not possible.  So, I ended up implementing expanding hash tables, and ran into a familiar set of problems. The design is simple; [...]]]></description>
			<content:encoded><![CDATA[<p>After my previous conclusion that <a href="http://rusty.ozlabs.org/?p=94">doubling linear hash tables were good enough</a>, it turns out that they don&#8217;t work for TDB: enlarging or moving the hash table in the presence of tdb_chainlock is not possible.  So, I ended up implementing expanding hash tables, and ran into a familiar set of problems.</p>
<p>The design is simple; we start with a simple hash table.  When it gets too full, we expand a bucket to point to a sub-hashtable, which we similarly expand to sub-tables when it fills.  Seems like a nice logarithmic expanding data structure that means if we use 8 bit hash tables (ie. 256  entries) we&#8217;ll fit well over a billion entries in a 4 level deep set of tables.</p>
<p>Yet as we <a href="http://rusty.ozlabs.org/?p=94#memory-usage">discovered previously</a>, the hash density is horrible.  To see why, imagine our entries hit the hash buckets in order: the first entry belongs in hash bucket 0, the next in hash bucket 1&#8230; it&#8217;s all good for the first 256 entries, and our single top-level hash table ends up with 100% occupancy.  However, the 257th entry collides in bucket 0, causing it to expand into a 256-entry subtable which only has two entries in it.  By the time we have 512 entries, we&#8217;ve got a top-level hash table full of pointers to 256 sub-hash tables; that&#8217;s a total of 68352 hash buckets holding a mere 512 entries.  That&#8217;s 0.75% density, or an overhead just over 1k per entry!</p>
<p>In practice our arrangement is not perfectly even, so we don&#8217;t get as low as 0.75%, but we certainly don&#8217;t get up to 100% either.  Our density wavers between a <strong>minimum of 1.3% and a maximum of 4.5%</strong> (I simulated this; if someone has pointers to a good &#8220;Hash Statistics For Beginners&#8221; course please tell me!).  Our average density sits roughly halfway between those two, so I&#8217;ll be quoting min and max values from here in.</p>
<p>So, how do we improve this?  The first thing I tried is to organize our hash into groups: we only expand when we fill an entire group.<a href="#footnote-1">[1]</a>.  Say we use 8-entry groups; if your bucket is full, you try the next one in the group.  If all 8 are full, then you expand all the buckets into 8 new sub-tables.  At expense of a slightly longer search time (we now have to search up to 8 buckets at the bottom level, rather than just 1), this means we tend to be fuller before we expand.  This raises the<strong> maximum density to a respectable 25.3%, though the minimum drops to 0.6%</strong>.  Still, our average density has jumped from 3% to 13%.</p>
<p>So, what if we don&#8217;t expand all 8 buckets at once, but expand the most popular one in the group?  Our <strong>minimum density rises to 1.5%, and our maximum to 33%</strong>; closer to a 17% average.  Unfortunately calculating the most popular bucket means re-calculating the hash of all entries in the group.  With the expand-all approach, we needed to recalculate hashes for 8 entries to decide into which subtable each entry should be inserted.  With the expand-one approach, we calculate hashes for 8 entries, then 7 next time, then 6&#8230; 36 calculations (ie. O(N^2)).</p>
<p>We do have the hash value of the current entry: what if we simply expand the bucket that belongs in?  It may not be the fullest bucket, but we know  it&#8217;s not going to be empty.   This gives a close-to-optimal result, with <strong>densities ranging from 1.2% to 31%</strong>.</p>
<p>Now note that with all these approaches, expanding a bucket to point to a subtable means messing with a full group: some entries may go down into the subtable, others may move within group.  So we need to re-calculate the hashes anyway unless we store some extra information in the hash bucket somewhere.  For TDB2, we don&#8217;t really need 64 bits for entries: 64 exabytes should be enough for anyone, so the top 8 bits are free, and all records are 8-byte aligned so the bottom 3 bits are free.</p>
<p>There are two approaches which seem useful: store the &#8220;home bucket&#8221; in unused bits in the offset (3 bits) which means we never have to rehash when we expand a bucket (unless moving a hash entry down a level), or store a single &#8220;happy where I am&#8221; bit (around half of entries in full groups are in exactly the right location, so knowing this saves us half our rehash calculations).  It depends on how many bits we want to spend.</p>
<p>But 15% average density still sucks.  If we increase the group size it slows down searches a little and requires more rehashing on expansion or more bits to indicate the home bucket.  For example, 32-entry groups using &#8220;create subtable where we want to insert the new entry&#8221; gets us <strong>1.2% to 60% density</strong>.  Yet that means storing the &#8220;home bucket&#8221; would take 5 bits.</p>
<p>That minimum density is still a worry.  The obvious change is to reduce our subtable size: say 64, not 256 entries for sub-levels<a href="#footnote-2">[2]</a>.  Of course, our tree becomes deeper, making us less efficient, so we don&#8217;t really want to do that.</p>
<p>Is there anything else we can do to increase that minimum density?  The answer is yes, but it&#8217;s not free: we can share subtables.  For example, when a group fills, we expand all group entries to point at the same (new) subtable.  When a group in that subtable fills, we split the subtable.  In effect, we expand a table sideways before we expand down a level.</p>
<p>In the simplest case, we split the shared subtable back into one-subtable-per-bucket immediately when any group fills.  Going back to our 256-entry hash tables with groups of 32, this gives a <strong>density range of 2.6% to 61%</strong>. This has raised the minimum density by a factor of 2.  But that expansion from a single shared subtable to 32 subtables is costing us, so I tried an alternative where instead  of unsharing immediately, we split into two.  So we start with all 32 buckets in the group pointing at the same subtable, then split so 16 buckets are pointing at each of two subtables, until eventually each one has a unique subtable, which then expands down.  The result is a <strong>density range from 13% to 61%</strong>.  This last result is ten times the minimum on our unshared 32-entry groups.</p>
<p>Of course, unsharing has costs as well: again, we need to rehash to figure out which of the subtables each entry belong in.  And again, doing it all at once is cheaper than doing it five times.  And once more, we can use 5 additional bits to say which entry of the group above this entry belongs to.  Once we&#8217;re in an unshared subtable however, these bits are useless (and on average we will be in an unshared subtable half the time).  That&#8217;s a fair cost for something which has marginal effect on our average density; it just helps our worst-case.</p>
<p>This entire decision comes down to <em>expansion cost.<strong> </strong></em>This is not the same as insertion cost; not all insertions cause expansion, and if the system is in steady state (we don&#8217;t ever shrink the hash) expansion is rare.  We need a model for our usage to know how often we expand; we also need to know how often we delete, insert and search (both successful and failing searches).</p>
<p>To wrap up, here is how we can use any extra bits in our hash entries:</p>
<table border="1" width="100%">
<thead>
<tr>
<th>Num Bits</th>
<th>Name</th>
<th width="65%">Benefits</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Subtable Bit</td>
<td>Bucket points to subtable, not an actual entry.</td>
</tr>
<tr>
<td>Any</td>
<td>Extra Hash Bits</td>
<td>Avoids lookups on hash collisions: each bit halves number of lookups.  May avoid hash recalculation when pushing entries down into subtable.</td>
</tr>
<tr>
<td>1</td>
<td>Hash Truncated Bit</td>
<td>Indicates fewer/no Extra Hash Bits are valid.  Otherwise we always need to rehash when we push entries down a sublevel, to fill in the Extra Hash bits.  This way it can be done as required.</td>
</tr>
<tr>
<td>log2(groupsize)</td>
<td>Home Bucket</td>
<td>Avoid rehashing on expanding a bucket to a subtable,<br />
for entries not going down to that subtable.<br />
Helps searching on collisions.</td>
</tr>
<tr>
<td>1</td>
<td>In Home Bucket</td>
<td>Alternative to above: avoids rehashing about 50% of buckets, and helps searching on collisions.</td>
</tr>
<tr>
<td>log2(groupsize)</td>
<td>Shared Bucket</td>
<td>Indicate which subtable we belong to in a shared subtable.  With one of the two above, avoids rehashing when splitting shared subtable.  Helps searching to a lesser extent (only on shared subtable).</td>
</tr>
<tr>
<td>1</td>
<td>Deleted Bit</td>
<td>Avoids reshuffle on delete, but may slow lookups a little.</td>
</tr>
<tr>
<td>1</td>
<td>Collision Bit</td>
<td>Indicates we should keep searching.  Speeds lookups.</td>
</tr>
</tbody>
</table>
<p>Feedback welcome.  If you want to play with my simulator, you can find it <a href="http://ozlabs.org/~rusty/hash-density.c">here</a>.</p>
<hr />
<p><a name="footnote-1">[1]</a> It also means that two identical hash values don&#8217;t create an infinite set of subtables.  In practice, we need to use a linked list if we run out of hash bits anyway.  My test code has an abort() in this case.</p>
<p><a name="footnote-2">[2]</a> With a hash size of 64, our <strong>minimum density rises to 5.8%, maximum 42%</strong> with 8-entry groups (with 32-entry groups the density range is <strong>6% to 66%</strong>).</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 806px; width: 1px; height: 1px; overflow: hidden;">We can use some bits in each entry to indicate what its &#8220;home bucket&#8221; would be, but that has a cost too.</div>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=125</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>fcntl lock starvation and TDB</title>
		<link>http://rusty.ozlabs.org/?p=120</link>
		<comments>http://rusty.ozlabs.org/?p=120#comments</comments>
		<pubDate>Fri, 13 Aug 2010 04:09:03 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=120</guid>
		<description><![CDATA[The Trivial DataBase (ccan variant here) uses fcntl locks for consistency: records are chained off a fixed-size hash table (or the free list), and a 1-byte fcntl lock at the offset of the chain head protects all records in that chain. There&#8217;s also a tdb_lockall() function which grabs a lock across all the hash chains [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdb.samba.org/">The Trivial DataBase</a> (<a href="http://ccan.ozlabs.org/info/tdb.html" class="broken_link" >ccan variant here</a>) uses fcntl locks for consistency: records are chained off a fixed-size hash table (or the free list), and a 1-byte fcntl lock at the offset of the chain head protects all records in that chain.</p>
<p>There&#8217;s also a tdb_lockall() function which grabs a lock across all the hash chains at once to let you do arbitrary atomic munging.  This works because fcntl() locks have an offset and length: you can lock arbitrary byte ranges.</p>
<p>Unfortunately, tdb_lockall() is subject to starvation, at least under Linux.  This is because the kernel merely checks whether a lock is available and gets it if it can, rather than queuing behind someone else who wants a superset of the lock.  So single byte lockers come in and out while the whole-file locker waits for them all to go away.</p>
<p>I&#8217;m not sure this is wrong, and as it&#8217;s simpler than the alternative, I&#8217;m not prepared to change it just yet.  Fortunately, there&#8217;s a way of avoiding this starvation in userspace, which occurred independently to both Volker Lendecke and me.  I called this variant tdb_lockall_gradual(), in which we try to lock each chain one at a time so we compete with the single-chain lockers on fair terms.  My first naive thought was to try to lock all the chains one at a time in order, nonblocking, then go back and retry (blocking) any we failed to get.  This is slow, and can deadlock against another process doing the same thing.  Volker&#8217;s suggestion was much nicer: we do a non-blocking lock, and if that fails we divide and conquer.  If we get down to a single record, we do a blocking lock.</p>
<p>I wrote  a test program which fires off N children, each of which grabs a random chain lock for 50-150 milliseconds before sleeping for 1 second, then repeating. The parent waits for a second, then tries to do a tdb_lockall() or tdb_lockall_gradual() depending on the commandline.  Running it five times and showing the average wait time for the lockall gives this:</p>
<p><img src="http://chart.apis.google.com/chart?cht=lc&amp;chs=450x150&amp;chd=t:0,0,1,0,1,1,0,1,0,2,0,2,2,3,4,0,0,4,9,4,6,5,2,5,9,13,2,2,7,5,1,8,5,23,12,23,62,18,96,10,19,13,5,11,20,54,123,77,6,33|0,0,0,0,1,1,2,0,0,3,3,0,3,2,0,0,0,0,2,2,1,5,4,4,2,1,5,7,3,5,5,2,8,1,4,7,2,6,7,6,6,5,6,2,11,5,7,6,8,5&amp;chdl=tdb_lockall|tdb_lockall_gradual&amp;chxr=1,0,5000|0,1,50&amp;chco=FF0000,00FF00&amp;chxt=x,y,x,y&amp;chxl=2:|Processes|3:|ms(avg)&amp;chxp=2,50|3,50" alt="" /></p>
<p>Now, regarding performance.  While there can be 10000 hash chains, this isn&#8217;t as bad as it sounds.   The fast case is the uncontended one, and that&#8217;s as fast as before, and  the contended case is already slow.  I annotated the source to print out how many blocking/nonblocking locks it&#8217;s actually doing.  Inevitably, if there&#8217;s contention, it will end up dividing down to a blocking lock, so log(numchains) locks before doing a blocking lock.</p>
<table border="1">
<tbody>
<tr>
<th>Processes</th>
<th>Blocking locks</th>
<th>Nonblocking locks</th>
<th>Seconds</th>
</tr>
<tr>
<td>5</td>
<td>0-2</td>
<td>1-27</td>
<td>0.03</td>
</tr>
<tr>
<td>50</td>
<td>8-12</td>
<td>93-111</td>
<td>0.20</td>
</tr>
<tr>
<td>500</td>
<td>13-21</td>
<td>130-170</td>
<td>0.29</td>
</tr>
<tr>
<td>5000</td>
<td>309-347</td>
<td>1660-1832</td>
<td>9.1</td>
</tr>
</tbody>
</table>
<p>Sure, that&#8217;s a lot of locking when we&#8217;re competing with 5000 processes, but it&#8217;s less the naive one per chain, and it&#8217;s clear that it&#8217;s not the cause of the slowdown (we&#8217;re doing fewer locks per second than the 5 processes case).</p>
<p>And anyway, locking the entire database cannot be a speed-critical operation.  Indeed, after the evidence here, I followed Volker&#8217;s suggestion to simply replace tdb_lockall() with the new implementation.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=120</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Bob Jenkins and lookup8.c</title>
		<link>http://rusty.ozlabs.org/?p=117</link>
		<comments>http://rusty.ozlabs.org/?p=117#comments</comments>
		<pubDate>Thu, 12 Aug 2010 07:15:14 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=117</guid>
		<description><![CDATA[I pulled Bob Jenkins&#8217; superlative lookup3.c into ccan some time ago, and with the work on TDB2 (aka 64-bit TDB) I wondered if there was a 64-bit variant available.  I didn&#8217;t look hard enough: I should have checked his top-level page and seen lookup8.c before wasting his time with an email :( I did note [...]]]></description>
			<content:encoded><![CDATA[<p>I pulled Bob Jenkins&#8217; superlative lookup3.c into <a href="http://ccan.ozlabs.org/info/hash.html">ccan</a> some time ago, and with the work on <a href="http://lists.samba.org/archive/samba-technical/2010-August/072552.html">TDB2</a> (aka 64-bit TDB) I wondered if there was a 64-bit variant available.  I didn&#8217;t look hard enough: I should have checked his <a href="http://burtleburtle.net/bob/hash/">top-level page</a> and seen lookup8.c before wasting his time with an email :(</p>
<p>I did note in my mail that since lookup3.c can return a <em>pair</em> of 32 bit numbers, I could combine those to get a 64 bit hash &#8220;but I wondered if it was possible to do better&#8230;&#8221;</p>
<p>His one-line reply was that he was working on a 128-bit hash now.  Respectful and informative.</p>
<p>The gold standard test of online manners is how you respond to a dumb  random email.  A truly gracious gentleman/lady will respond as if you  are far smarter far than you appear.  Thanks Bob.  And 128-bit; I&#8217;m a little stunned&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=117</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>On Barriers To Entry</title>
		<link>http://rusty.ozlabs.org/?p=112</link>
		<comments>http://rusty.ozlabs.org/?p=112#comments</comments>
		<pubDate>Sat, 24 Jul 2010 03:00:58 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=112</guid>
		<description><![CDATA[My philosophy for Free/Open Source Software comes down to this: that others can take what I do and do something awesome with it.  Since I don&#8217;t know what you&#8217;ll need, I hand you every capability I have to get you started.  Others granted me that very power to get where I am, so I seek [...]]]></description>
			<content:encoded><![CDATA[<p>My philosophy for Free/Open Source Software comes down to this: that others can take what I do and do something awesome with it.  Since I don&#8217;t know what you&#8217;ll need, I hand you every capability I have to get you started.  Others granted me that very power to get where I am, so I seek to increment that.</p>
<p>It&#8217;s not always simple to do: sometimes you build it, and nobody comes.  My experience is that clear code, convenient install, documentation and useful functionality all help.  An encouraging welcome helps even more, as does getting the software out in front of people. <em> It&#8217;s all about avoiding or lowering barriers.</em></p>
<p>We accept some barriers to modification which are reasonable: if you modify the software, I don&#8217;t have to support it.  If I make you sign a support deal which says I won&#8217;t support the software (even unmodified versions) if you modify or redistribute the software, that&#8217;s not reasonable.  If you get fired for publishing pre-release modified copyleft source code, that&#8217;s reasonable.  If you get fired for publishing post-release, that&#8217;s not.</p>
<p>The hardware and electricity costs are barriers, but they&#8217;re undiscriminating and reasonable, so we accept them. Even the GPL explicitly allows you to charge for costs to make a copy. The software cost of the system is also explicitly allowed as a barrier.  The software costs of the build environment are also accepted barriers (though historic for most of us): again even the GPL doesn&#8217;t require your software to be buildable with freely available tools.</p>
<p>As this shows, your choice of licensing is among your arsenal in keeping barriers low for co-hackers (who are not  necessarily contributors!).  I believe  copyright gives too much power to the copyright holder, but as copyright is  so hard to unmake, I favor the GPL.  It tries to use legal power to meet  the aims in the first paragraph: to force you to hand onwards all the  pieces I handed to you.  It&#8217;s also well understood by people and that  common understanding gels a community.</p>
<p>Yet, as I alluded at the top, there are a realm of barriers which licenses don&#8217;t even try to address: the code could be an unmodifiable tangle, the documentation awful, the installation awkward, or the trademarks invasive. A license can&#8217;t make coders  welcome newcomers, be friendly to upstream, responsive to bugs, write useful code or speak english.</p>
<p>The spectrum of barriers goes roughly from &#8220;that&#8217;s cool&#8221; through &#8220;I&#8217;m not so comfortable with that&#8221; to &#8220;that&#8217;s not Free/Open Source&#8221;.  It&#8217;s entirely up to <strong>your</strong> definition of reasonableness;  only in the simplest cases will that be the same point at which the license is violated, even if that license is explicitly drafted to defend that freeness!</p>
<p>So, don&#8217;t start with an analysis of license clauses.  Start with &#8220;is that OK?&#8221;.  Is there a fundamental or only a cosmetic problem?   If it&#8217;s not OK, ask &#8220;does it matter?&#8221;.  Is it effecting many people, is it setting a bad example, is it harming the project&#8217;s future, is it causing consternation among existing developers?   If it is, <strong>then</strong> it&#8217;s time to look at the license to see if you can do anything.  Remember that the license is merely a piece of text.  It can&#8217;t stop anything, it can only give you leverage to do so.  It certainly can&#8217;t make using the law easy or convenient, or even worthwhile pursuing.</p>
<p>To close, I will leave the last word to <a href="http://en.wikipedia.org/wiki/Kimberlee_Weatherall">Kim Weatherall</a>, who once told me: &#8220;if you&#8217;re spending your time on legal issues, you&#8217;re doing it wrong&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=112</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Superfreakonomics; Superplug for Intellectual Ventures.</title>
		<link>http://rusty.ozlabs.org/?p=110</link>
		<comments>http://rusty.ozlabs.org/?p=110#comments</comments>
		<pubDate>Wed, 07 Jul 2010 10:52:14 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=110</guid>
		<description><![CDATA[I enjoyed Levitt &#38; Dubner&#8217;s &#8220;Freakonomics&#8221;, and picked up the followup &#8220;Superfreakonomis&#8221; recently at an airport.  The last chapter, however, was astonishing.  The entire chapter was devoted to a glowing advertisement for Intellectual Ventures, pointing out that they own 20,000 patents &#8220;more than all but a few dozen companies in the world&#8221;, but of course [...]]]></description>
			<content:encoded><![CDATA[<p>I enjoyed Levitt &amp; Dubner&#8217;s &#8220;Freakonomics&#8221;, and picked up the followup &#8220;Superfreakonomis&#8221; recently at an airport.  The last chapter, however, was astonishing.  The entire chapter was devoted to a glowing advertisement for Intellectual Ventures, pointing out that they own 20,000 patents &#8220;more than all but a few dozen companies in the world&#8221;, but of course &#8220;there is little hard evidence&#8221; that they are patent trolls.</p>
<p>But this bunch of wacky genius billionaires have solved global warming (much of which they dispute anyway) and can control malaria and prevent hurricanes from forming.  Unlike the rest of the book which covers analysis of well-known facts and disputes them with insightful economic research, this chapter is so breathless and gushy that it makes me question the rest of the author&#8217;s work.</p>
<p>I first came across Intellectual Ventures when The Economist reversed their 100-year opposition to patents, and the only reason I could find was a similarly cheerleading piece about this company.  (I had naively expected new research revealing some net positive of patents, or some such revelation).</p>
<p>Side note: when a respected information source covers something where you have on-the-ground experience, the result is often to make you wonder how much fecal matter you&#8217;ve swallowed in areas outside your own expertise.</p>
<p>So, what is IV actually doing?  Buying up loads of patents and licensing them to companies who calculate it&#8217;s not worth the fight is patent trolling 101.  Yet the scale they&#8217;re operating on puts them on new ground, and opens new opportunities.  It seems obvious to get corporate investors on board by promising them immunity from  patent claims.  With enough patents you stop trying to license them one-by-one and just tax each industry at some non-negotiable rate.  No doubt they have more tricks I haven&#8217;t even thought of, but these potential devices really do make them a new breed of Super Trolls.</p>
<p>Their efforts to actually attain their own patents could simply be more of the same, but it&#8217;s also a relatively cheap but clever PR exercise (as shown by their media treatment).  This will help them when (legislative?) efforts are made to shut down patent trolls.  I&#8217;m fairly confident that they&#8217;ll simply license rather than implement anything themselves; actually producing things requires much more work, and simply exposes you to others&#8217; patents.</p>
<p>Without diving deeply into this, they seem to understand two things clearly:</p>
<ol>
<li>They learnt from Microsoft that government-enforced monopolies are worth billions.  Microsoft had copyright on software, this is patents.</li>
<li>Development is getting much cheaper, while patents are getting more valuable.   Cheaper development is shown clearly by free software, open hardware and hackerspaces.  Patent value increases as more of the world becomes a more profitable and enforceable patent target.</li>
</ol>
<p>Now, I don&#8217;t really care if one company leeches off the others.  But if they want to tax software, they have to attack free software otherwise people will switch to avoid their patent licensing costs.  And if you don&#8217;t believe some useful pieces of free software could be effectively banned due to patent violations, you don&#8217;t think on the same scale as these guys.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=110</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>LWN Quotes Of The Week</title>
		<link>http://rusty.ozlabs.org/?p=105</link>
		<comments>http://rusty.ozlabs.org/?p=105#comments</comments>
		<pubDate>Tue, 08 Jun 2010 05:01:38 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=105</guid>
		<description><![CDATA[I have been petitioning Jon Corbet to introduce a &#8220;Supporter&#8221; level subscription to LWN; I think given his failure to keep up with inflation and my need to experience conferences vicariously I feel deeply indebted to them. That lead to me looking through LWN Quote of The Week; there&#8217;s no neat index of these things.  [...]]]></description>
			<content:encoded><![CDATA[<p>I have been petitioning Jon Corbet to introduce a &#8220;Supporter&#8221; level subscription to LWN; I think given his failure to keep up with inflation and my need to experience conferences vicariously I feel deeply indebted to them.</p>
<p>That lead to me looking through LWN Quote of The Week; there&#8217;s no neat index of these things.  And I&#8217;m not going to create one, but I did troll for my old quotes while procrastinating, and here&#8217;s my vanity list:</p>
<ol>
<li><a href="http://lwn.net/Articles/67163/">January 21, 2004</a></li>
<li><a href="http://lwn.net/Articles/226007/">March 14, 2007</a></li>
<li><a href="http://lwn.net/Articles/228207/">March 28, 2007</a></li>
<li><a href="http://lwn.net/Articles/271835/">March 5, 2008</a></li>
<li><a href="http://lwn.net/Articles/281248/">May 7, 2008</a></li>
<li><a href="http://lwn.net/Articles/310569/">December 10, 2008</a></li>
<li><a href="http://lwn.net/Articles/316655/">January 28, 2009</a></li>
<li><a href="http://lwn.net/Articles/318737/">February 11, 2009</a></li>
<li><a href="http://lwn.net/Articles/328685/">April 22, 2009</a></li>
<li><a href="http://lwn.net/Articles/389390/">May 26, 2010</a></li>
</ol>
<p>From the comments, it looks like I got the very first one.  Wow.  I&#8217;m sure there are missing ones (I was sure I got two weeks in a row once).</p>
<p>I&#8217;m behind quota for 2010 though; I was surprised my recent fight with Linus didn&#8217;t get in.  I&#8217;ll try harder&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=105</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Typesafe callbacks in C (and gcc)</title>
		<link>http://rusty.ozlabs.org/?p=101</link>
		<comments>http://rusty.ozlabs.org/?p=101#comments</comments>
		<pubDate>Mon, 24 May 2010 02:28:28 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=101</guid>
		<description><![CDATA[A classic pattern in C is to hand a generic callback function around which takes a &#8220;void *priv&#8221; pointer so the function can take arbitrary state (side note: a classic anti-pattern is not to do this, resulting in qsort being reimplemented in Samba so one can be provided!). The problem with this pattern is that [...]]]></description>
			<content:encoded><![CDATA[<p>A classic pattern in C is to hand a generic callback function around which takes a &#8220;void *priv&#8221; pointer so the function can take arbitrary state (side note: a classic anti-pattern is not to do this, resulting in qsort being reimplemented in Samba so one can be provided!).</p>
<p>The problem with this pattern is that it breaks type safety completely, such as in the following example:<br />
<code><br />
int register_callback(void (*callback)(void *priv), void *priv);<br />
static void my_callback(void *_obj)<br />
{<br />
        struct obj *obj = _obj;<br />
        ...<br />
}<br />
...<br />
		register_callback(my_callback, &#038;my_obj);<br />
</code></p>
<p>If I change the type of my_obj, there&#8217;s no compiler warning that I&#8217;m now handing my callback something it doesn&#8217;t expect.</p>
<p>Some time ago, after such a change bit me, I proposed a patch to lkml to rectify this, using a typesafe callback mechanism.  It was a significant change, and the kernel tends to be lukewarm on safety issues so it went nowhere.  But these thoughts did evolve into CCAN&#8217;s <a href="http://ccan.ozlabs.org/info/typesafe_cb.html">typesafe_cb</a> module.</p>
<h3> The tricksiness&#8230; </h3>
<p>More recently, I tried to use it in libctdb (the new async ctdb library I&#8217;ve been toying with), and discovered a fatal flaw.  To understand the problem, you have to dive into how I implemented typesafe_cb.  At its base is a conditional cast macro: cast_if_type(desttype, expr, oktype).  If expr is of type &#8220;oktype&#8221;, cast it to &#8220;desttype&#8221;.  On compilers which don&#8217;t support the fancy gcc builtins needed to do this, this just becomes an unconditional cast &#8220;(desttype)(expr)&#8221;.  This allows us to do the following:<br />
<code><br />
    #define register_callback(func, priv) \<br />
        _register_callback(cast_if_type(void (*)(void *), (func), void (*)(typeof(priv)))<br />
</code></p>
<p>This says that we cast the func to the generic function type only if it exactly matches the private argument.  The real typesafe_cb macro is more complex than this because it needs to ensure that priv is a pointer, but you get the idea.</p>
<p>Now, one great trick is that the callback function can take a &#8220;const&#8221; (or volatile) pointer of the priv type, and we let that work as well: we have a &#8220;cast_if_any&#8221; which extends &#8220;cast_if_type&#8221; to any of three types:<br />
<code><br />
#define typesafe_cb(rtype, fn, arg)			\<br />
	cast_if_any(rtype (*)(void *), (fn),		\<br />
		    rtype (*)(typeof(*arg)*),		\<br />
		    rtype (*)(const typeof(*arg)*),	\<br />
		    rtype (*)(volatile typeof(*arg)*))<br />
</code></p>
<h3>The flaw&#8230; </h3>
<p>If your private arg is an undefined type, typeof (*arg) won&#8217;t work, and you need this to declare a const pointer to the same type.  I have <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44257">just filed a bug report</a>, but meanwhile, I need a solution.</p>
<h3>The workarounds&#8230;</h3>
<p>Rather than use cast_if_any, you can insert an explicit call to the callback to evoke a warning if the private arg doesn&#8217;t match, then just cast the callback function.  This is in fact what I now do, with an additional test that the return type of the function exactly matches the expected return type.  cast_if_type() now takes an extra argument, which is the type to test:</p>
<p><code><br />
#define typesafe_cb(rtype, fn, arg)			\<br />
	cast_if_type(rtype (*)(void *), (fn), (fn)(arg), rtype)<br />
</code></p>
<p>cast_if_type does a typeof() on (fn)(arg), which will cause a warning if the arg doesn&#8217;t match the function, and the cast_if_type will only cast (fn) if the return type matches rtype.  You can&#8217;t test the return type using a normal test (eg. &#8220;rtype _test; sizeof(test = fn(arg));&#8221;) because implicit integer promotion makes this compile without a warning even if fn() returns a different integer type.</p>
<p>Unfortunately, the more general typesafe_cb_preargs() and typesafe_cb_postargs() macros lose out.  These are like typesafe_cb but for callbacks which take extra arguments (the more common case). </p>
<p><code><br />
 /* This doesn't work: arg might be ptr to undefined struct. */<br />
 #define typesafe_cb_preargs(rtype, fn, arg, ...)			\<br />
	cast_if_any(rtype (*)(__VA_ARGS__, void *), (fn),		\<br />
		    rtype (*)(__VA_ARGS__, typeof(arg)),		\<br />
		    rtype (*)(__VA_ARGS__, const typeof(*arg) *),	\<br />
		    rtype (*)(__VA_ARGS__, volatile typeof(*arg) *))<br />
</code></p>
<p>We can&#8217;t rely on testing an indirect call: we&#8217;d need example parameters to pass, and because they&#8217;d be promoted.  The direct call might work fine but an indirect call via a different function signature fail spectacularly.  We&#8217;re supposed to increase type safety, not reduce it!</p>
<p>We could force the caller to specify the type of the priv arg, eg. &#8220;register_callback(func, struct foo *, priv)&#8221;.  But this strikes me as placing the burden in the wrong place, for an issue I hope will be resolved soonish.  So for the moment, you can&#8217;t use const or volatile on callback functions:</p>
<p><code><br />
 /* This doesn't work: arg might be ptr to undefined struct. */<br />
 #define typesafe_cb_preargs(rtype, fn, arg, ...)			\<br />
	cast_if_type(rtype (*)(__VA_ARGS__, void *), (fn), (fn),		\<br />
		    rtype (*)(__VA_ARGS__, typeof(arg)))<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=101</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>More Realistic Hashing: Cache Sensitivity Part II</title>
		<link>http://rusty.ozlabs.org/?p=94</link>
		<comments>http://rusty.ozlabs.org/?p=94#comments</comments>
		<pubDate>Thu, 22 Apr 2010 12:41:52 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=94</guid>
		<description><![CDATA[So my previous post showed a trick with stuffing extra bits into the pointers of a simple hash table.  In most real situations, we want the hash to still be useful as the number of elements increases: the simple hash I used will slow down dramatically as we pass 75% utilization.  In addition, we want [...]]]></description>
			<content:encoded><![CDATA[<p>So my <a title="Hash Tables: In A Cache-Sensitive World? " href="http://rusty.ozlabs.org/?p=89">previous post</a> showed a trick with stuffing extra bits into the pointers of a simple hash table.  In most real situations, we want the hash to still be useful as the number of elements increases: the simple hash I used will slow down dramatically as we pass 75% utilization.  In addition, we want to be able to delete entries, which can be slightly painful in a linear hash.</p>
<p>Since then, I&#8217;ve been trying a few different approaches: in fact, I spent quite a while down this rabbit hole before digging myself out.  Here are the approaches I benchmarked (on a 64-bit system):</p>
<ol>
<li><strong>Doubling</strong>: Linear hash with extra hash bits in the pointers, doubling and rehashing everything when it hits &gt; 5/8 full.</li>
<li><strong>Cacheline Tree</strong>: Divide the hash into 128-byte groups.  Do linear collision resolution within each group, and when a group fills explode it into 16 pointers to separate hash tables of N 128-byte groups.  When that fills, explode again, etc.  In practice, N was 2.</li>
<li><strong>Cacheline Tree Then Linked</strong>:  Explode the top level like the above, but allocate a single cacheline (N=1) for the second level and just fill the second level from first bucket onwards.  If that fills, simply chain on another cacheline.  This actually freed up on delete as chains were emptied.</li>
<li><strong>Cacheline Linked</strong>: Even simpler: when the toplevel cacheline fills, just chain another cacheline off it.  Each cacheline is simply filled in order, but we only put 15 pointers in each cacheline and use the extra 4 bits per entry for additional hash bits (to reduce comparisons).  This also freed them up on delete.</li>
<li><strong>Chaining</strong>: Double linked list through each object: when a bucket fills we simply append the new entry to the existing ones.</li>
</ol>
<p>Then I benchmarked a 2M-bucket (actually 2097152) hashtable of each type, increasing the number of entries by a factor of 2 at a time from 1M.  The good thing about visiting the Canberra office is I could use one of the  older Power machines here with gobs of memory.</p>
<p>The first three tests were very similar to the last post, except I used an array of scrambled pointers so I wasn&#8217;t accessing the objects in memory order.  The last two are new:</p>
<ol>
<li>Insert all the objects into the hash.</li>
<li>Find all the objects in the hash.</li>
<li>Do the same number of missed searches in the hash.</li>
<li>Delete half the objects, then time reinserting them (steady-state test which avoids any allocation penalties for expansion).</li>
<li>Delete every object from the hash.</li>
</ol>
<h2>Insert</h2>
<p><img src="http://chart.apis.google.com/chart?cht=lc&amp;chs=400x150&amp;chd=s:IOSVZdgi,GQWVWYjt,ISYYaeo9,KNSd0___,HIJLOQRS&amp;chxt=x&amp;chxl=0:|1|2|4|8|16|32|64|128M&amp;chco=0000ff,9090af,ff808f,ffb04f,00ff00&amp;chdl=Doubling|Cacheline+Tree|CLT+Then+Linked|CL+Linked|Chained&amp;chtt=Insertion+Time+Per+Entry" alt="" /></p>
<p>Our simple link of cachelines (CLT Linked) gets so slow I took it out of the benchmark after 8x overload.  Chained is the winner: we expect it to modify the inserted entry, the hash bucket and the current top entry for a total of three cache misses (and the object being inserted would generally be hot).  It also never needs to (re)alloc or rehash.</p>
<p>We can see the CLT-then-linked case is getting worse as we fall into the chain and have to linear search for the entry to place into; there are 16 times as many of these chains as in the dumb &#8220;link of cache lines&#8221; case, because we have a link off each pointer off each toplevel hash entry, rather than one off each cacheline.</p>
<p>If we look at reinserts, we can remove the realloc and rehash overhead:</p>
<p><img src="http://chart.apis.google.com/chart?cht=lc&amp;chs=400x150&amp;chd=s:HKMNPSTU,FLPQSUaj,HOTUWbm9,ILSe3___,GHIKMOPQ&amp;chxt=x&amp;chxl=0:|1|2|4|8|16|32|64|128M&amp;chco=0000ff,9090af,ff808f,ffb04f,00ff00&amp;chdl=Doubling|Cacheline+Tree|CLT+Then+Linked|CL+Linked|Chained&amp;chtt=Reinsertion+Time+Per+Entry" alt="" /></p>
<p>In steady-state we can see the others are more competitive, though even our flat linear hash loses a little as it scans for the next NULL bucket.<br />
<a name="memory-usage"></p>
<h2>Memory Usage</h2>
<p></a><br />
<img src="http://chart.apis.google.com/chart?cht=lc&amp;chs=400x150&amp;chd=s:HHHHHHHH,H39ePI39,HdfPHFEE,HFEEE___,OLJIHHHH&amp;chxt=x,y&amp;chxl=0:|1|2|4|8|16|32|64|128M|1:|0+bytes|131+bytes&amp;chco=0000ff,9090af,ff808f,ffb04f,00ff00&amp;chdl=Doubling|Cacheline+Tree|CLT+Then+Linked|CL+Linked|Chained&amp;chtt=Memory+Overhead+Per+Entry" alt="" /></p>
<p>The optimal reasonable case would be one pointer per object; 8 bytes.  The two linked cases quickly approach this (at which point they suck).  The chaining cases uses two pointers; doubling uses 2 pointers for these values too (it can do slightly better just before it doubles, and worse just afterwards).</p>
<p>The real story is the cacheline tree.  It hits a tipping point as buckets fill: that 512-byte second level off each top level pointer means we can spend 131 bytes per object just after we fill the top level.  At 8 million objects in our 1 million buckets we are in fact spending 131 bytes per object (vs 17 for the chained case).</p>
<p>This is why I reduced the second level hash size to two cachelines; and we still get that factor of 16 explosion on each expansion.  In fact, the chaining hashes were an attempt to find a &#8220;good enough&#8221; variant which didn&#8217;t explode like this.  The chaining variant (CLT then linked) explodes once, to 65 bytes per entry, but then expands linearly.</p>
<h2>Lookups</h2>
<p><img src="http://chart.apis.google.com/chart?cht=lc&amp;chs=400x150&amp;chd=s:BBCCCDDD,BCDDDEFG,BCDEFGIO,BCDEI___,CCDEIPd9&amp;chxt=x&amp;chxl=0:|1|2|4|8|16|32|64|128M&amp;chco=0000ff,9090af,ff808f,ffb04f,00ff00&amp;chdl=Doubling|Cacheline+Tree|CLT+Then+Linked|CL+Linked|Chained&amp;chtt=Time+Per+Successful+Lookup" alt="" /></p>
<p><img src="http://chart.apis.google.com/chart?cht=lc&amp;chs=400x150&amp;chd=s:FCCFGGCC,DEDCCDDD,EFIIHLKZ,HINQc___,JCMGJac9&amp;chxt=x&amp;chxl=0:|1|2|4|8|16|32|64|128M&amp;chco=0000ff,9090af,ff808f,ffb04f,00ff00&amp;chdl=Doubling|Cacheline+Tree|CLT+Then+Linked|CL+Linked|Chained&amp;chtt=Time+Per+Missed+Lookup" alt="" /></p>
<p>This is where the cache damage of chaining becomes apparent.  Doubling performs best, and the tree is close behind.  Even a linked list of cachelines beats chaining: with 15 entries per cacheline on average 13 of those will not need to be examined (since the lower pointer bits where we&#8217;ve stashed another 3 hash bits will only accidentally match for two of them).  This means 1/5 of the cache misses of the chained case for really large overload values.</p>
<p>By 64 entries per bucket (128M objects) chaining is 16 times slower than doubling for a successful lookup, and 20 times slower for an unsuccessful one.  Even at 8 per bucket, it matches our terrible chained case at being 3 times slower than the linear case.</p>
<p>Since I assume most hashes are lookup heavy, this result should be weighted more than add or delete.</p>
<h2>Delete</h2>
<p><img src="http://chart.apis.google.com/chart?cht=lc&amp;chs=400x150&amp;chd=s:KORSVZac,KUUVYenn,KVVWZgq9,INTdw___,CDDEHKLM&amp;chxt=x&amp;chxl=0:|1|2|4|8|16|32|64|128M&amp;chco=0000ff,9090af,ff808f,ffb04f,00ff00&amp;chdl=Doubling|Cacheline+Tree|CLT+Then+Linked|CL+Linked|Chained&amp;chtt=Time+Per+Delete" alt="" /></p>
<p>Chained delete is cheap: you might get three cache misses (one for the object you&#8217;re deleting, and one for the next and prev objects in the linked list) but you don&#8217;t need to do a hash lookup at all.  The linear hash has a cache miss to cache the object, then a cache miss to do the delete, but then it has to rehash any objects in immediately following hash buckets.  It&#8217;s 2.2 times slower at 64x overload.  We could use a special value to avoid this.</p>
<p>Cacheline tree does OK, but still needs to hash and similarly reseat any &#8220;runs&#8221; within the bottom cacheline.  At three levels, add cache misses for the second level and third levels.  3.1 times slower than chained at 64x overload.</p>
<h2>Conclusion</h2>
<p>I&#8217;d love to spend more time refining these results.  In particular, there are ways to steal more bits to store extra hashing, ways to avoid reseating entries on linear deletes, ways to avoid rehashing to double the linear case.  Compression of pointers is also possible, but it gets messy since there are a no longer a fixed number of entries per cacheline.  I might get time for some of this, but at some point you have to get on with less abstract work!</p>
<p>But the takeaway is this: it&#8217;s hard to beat the simplicity of a big hash array which doubles and stashes a few extra hash bits.  If your workload is add/delete heavy, use chaining.  If you are worried about unknown work sizes, use doubling.  Or do what Perl does, and do both (though you can&#8217;t use the extra hash bit stowing with chaining).</p>
<p>The cache tree idea is not best at anything, unless you can&#8217;t double for some reason (the Linux kernel probably has this issue, and TDB may or may not).<span id="more-94"></span></p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=94</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Hash Tables: In A Cache-Sensitive World? (FIXED)</title>
		<link>http://rusty.ozlabs.org/?p=89</link>
		<comments>http://rusty.ozlabs.org/?p=89#comments</comments>
		<pubDate>Mon, 12 Apr 2010 12:57:47 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=89</guid>
		<description><![CDATA[(FIXED: my &#8220;NoMatched&#8221; bench was bogus, and actually the same as &#8220;Matched&#8221; case. Graphs changed, but conclusions the same.) Everyone loves hash tables; certainly the networking code in the kernel uses them heavily and I do too.  But with more work on TDB (which is basically a hash table in a file), I&#8217;ve been re-measuring [...]]]></description>
			<content:encoded><![CDATA[<p><strong>(FIXED: my &#8220;NoMatched&#8221; bench was bogus, and actually the same as &#8220;Matched&#8221; case.  Graphs changed, but conclusions the same.)</strong><br />
Everyone loves hash tables; certainly the networking code in the kernel uses them heavily and I do too.  But with more work on TDB (which is basically a hash table in a file), I&#8217;ve been re-measuring some of the fundamentals.</p>
<p>We all know that hash tables are cache-unfriendly; a good hash table means you&#8217;re hitting a &#8220;random&#8221; bucket every time.   Back in my university days this was never mentioned (caches were new and fancy things); the optimal hash table was seen as a prime-numbered sequence of buckets using a primary hash then a secondary hash to jump to the next bucket if this was full.  This gives fewer lookups than a naive linear search &#8220;if this bucket is full, go to the next one&#8221;, but does this override the cache unfriendliness of the approach?</p>
<p>These days it&#8217;s normal to use a fast <a title="Bob Jenkins' lookup3 hash" href="http://burtleburtle.net/bob/c/lookup3.c">universal hash</a> and a power-of-two for the hash table size (Perl 5 and the Linux kernel do this, though Perl uses another weaker hash also by Jenkins).  Also, we deal with hash collisions by chaining off entries rather than using other hash buckets.  This has two main advantages: (1) it doesn&#8217;t barf when the hash table fills up, and (2) you can easily delete an entry from the hash table.  Unfortunately, this is pretty cache-unfriendly too, compared to a linear bucket fallback, but can we measure it?</p>
<p>To this end, I wrote a <a title="Hashbench example C source" href="http://ozlabs.org/~rusty/hashbench.c">simple example program</a> which filled each kind of hash table (linear hash bucket, secondary hash bucket and chained hash buckets) to 50%, then ran successful lookups, then ran failed lookups.  64 bit machine, and I chose 2^27 as my hash size giving a 1G hash table.  While most hashes are not this large, it&#8217;s useful to approximate a situation where other things are also using the cache.</p>
<p><img src="http://chart.apis.google.com/chart?cht=bvg&amp;chs=450x150&amp;chd=s:m9H,u8H,kzH&amp;chxt=x,y&amp;chxl=0:|Insert|Match|NoMatch|1:|Time&amp;chco=4D89F9,80A7FA,C6D9FD&amp;chdl=Linear|Secondary|Chained&amp;chtt=Performance+of+1-GB+50%-used+Hash+Table" alt="" /></p>
<p>This result surprised me, so I fiddled a bit and the basic shape remained; the differences vanished if the table was (say) only 10% full, but even at 25% we see chaining win.  Here it&#8217;s about 15% faster on matched lookups (5% faster on misses).</p>
<p>What does this mean? It looks like linear edges over secondary for insertion, but for lookup it&#8217;s a wash.  But both are overshadowed by chaining, which doesn&#8217;t penalize other buckets when there&#8217;s a hash clash.  Despite the fact that objects are one pointer larger in the chaining case, it still wins (the test code uses two 64-bit values as the basic object).</p>
<h2>But Now For The Twist&#8230;</h2>
<p>The reason I was looking at old-school non-chained hashing schemes was because I have a new trick for them: stashing some hash bits in the bottom bits of the pointer.  This allows you to skip the dereference 7/8 times (assuming 64-bit-aligned pointers).</p>
<p>So, we add that trick to the linear case:<br />
<img src="http://chart.apis.google.com/chart?cht=bvg&amp;chs=450x150&amp;chd=s:m9H,u8H,kzH,mtF&amp;chxt=x,y&amp;chxl=0:|Insert|Match|NoMatch|1:|Time&amp;chco=4D89F9,80A7FA,C6D9FD,C63030&amp;chdl=Linear|Secondary|Chained|Bitsteal&amp;chtt=Performance+of+1-GB+50%-used+Hash+Table" alt="" /></p>
<p>Now we can see the potential of not chaining through hash entries!  It&#8217;s a full 25% faster than the normal linear case, and 10% faster than chaining (almost 20% faster in the missed case).  Of course, for real life we need to handle delete and hash table filling.  And that&#8217;s the subject of my next post, once I&#8217;ve finished coding it!</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=89</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Linux Users of Victoria: Tuesday 6th April</title>
		<link>http://rusty.ozlabs.org/?p=87</link>
		<comments>http://rusty.ozlabs.org/?p=87#comments</comments>
		<pubDate>Mon, 29 Mar 2010 10:57:16 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=87</guid>
		<description><![CDATA[Several months ago Donna Benjamin convinced me to speak at LUV, and now the time is approaching.  My intent is to give a talk about bits and pieces, and rely on questions to see what the audience is interested in.  Pretty casual and should be heaps of fun if you&#8217;re nearby. I will also be [...]]]></description>
			<content:encoded><![CDATA[<p>Several months ago <a title="Donna's Homepage" href="http://kattekrab.net/">Donna Benjamin</a> convinced me to speak at LUV, and now the <a title="Linux Users of Victoria April" href="http://wiki.luv.asn.au/Main_Page#April">time is approaching</a>.  My intent is to give a talk about bits and pieces, and rely on questions to see what the audience is interested in.  Pretty casual and should be heaps of fun if you&#8217;re nearby.</p>
<p>I will also be taking the chance to drop by Lonely Planet; one of the places we stayed in Lithuania had seen an influx of foreign tourists since being featured in their guide, so they forced a note and a bottle of their vodka on us to take to LP.  Naturally, we Australians all know each other, so I couldn&#8217;t turn them down :)</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=87</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rusty&#8217;s Travels</title>
		<link>http://rusty.ozlabs.org/?p=85</link>
		<comments>http://rusty.ozlabs.org/?p=85#comments</comments>
		<pubDate>Sat, 20 Feb 2010 07:02:20 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Self]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=85</guid>
		<description><![CDATA[Headed through Germany 26th through 3rd March or so, then Lithuania via Poland.  Back via Singapore on 24/25 March. My email will be intermittent (I hope!) but if you&#8217;re around and want to grab a meal or a beer with us, ping me!]]></description>
			<content:encoded><![CDATA[<p>Headed through Germany 26th through 3rd March or so, then Lithuania via Poland.  Back via Singapore on 24/25 March.</p>
<p>My email will be intermittent (I hope!) but if you&#8217;re around and want to grab a meal or a beer with us, ping me!</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=85</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Followup: lrzip</title>
		<link>http://rusty.ozlabs.org/?p=81</link>
		<comments>http://rusty.ozlabs.org/?p=81#comments</comments>
		<pubDate>Tue, 16 Feb 2010 01:21:58 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=81</guid>
		<description><![CDATA[Mikael﻿ noted in my previous post that Con Kolivas&#8217;s lrzip is another interesting compressor.  In fact, Con has already done a simple 64-bit enhance of rzip for lrzip, and on our example file it gets 56M vs 55M for xz (lrzip in raw mode, followed by xz, gives 100k worse than just using lrzip: lrzip [...]]]></description>
			<content:encoded><![CDATA[<p><em>Mikael</em>﻿ <a href="http://rusty.ozlabs.org/?p=75#comment-163">noted</a> in my <a href="http://rusty.ozlabs.org/?p=75">previous post</a> that Con Kolivas&#8217;s <a href="http://ck.kolivas.org/apps/lrzip/">lrzip</a> is another interesting compressor.  In fact, Con has already done a simple 64-bit enhance of rzip for lrzip, and on our example file it gets 56M vs 55M for xz (lrzip in raw mode, followed by xz, gives 100k worse than just using lrzip: lrzip already uses lzma).</p>
<p>Assuming no bugs in rzip, the takeaway here is simple: rzip should not attempt to find matches within the range that the backend compressor (900k for bzip2 in rzip, 32k for gzip, megabytes for LZMA as used by lrzip).  The backend compressor will do a better job (as shown by similar results with lrzip when I increase the hash array size so it finds more matches: the resulting file is larger).</p>
<p>The rzip algorithm is good at finding matches over huge distances, and that is what it should stick to.  Huge here == size of file (rzip does not stream, for this reason).  And this implies only worrying about large matches over huge distances (the current 32 byte minimum is probably too small).  The current version of rzip uses an mmap window so it never has to seek, but this window is artificially limited to 900MB (or 60% of mem in lrzip).   If we carefully limit the number of comparisons with previous parts of the file, we may be able to reduce them to the point where we don&#8217;t confuse the readahead algorithms and thus get nice performance (fadvise may help here too) whether we are mmaped or seeking.</p>
<p>I like the idea that rzip should scale with the size of the file being compressed, not make assumptions about today&#8217;s memory sizes.  Though some kind of thrash detection using mincore might be necessary to avoid killing our dumb mm systems :(</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=81</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>xz vs rzip</title>
		<link>http://rusty.ozlabs.org/?p=75</link>
		<comments>http://rusty.ozlabs.org/?p=75#comments</comments>
		<pubDate>Mon, 15 Feb 2010 07:56:10 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=75</guid>
		<description><![CDATA[As the kernel archive debates replacing .bz2 files with .xz, I took a brief glance at xz. My test was to take a tarball of the linux kernel source (made from a recent git tree, but excluding the .git directory): linux.2.6.tar 395M For a comparison, bzip2 -9, rzip -9 (which uses bzip2 after finding distant [...]]]></description>
			<content:encoded><![CDATA[<p>As the kernel archive debates replacing .bz2 files with .xz, I took a brief glance at <a href="http://en.wikipedia.org/wiki/Xz">xz</a>.  My test was to take a tarball of the linux kernel source (made from a recent git tree, but excluding the .git directory):</p>
<pre>     linux.2.6.tar 395M</pre>
<p>For a comparison, bzip2 -9, rzip -9 (which uses bzip2 after finding distant matches), and xz:</p>
<pre>     linux.2.6.tar.bz2 67M
     linux.2.6.tar.rz 65M
     linux.2.6.tar.xz 55M</pre>
<p>So, I hacked rzip with a -R option to output non-bzip&#8217;d blocks:</p>
<pre>     linux.2.6.tar.rawrz 269M</pre>
<p>Xz on this file simulates what would happen if rzip used xz instead of libbz2:</p>
<pre>     linux.2.5.tar.rawrz.xz 57M</pre>
<p>Hmm, it makes xz worse!  OK, what if we rev up the conservative rzip to use 1G of memory rather than 128M max?  And the xz that?</p>
<pre>     linux.2.6.tar.rawrz 220M
     linux.2.6.tar.rawrz.xz 58M</pre>
<p>It actually gets worse as rzip does more work, implying xz is finding quite long-distance matches (bzip2 won&#8217;t find matches over more than 900k).  So, rzip could only have benefit over xz on really huge files: but note that current rzip is limited on filesize to 4G so it&#8217;s a pretty small useful window.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=75</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Code review: libreplace</title>
		<link>http://rusty.ozlabs.org/?p=61</link>
		<comments>http://rusty.ozlabs.org/?p=61#comments</comments>
		<pubDate>Fri, 12 Feb 2010 08:53:28 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=61</guid>
		<description><![CDATA[libreplace is the SAMBA library (also used in ctdb) to provide working implementations of various standard(ish) functions on platforms where they are missing or flawed.  It was initially created in 1996 by Andrew Tridgell based on various existing replacement hacks in utils.c (see commit 3ee9d454). The basic format of replace.h is: #ifndef HAVE_STRDUP #define strdup [...]]]></description>
			<content:encoded><![CDATA[<p>libreplace is the SAMBA library (also used in ctdb) to provide working implementations of various standard(ish) functions on platforms where they are missing or flawed.  It was initially created in 1996 by Andrew Tridgell based on various existing replacement hacks in utils.c (see commit <a title="Samba replace.c initial commit" href="http://gitweb.samba.org/?p=samba.git;a=commit;h=3ee9d454">3ee9d454</a>).</p>
<p>The basic format of replace.h is:</p>
<pre>    #ifndef HAVE_STRDUP
    #define strdup rep_strdup
    char *rep_strdup(const char *s);
    #endif</pre>
<p>If configure fails to identify the given function X, rep_X is used in its place.  replace.h has some such declarations, but most have migrated to the system/ include directory which has loosely grouped functions by categories such as <tt>dir.h</tt>, <tt>select.h</tt>, <tt>time.h</tt>, etc.  This works around the &#8220;which header(s) do I include&#8221; problem as well as guaranteeing specific functions.</p>
<p>Other than reading this code for a sense of Unix-like paleontology (and it&#8217;s so hard to tell when to remove any of these helpers that cleanups are rare) we can group replacements into three categories:</p>
<ol>
<li>Helper functions or definitions which are missing, eg. <tt>strdup</tt> or <tt>S_IRWXU</tt>.</li>
<li>&#8220;Works for me&#8221; hacks for platform limitations, which make things compile but are not general, and</li>
<li>Outright extensions, such as <tt>#define ZERO_STRUCT(x) memset((char *)&amp;(x), 0, sizeof(x))</tt> or Linux kernel inspired <tt>likely()</tt></li>
</ol>
<p>Since it&#8217;s autoconf-based, it uses the standard <tt>#ifdef</tt> instead of <tt>#if</tt> (a potential source of bugs, as I&#8217;ve <a title="#ifdef and -Wundef" href="http://ozlabs.org/~rusty/index.cgi/tech/2008-01-04.html">mentioned before</a>).  I&#8217;ll concentrate on the insufficiently-general issues which can bite users of the library, and a few random asides.</p>
<ul>
<li> <tt>#ifndef HAVE_VOLATILE</tt> ?  I can&#8217;t believe Samba still compiles on a compiler that doesn&#8217;t support volatile (this just defines <tt>volatile</tt> away altogether)  If it did no optimizations whatsoever, volatile might not matter, but I&#8217;m suspicious&#8230;</li>
<li><tt>typedef int bool;</tt> is a fairly common workaround for lack of bool, but since pointers implicitly cast to bool but can get truncated when passed as an int, it&#8217;s a theoretical trap.  ie. (bool)0&#215;1234567800000000 == true, (int)0&#215;1234567800000000 == 0.</li>
<li><tt>#if !defined(HAVE_VOLATILE)</tt> is the same test as above, repeated.  It&#8217;s still as bad an idea as it was 186 lines before :)</li>
<li><tt>ZERO_STRUCT</tt>, <tt>ZERO_ARRAY</tt> and <tt>ARRAY_SIZE</tt> are fairly sane, but could use gcc extensions to check their args where available.  I implemented this for ARRAY_SIZE in the Linux kernel and in CCAN.  Making sure an arg is a struct is harder, but we could figure something&#8230;</li>
<li><tt>#define PATH_MAX 1024</tt> assumes that systems which don&#8217;t define <tt>PATH_MAX</tt> probably have small path limits.  If it&#8217;s too short though, it opens up buffer overruns. Similarly for <tt>NGROUPS_MAX</tt> and <tt>PASSWORD_LENGTH</tt>.</li>
<li>The <tt>dlopen</tt> replacement is cute: it uses <tt>shl_load</tt> where available (Google says <a href="http://www.docs.hp.com/en/B2355-90695/shl_load.3X.html" class="broken_link" >HPUX</a>), but <tt>dlerror</tt> simply looks like so:
<pre>    #ifndef HAVE_DLERROR
    char *rep_dlerror(void)
    {
     	return "dynamic loading of objects not supported on this platform";
    }
    #endif</pre>
<p> This cute message for runtime failure allows your code to compile, but isn&#8217;t helpful if dlopen was a requirement.  Also, this should use <tt>strerror</tt> for <tt>shl_load</tt>.</li>
<li><tt>havenone.h</tt> is (I assume) a useful header for testing all the replacements at once: it undefines all HAVE_ macros.  Unfortunately it hasn&#8217;t been updated, and so it isn&#8217;t complete (unused code is buggy code).</li>
<li><tt>inet_pton</tt> is credited to Paul Vixie 1996.  It&#8217;s K&amp;R-style non-prototype, returns an int instead of bool, and doesn&#8217;t use strspn <tt>((pch = strchr(digits, ch)) != NULL)</tt> or (better) atoi.  But it checks for exactly 4 octets, numbers &gt; 255, and carefully doesn&#8217;t write to <tt>dst</tt> unless it succeeds.  I would have used sscanf(), which wouldn&#8217;t have caught too-long input like &#8220;1.2.3.4.5&#8243;.  OTOH, it would catch &#8220;127&#8230;1&#8243; which this would allow. But making input checks more strict is a bad way to be popular&#8230;</li>
<li>Tridge&#8217;s opendir/readdir/telldir/seekdir/closedir replacement in <a href="http://gitweb.samba.org/?p=samba.git;a=blob;f=lib/replace/repdir_getdents.c;h=afc634a79621247a49dd48d92aa1c099440f1fc5;hb=HEAD">repdir_getdents.c</a> is a replacement for broken telldir/seekdir in the presence of deletions, and a workaround for (older?) BSD&#8217;s performance issues.  It is in fact never used, because the configure test has had <tt>#error _donot_use_getdents_replacement_anymore</tt> in it since at least 2006 when the Samba4 changes were merged back into a common library!</li>
<li>repdir_getdirents.c is the same thing, implemented in terms of getdirents rather than getdents; it&#8217;s still used if the telldir/delete/seekdir test fails.</li>
<li>replace.c shows some of the schizophrenia of approaches to replacement: <tt>rep_ftruncate</tt> #errors if there&#8217;s no <tt>chsize</tt> or <tt>F_FREESP</tt> ioctl which can be used instead, but <tt>rep_initgroups</tt> returns -1/ENOSYS in the similar case.  Best would be not to implement replacements if none can be implemented, so compile will fail if they&#8217;re used.</li>
<li><tt>rep_pread</tt> and <tt>rep_pwrite</tt> are classic cases of the limitations of replacement libraries like this.  As <tt>pread</tt> is not supposed to effect the file offset, and file offsets are shared with children or dup&#8217;d fds.  There&#8217;s no sane general way to implement this, and in fact tdb has to test this in <a href="http://git.samba.org/?p=samba.git;a=blob;f=lib/tdb/common/open.c">tdb_reopen_internal</a>.  I would implement a read_seek/write_seek which are documented not to have these guarantees.  I remember Tridge ranting about glibc doing the same kind of unsafe implementation of <a href="http://www.opengroup.org/onlinepubs/000095399/functions/select.html">pselect</a> :)</li>
<li><tt>snprintf</tt> only rivals qsort-with-damn-priv-pointer for pain of &#8220;if only they&#8217;d done the original function right, I wouldn&#8217;t have to reimplement the entire thing&#8221;. I&#8217;ll avoid the glibc-extracted strptime as well.</li>
</ul>
<p>I&#8217;m not sure Samba compiles on as many platforms as it used to; Perl is probably a better place for this kind of library to have maximum obscure-platform testing.  But if I were to put this in CCAN, this would make an excellent start.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=61</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Code Reviewing: popt</title>
		<link>http://rusty.ozlabs.org/?p=55</link>
		<comments>http://rusty.ozlabs.org/?p=55#comments</comments>
		<pubDate>Thu, 28 Jan 2010 11:40:23 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=55</guid>
		<description><![CDATA[I decided that every day I would review some code in ctdb.  I never spend enough time reading code, and yet it&#8217;s the only way to really get to know a project.  And I decided to start easy: with the popt library in ctdb. popt is the command-line parsing library included with the RPM source, [...]]]></description>
			<content:encoded><![CDATA[<p>I decided that every day I would review some code in <a href="http://ctdb.samba.org/">ctdb</a>.  I never spend enough time reading code, and yet it&#8217;s the only way to really get to know a project.  And I decided to start easy: with the popt library in ctdb.</p>
<p>popt is the command-line parsing library included with the <a href="http://en.wikipedia.org/wiki/RPM_Package_Manager">RPM</a> source, and used by SAMBA.  I vaguely recall Tridge telling me years ago how good it was.  I started with the man page, and it <strong>is</strong> an excellent and useful library: it does enough to make the simple cases less code that getopt_long, yet allows flexibility for complex cases.</p>
<p>The idea is simple: similar to getopt_long, you create an array describing the possible options.  Unlike getopt, however, simple integers and flags are handled automatically.  So you set up the context with the commandline, then hand that context to poptGetNextOpt() to do the parsing.  That keeps parsing args until it hits an error or you&#8217;ve marked an argument to return a value for special handling.  The manual page is excellent and made me feel really comfortable with using the code.</p>
<p>Now, the code itself.  Even before you notice the four-space tabs and bumpyCaps, you see the lint annotations and docbook-style comments cluttering the source.  It does make the code annoying to read, breaking CCAN&#8217;s <a title="Our Code Should Not Be Ugly" href="http://ccan.ozlabs.org/Wiki/GoldenRule" class="broken_link" >Golden Rule</a>.  Typedefs of structs, typedefs to pointers, and several #ifdef  __cplusplus complete my minor gripes.</p>
<p>The code is old and cross-platform: the header test for features we&#8217;d simply assume in a modern Linux.  It has a simple set of bitmap macros (taken from pbm, judging from the name), a helper routine to find an executable in $PATH (using alloca!) .  These are the kinds of things which would be in separate modules, were this in CCAN.</p>
<p>The definition of _free() to be a (redundantly-NULL-taking) free() which always returns NULL is used to effect throughout the code:</p>
<pre>    defs = _free(defs);</pre>
<p>Here is a trick I hadn&#8217;t seen before to zero an onstack var, and really don&#8217;t recommend:</p>
<pre>poptDone done = memset(alloca(sizeof(*done)), 0, sizeof(*done));</pre>
<p>The help-printing code is in a separate file, popthelp.c.  It&#8217;s actually about <span style="text-decoration: line-through;">half </span>1/3 of the code!  That&#8217;s mainly because it takes pains to pretty-print, and it&#8217;s done by manually tracking the column number through the routines (aka &#8216;cursor&#8217;).  These days we&#8217;d asprintf into a temp buffer and strlen() to figure out if we should start a new line and indent before printing this.  Or even better, create a struct with the FILE * and the column number, and create a fprintf variant which updated the column number and figured out wrapping for us. Routines like maxArgWidth() which iterates the table(s) to figure how much to indent will still suck however: probably simplest to build all the strings in the help table in memory and then dump at the end.</p>
<p>I thought I found a buffer overrun, but a test program disproved it: the singleOptionHelp() uses its maxLeftCol (plus some extra stuff) to size a buffer.  This works because maxLeftCol is previously calculated as the worst-case size of the argument help.  Now, the code is unclear (AFAICT maxLeftCol must always be sufficient, so the extra bytes are wasted), but not buggy.</p>
<p>In summary, this is excellent code.  Talloc would help it, as would modern printf usage (%.*s for example), but generally the code is in really good shape.  I know that the popt code in RPM is a little updated, but I can&#8217;t imagine that much has changed in such an obviously-stable codebase. The temptation to rewrite it is thus very low: who knows what the testsuite would miss?</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=55</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>linux.conf.au 2010</title>
		<link>http://rusty.ozlabs.org/?p=50</link>
		<comments>http://rusty.ozlabs.org/?p=50#comments</comments>
		<pubDate>Thu, 28 Jan 2010 04:29:40 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=50</guid>
		<description><![CDATA[After slightly disastrous preparation  (my left knee in a brace as detailed for the perversely-curious here) my week went well.  I tried to get back to my hotel room early each evening to rest as per doctor&#8217;s orders (and managed it except Friday night), but polishing my Friday talk tended to take a few hours [...]]]></description>
			<content:encoded><![CDATA[<p>After slightly disastrous preparation  (my left knee in a brace as detailed for the perversely-curious <a title="linux.conf.au Wiki page on Rusty's Lef" href="http://conf.linux.org.au/wiki/RustysLeg">here</a>) my week went well.  I tried to get back to my hotel room early each evening to rest as per doctor&#8217;s orders (and managed it except Friday night), but polishing my Friday talk tended to take a few hours every day.</p>
<h2>Sunday</h2>
<p>The Newcomer&#8217;s Session was well attended, but Jacinta and I were slack with preparation so it was unbalanced for my tastes.  I raced to the post-session pub assuming my crutches would ensure I&#8217;d be the trailer, to find that I was wrong.  It would have been better to explicitly and immediately drag people towards the pub, because that&#8217;s (seriously) the most important part of the introduction to LCA.</p>
<h2>Monday</h2>
<p>Miniconf time, and I started in the Open Programming Languages miniconf.  There was some interestingly random language stuff there: it&#8217;s one of my few opportunities to get exposure to higher level languages.  The miniconf talks were enthusiastic and unpolished as such things are supposed to be.  <a href="http://blogs.tucs.org.au/oplm/programme/#haskell" class="broken_link" >Haskell, and all the wonderful things it doesn’t let you do</a> <em>by</em> Stephen Blackheath was interesting,  but lacked solid examples. <a href="http://blogs.tucs.org.au/oplm/programme/#gearman" class="broken_link" >Introducing Gearman — Distributed server for all languages </a><em>by</em> Giuseppe Maxia was a great short intro into an unknown project. <a href="http://www.lca2010.org.nz/programme/schedule/monday">vcs-pkg.org </a><em>by</em> Martin F. Krafft was classic work-in-progress talk with insights into a mundane but critical infrastructure problem (standards and practices for coordinating upstream and across distributions using distributed revision control).</p>
<p><a href="http://libregraphicsday.org/proposal/31/die-flash-die-svg-has-arrived">Die Flash Die &#8211; SVG has arrived</a> <em>by</em> Andy Fitzsimon gave classic bling talk with a message about the animation potential for SVG.  Useful content, too, for those dealing with this, and I was blown away to hear of <a href="http://github.com/tobeytailor/gordon">Gordon</a>, a FOSS Flash™ runtime written in JavaScript.</p>
<p><a href="http://libregraphicsday.org/proposal/23/how-use-foss-graphics-tools-pay-college">How to Use FOSS Graphics Tools to Pay for College</a> <em>by</em> Elizabeth Garbee was an insight into the US education system and a chance to find out what my friend Edale (I know she hates that meme!) was doing.  But her talk didn&#8217;t quite gel for this audience. Unfortunately using the words &#8220;did you spot the head-fake?&#8221; riles me.  You are suddenly telling me that you&#8217;ve been using your intellect to compete with me rather than to inform and enrich me.</p>
<p>Then came my own <a href="http://blogs.tucs.org.au/oplm/programme/#talloc" class="broken_link" >Talloc: Pick Up Your Own Garbage!</a> talk, which was delayed by my miscalculation of transit time on crutches. <em></em>A mediocre rehash of my previous talloc talks, but I wanted to put it in front of this group because it really offers fresh view into a program&#8217;s data structures at runtime.</p>
<p><a href="http://blogs.tucs.org.au/oplm/programme/#facebook" class="broken_link" >Writing Facebook Applications in Perl</a><em> by</em> Paul Fenwick was a nice little introduction to the FB API from a Perl point of view, but he kept his powder dry for his awesome lightening talk on Friday.</p>
<h2>Tuesday</h2>
<p>I peered in at the tail end of the keynote which was apparently excellent.  I woke a little early then did some more work on my presentation, and by the time I had breakfast I was incurably late. One person admitted to me that they watched the live stream from their hotel room, but I wasn&#8217;t that clever.</p>
<p>This this day was all hallway track for me, catching up with many people I haven&#8217;t seen since last year. Then the Speaker&#8217;s Dinner at Museum of New Zealand: Te Papa Tongarewa. This is also a fun time to chat with everyone, but I was disappointed that my crutches forced me to forgo learning a traditional <a href="http://en.wikipedia.org/wiki/Haka">Haka</a>. It was also the first chance to greet the two chief organizers, who had been sick the first two days of the conference.  Edale and I also had fun playing with their very-past-bedtime hyper 2 yo Brooke (until we were told not to stir her up any more!)</p>
<h2>Wednesday</h2>
<p>The keynote by <a href="http://www.lca2010.org.nz/programme/keynotes#BenjaminMakoHill">Benjamin Mako Hill</a> was a little chaotic but made his point about antifeatures well: how such things are only viable when consumers don&#8217;t have freedom of choice (in particular, ability to examine, modify and share the software they&#8217;re using).  I then headed to <a href="http://www.lca2010.org.nz/programme/schedule/view_talk/50171?day=wednesday">Introduction to game programming</a> <em>by</em> Richard Jones, where I struggled with pyglet before giving up and paying half-attention.  I did learn some things though, and everyone who was active seemed to get great satisfaction from the tutorial.</p>
<p><a href="http://www.lca2010.org.nz/programme/schedule/view_talk/50081?day=wednesday">Open Sourcing the Accountants</a> <em>by</em> Jethro Carr lacked density.  It takes a great deal of work to give a thorough comparison of different accounting packages, and his insights into how accountants think were insufficient to make that the backbone of his talk either.</p>
<p><a href="http://www.lca2010.org.nz/programme/schedule/view_talk/50297?day=wednesday">subunit: Testing across boundaries for fun and profit</a> <em>by</em> Robert Collins was slightly familiar ground for me, but as <a href="http://ccan.ozlabs.org/info/tap.html">libtap</a> maintainer he wanted me to attend.  It was a good bread-and-butter talk, which perhaps could have benefited from a few more snazzy real-life examples (making testing sexy is hard though!).  He semi-seriously suggested I should take over the C output implementation for subunit; still thinking&#8230;</p>
<p>I caught the questions at <a href="http://www.lca2010.org.nz/programme/schedule/view_talk/50100?day=wednesday">Teaching FOSS at universities</a> <em>by</em> Andrew Tridgell <em>and</em> Robert (Bob) Edwards, which I will watch seriously once the videos are uploaded.</p>
<p>Then was one compulsory-attendance presentation of the week: <a href="http://www.lca2010.org.nz/programme/schedule/view_talk/50256?day=wednesday">The World&#8217;s Worst Inventions</a> <em>by</em> Paul Fenwick. I had made a comment to Paul earlier in the week that I was concerned that my talk lacked substance.  His reply was &#8220;I won&#8217;t comment how much substance is in my talk&#8221;.  And any conclusions were left to the minds of the audience as full-costumed Paul took us through a series of invention disasters.  I teased him about it later, but let&#8217;s be honest: if I could present like that I wouldn&#8217;t have worried about content either!</p>
<p>That evening was the <a href="http://wellington.pm.org/articles/hackoff2010/">HackOff</a>.  I&#8217;ve never tried competitive programming, so when we came up with the plan of a SAMBA team, I heartily endorsed it :)  Intimidation is important at these events, and the tweet from Adam Harvey was promising: <a href="http://twitter.com/LGnome">At the #lca2010 HackOff. There&#8217;s a table with Rusty, Tridge, Anthony Towns and Andrew Bartlett. We&#8217;re fucked.</a> However, despite having the largest team (with 6 of us), we only just squeaked in by 2 minutes.  Subtract any one of the team and we wouldn&#8217;t have won, though with fewer we might not have tried to brute-force the final question.</p>
<h2>Thursday</h2>
<p>Glyn Moody&#8217;s <a href="http://www.lca2010.org.nz/programme/keynotes#GlynMoody">keynote</a> was excellent. Then I lost some more hallway time before emerging in <a href="http://www.lca2010.org.nz/programme/schedule/view_talk/50076?day=thursday">The Elephant in the Room: Microsoft and Free Software</a> <em>by</em> Jeremy Allison. I thought it was a worthwhile and balanced presentation; of course it had a few cheap laughs in it, but the examination of Microsoft&#8217;s actions wrt FOSS is a worthwhile exercise if we want to assess their potential impact.</p>
<p>I was a bit late to <a href="http://www.lca2010.org.nz/programme/schedule/view_talk/50322?day=thursday">Building a Xapian index of Wikipedia in less time than this talk takes</a> <em>by</em> Olly Betts, but it was too unprepared for my tastes and I went in not knowing what Xapian was (though I picked it up from context). <a href="http://www.lca2010.org.nz/programme/schedule/view_talk/50189?day=thursday">Tux on the Moon: FOSS hardware and software in space</a> <em>by</em> Jonathan Oxer was good, but another one I was late to (15 minutes between talks seems to give me enough time to start conversations, but not enough to finish them).</p>
<p><a href="http://www.lca2010.org.nz/programme/schedule/view_talk/50240?day=thursday">Simplicity Through Optimization</a> <em>by</em> Paul McKenney was a good talk if you didn&#8217;t know your <a href="http://en.wikipedia.org/wiki/Read-copy-update">RCU</a>.  For me I would have liked to hear more what the various lines of code were doing (before they were excised by the optimized implementation).  But being deeply familiar with the theory and somewhat familiar with the practice, I&#8217;m probably in a minority.</p>
<p>By this stage I was exhausted, and <a href="http://www.lca2010.org.nz/programme/schedule/view_talk/50193?day=thursday">Using Functional Programming Techniques In Your Favourite Language</a> <em>by</em> Malcolm Tredinnick was in the same room so I stayed.  This talk was a disappointment to me (and, I think, Malcolm) because it didn&#8217;t quite contain the general insights he&#8217;d believed were there when he proposed the talk. Nice for me to get an refreshing exposure to functional programming though.</p>
<p>Dinner at an Indian restaurant with the SAMBA people, which meant I was right near the <a href="http://www.lca2010.org.nz/programme/social_events#ProfessionalDelegatesNetworkingSession">PDNS</a>, so I dropped in briefly then returned to my hotel room for an early night.</p>
<h2>Friday</h2>
<p><a href="http://www.lca2010.org.nz/programme/keynotes#NathanTorkington">Nat Torkington&#8217;s keynote</a> contained the classic &#8220;heckle Rusty&#8221; factor and was delightfully punchy. He rolled over to a very very strong set of lightning talks; a format which works so well at these geek-rich events.  Paul Fenwick&#8217;s &#8220;Unfriendly&#8221; Facebook app was an awesome way to close.</p>
<p><a href="http://www.lca2010.org.nz/programme/schedule/view_talk/50091?day=friday">Patent defence for free software</a> <em>by</em> Andrew Tridgell (late again!) was familiar ground for me, but I wanted to see how he presented such a dry area.  Lots of text: I would have included some more diagrams (claim dependencies are well represented by a tree, for example). But the audience were rapt, so I&#8217;m clearly too picky!</p>
<p>Last minute prep for my talk: I decided the previous night that I would use Notes View, only to find that noone could get it to work.  Both notes and presentation appeared on the projector screen, fortunately as I was about to give up and run without notes, someone suggested I simply drag the notes view back onto my laptop screen!  Sometimes the low-tech approaches evade our over-complicated minds.</p>
<p><a href="http://www.lca2010.org.nz/programme/schedule/view_talk/50062?day=friday">FOSS Fun With A Wiimote</a> <em>by</em> Rusty Russell was <a href="https://twitter.com/gnat/status/8048582063">well-received.</a> I didn&#8217;t go as far with the project as I had intended, due to personal time contraints and time lost wrangling with actual hardware, but sometimes that&#8217;s instructive too.</p>
<p>The presentation itself was flawed in three places.  Firstly, my intro slide appeared all at once rather than clicking in one point at a time, destroying my carefully practiced routine at that point.  Secondly, noone knew what LED throwies were: <a href="http://graffitiresearchlab.com/?page_id=17">(an open source graffiti technology developed at the Graffiti Research Lab)</a> and I so that slide was completely lost.  Finally, I should have set up my <a href="http://pipka.org/">replacement two-year-old</a> on the stage where the audience and the cameras could see her clearly.</p>
<p>The closing announced <a href="http://followtheflow.org/">Brisbane for lca2011</a>, and I handed the virtual speakers&#8217; gift to the organisers.  That done, I was ready to relax at the Penguin Dinner.  Most years I don&#8217;t even drink, knowing that I&#8217;ll have to do the auction.  But as there was no auction I sat next to Nat Torkington to guarantee great conversation and was ready to chill. I did some singing, didn&#8217;t try the Haga (again). I even got a cuddle with the organiser&#8217;s very well-behaved 5-month-old son Adam.</p>
<p>Unfortunately, events conspired against me and I was dragged into a <a href="http://www.fundraiseonline.co.nz/LCA2010/">pledging war for a prize I didn&#8217;t want to win</a> (and at which my doctor would be aghast). I thought we could get more money from the Wenches For Winching, who were weasonably wealthy and weally wanted to win. <a href="http://thunk.org/tytso/blog/" class="broken_link" >Ted Ts&#8217;o</a> had a similar idea. Unfortunately the prospect of crippled Rusty being &#8220;rescued&#8221; (after being dropped: that was the <em>no way</em> part) was too alluring for many, and I had to work hard to ensure I didn&#8217;t win.</p>
<p>A good time had by all, though exhausting after a long week.</p>
<h2>Saturday</h2>
<p>Briefly peered into the Open Day, which was buzzing with setup and opening, before heading home, spent. I did find out that wild weather had wuined the winching of wenches; but there is a standing offer when they find themselves in Wellington again.</p>
<h2>Summary</h2>
<p>Absolutely on par with previous awesome conferences; there were no organisational disappointments for me the entire week. I was particularly happy <a href="http://blog.gingertech.net/2010/01/18/video-streaming-from-linux-conf-au/">to see people digging in and fixing things when they were wrong</a> instead of simply complaining.</p>
<p>A great achievement, everyone!</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=50</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>More Linux-next Graphing</title>
		<link>http://rusty.ozlabs.org/?p=38</link>
		<comments>http://rusty.ozlabs.org/?p=38#comments</comments>
		<pubDate>Tue, 05 Jan 2010 04:13:57 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=38</guid>
		<description><![CDATA[Mikey blogs about linux-next workload with pretty graphs.  Ideally, we should all have our patches marshalled before the freeze, and there should be no pre-merge-window peak.  I&#8217;ve gotten close to this in recent times, by being lazy and being content to wait for the next cycle if I miss one. Rushing things in tends to [...]]]></description>
			<content:encoded><![CDATA[<p><a title="Michael Neuling's Blog" href="http://neuling.org/mikey/">Mikey</a> blogs about <a title="Tue, 01 Dec 2009 Linux Next Graphing" href="http://neuling.org/mikey/index.cgi/tech/linux-next-size.html">linux-next workload with pretty graphs</a>.  Ideally, we should all have our patches marshalled before the freeze, and there should be no pre-merge-window peak.  I&#8217;ve gotten close to this in recent times, by being lazy and being content to wait for the next cycle if I miss one. Rushing things in tends to imply we skimped on review and testing.</p>
<p>So on that basis 2.6.30 looks like a winner:  it has the smallest &#8220;peak of crap&#8221;.</p>
<p>If you want to actually measure how much work Stephen is having to do, you would have to figure out what changes he is seeing.  Approximately, that would be the changes in Linus&#8217; tree that did <em>not</em> come from linux-next, plus any new work entering linux-next itself.  Anyone?</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=38</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Coding Fail: Rusty Breaks Booting</title>
		<link>http://rusty.ozlabs.org/?p=42</link>
		<comments>http://rusty.ozlabs.org/?p=42#comments</comments>
		<pubDate>Tue, 05 Jan 2010 04:12:07 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=42</guid>
		<description><![CDATA[I will freely admit that kernel work has dropped in my priority list. But that didn&#8217;t excuse sloppy work like my ae1b22f6e46 commit which sought to sidestep an issue for lguest without me having to do much work. There&#8217;s a 64 bit atomic exchange instruction on x86 called cmpxchg8b.  This isn&#8217;t supported on pre-586 processors, [...]]]></description>
			<content:encoded><![CDATA[<p>I will freely admit that kernel work has dropped in my priority list. But that didn&#8217;t excuse sloppy work like my <a href="http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=ae1b22f6e46c03cede7cea234d0bf2253b4261cf">ae1b22f6e46</a> commit which sought to sidestep an issue for lguest without me having to do much work.</p>
<p>There&#8217;s a 64 bit atomic exchange instruction on x86 called cmpxchg8b.  This isn&#8217;t supported on pre-586 processors, so we have cmpxchg8b_emu, but that implementation isn&#8217;t paravirtualized so won&#8217;t run under lguest.  That&#8217;s OK, we used to never run it except on machines which didn&#8217;t support that cmpxchg8b instruction and I&#8217;ve never received a report.  Then at some point we started doing so: the easiest mod I could see was to switch emulation off except for kernels specifically compiled for 386 or 486.  But I missed Linus&#8217; commit which had set the archs on which emulation was skipped:</p>
<blockquote><p>Note, this patch only adds CMPXCHG8B for the obvious Intel CPU&#8217;s, not for others. (There was something really messy about cmpxchg8b and clone CPU&#8217;s, so if you enable it on other CPUs later, do it carefully.)</p></blockquote>
<p>Now, I could blame Linus for putting that in a commit message, not in the Kconfig.cpu file where anyone changing it was going to see it.  But you should always double-check when you think you&#8217;re &#8220;fixing&#8221; something, and I didn&#8217;t.</p>
<p>(I get annoyed when developers don&#8217;t detail exactly what commit introduced a problem: it&#8217;s not just for convenient reading, but such research often prevents reintroducing subtle bugs! Like, say, Cyrix 6&#215;86 not booting&#8230;)</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=42</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Not Always Lovely Blooms&#8230;</title>
		<link>http://rusty.ozlabs.org/?p=20</link>
		<comments>http://rusty.ozlabs.org/?p=20#comments</comments>
		<pubDate>Tue, 27 Oct 2009 04:46:03 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=20</guid>
		<description><![CDATA[So, with my recent evangelizing of Bloom Filters, Tridge decided to try to apply them on a problem he was having.  An array of several thousand of unsorted strings, each maybe 100 bytes, which needed checking for duplicates.  In the normal case, we&#8217;d expect few or no duplicates. A Bloom Filter for this is quite [...]]]></description>
			<content:encoded><![CDATA[<p>So, with my recent evangelizing of <a href="http://en.wikipedia.org/wiki/Bloom_filter">Bloom Filters</a>, <a href="http://blog.tridgell.net">Tridge</a> decided to try to apply them on a problem he was having.  An array of several thousand of unsorted strings, each maybe 100 bytes, which needed checking for duplicates.  In the normal case, we&#8217;d expect few or no duplicates.</p>
<p>A Bloom Filter for this is quite simple: Wikipedia tells you how to calculate the optimal number of hashes to use and the optimal number of bits given (say) a 1 in a million chance of a false positive.</p>
<p>I handed Tridge some example code and he put it in alongside a naive qsort implementation.  It&#8217;s in his <a href="http://samba.org/ftp/unpacked/junkcode/stringdup.c">junkcode dir</a>.  The result?  qsort scales better, and is about 100x faster.  The reason?  Sorting usually only has to examine the first few characters, but creating N hashes means (in my implementation using the<a href="http://burtleburtle.net/bob/hash/index.html"> always-awesome Jenkins lookup3 hash</a>) passing over the whole string N/2 times.  That&#8217;s always going to lose: even if I coded a single-pass multihash, it&#8217;s still having to look at the whole string.</p>
<p>Sometimes, simplicity and standard routines are not just clearer, but faster.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=20</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>A Week With Android (HTC Magic)</title>
		<link>http://rusty.ozlabs.org/?p=24</link>
		<comments>http://rusty.ozlabs.org/?p=24#comments</comments>
		<pubDate>Tue, 27 Oct 2009 04:00:50 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=24</guid>
		<description><![CDATA[I haven&#8217;t used an iPhone in anger so I can&#8217;t compare, but I got this so I could use Google Maps to navigate public transport: Adelaide&#8217;s integration is excellent, and as I have no car it&#8217;s important for Arabella and me. The Good Typing on anything that size is suboptimal, but clever auto predict and [...]]]></description>
			<content:encoded><![CDATA[<p>I haven&#8217;t used an iPhone in anger so I can&#8217;t compare, but I got this so I could use Google Maps to navigate public transport: Adelaide&#8217;s integration is excellent, and as I have no car it&#8217;s important for Arabella and me.</p>
<h2>The Good</h2>
<ul>
<li>Typing on anything that size is suboptimal, but clever auto predict and correct are well done.</li>
<li>Google maps integration is nice: knowing my location makes getting public transport directions really sweet.</li>
<li>Since I pay <span style="text-decoration: line-through;">15c/MB</span> 1.5c/MB for data on the phone network, grabbing onto my home WiFi network where possible is good.</li>
<li>Google Calendar and contacts storage means I fear obsolete/lost phone much less.</li>
<li>Plugging in as a USB mass-storage makes transferring music and pictures of Arabella from Linux really easy.</li>
<li>Some neat features, like turning a map search into a contact (and then easily using a contact when looking for directions).</li>
</ul>
<h2>The Bad</h2>
<ul>
<li>Intermittent bugs, such as no characters showing up for SMS when the keyboard is in landscape mode, I discovered can be solved by power-cycle.</li>
<li>My calendar notifications are completely silent.  I&#8217;ve played with every option, but when a calendar event comes due, there&#8217;s nothing but a glowing trackball to indicate it.  This seems to be a bug, but I&#8217;m reluctant to factory reset to see if that fixes it.</li>
<li>Calendar entries default to My Calendar: if you forget to flip that to your google account when first creating the entry, it won&#8217;t be shared.  I want everything mirrored to Google, so several times I&#8217;ve had to delete and recreate laboriously-entered appointments.</li>
<li>I wish the screen would flip faster; landscape makes a better kbd, but portrait often better browsing.</li>
<li>Sometimes slowness makes it think I held down a key (giving a special character) when I didn&#8217;t, and the autopredict/correct seems to give up if you held a key down.</li>
<li>I have access to Internode&#8217;s hotspots around the city, but as that needs a username/password logon, it&#8217;s not useful automatically.</li>
<li>Battery life (in this stage of intense use) is 1-2 days.</li>
</ul>
<p>I got it from <a href="http://www.portagadgets.com/australia/product.php?productid=35459&amp;utm_source=getprice&amp;utm_medium=cpc">Portagadgets.com</a>, who were efficient (A$487 + $36 shipping, done via local bank transfer).  Getting an account and new SIM from Exetel took longer.</p>
<p>Conclusion: it&#8217;s definitely usable by non-geeks, and has raised my expectations of future phones.  There are some things (such as writing this post) which are much easier on my laptop.  But for reading Facebook or Wikipedia, finding your way on Google Maps, or having SMS conversations it&#8217;s excellent.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=24</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Google Analytics For WordPress Upgrade Fail</title>
		<link>http://rusty.ozlabs.org/?p=17</link>
		<comments>http://rusty.ozlabs.org/?p=17#comments</comments>
		<pubDate>Mon, 26 Oct 2009 14:20:28 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=17</guid>
		<description><![CDATA[Had an old copy of the &#8220;Google Analytics For WordPress&#8221; lying around (which didn&#8217;t seem to put anything in my blog source), but after upgrading it it kept saying &#8220;Google Analytics settings reset to default&#8221; whenever I tried to change anything. See this thread which talks about the problem and waves at the solution.  Here&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>Had an old copy of the &#8220;Google Analytics For WordPress&#8221; lying around (which didn&#8217;t seem to put anything in my blog source), but after upgrading it it kept saying &#8220;Google Analytics settings reset to default&#8221; whenever I tried to change anything.</p>
<p>See <a href="http://wordpress.org/support/topic/300824">this thread</a> which talks about the problem and waves at the solution.  Here&#8217;s what you need to do, if like me you&#8217;re not a WordPress/MySQL junkie and want simple instructions:</p>
<ol>
<li>Find your wordpress config file.  Mine, on a Debian system, was in /etc/wordpress/config-rusty.ozlabs.org.php</li>
<li>It will contain lines like this:
<pre>define('DB_NAME', 'rustyozlabsorg');</pre>
<pre>define('DB_USER', 'rustyozlabsorg');</pre>
<pre>define('DB_PASSWORD', 'g1812fbsa');</pre>
</li>
<li>You need to open the mysql database, we&#8217;re going to do some brain surgery to remove the old cruft:
<pre>$ mysql --user=rustyozlabsorg --password=g1812fbsa rustyozlabsorg</pre>
</li>
<li>This should give you a &#8220;mysql&gt;&#8221; prompt, where you type the following:
<pre>DELETE FROM wp_options where option_name='GoogleAnalyticsPP';</pre>
</li>
<li>It should say something like &#8220;Query OK, 1 row affected (0.00 sec)&#8221;.  Then type
<pre>quit;</pre>
</li>
<li>You&#8217;re done.  Reload your setting page and try again.</li>
</ol>
<p>Hope that gets into Google and helps someone else who can&#8217;t figure out what&#8217;s going on!</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=17</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rusty Finally Enters Web 1.1</title>
		<link>http://rusty.ozlabs.org/?p=3</link>
		<comments>http://rusty.ozlabs.org/?p=3#comments</comments>
		<pubDate>Mon, 26 Oct 2009 06:49:46 +0000</pubDate>
		<dc:creator>rusty</dc:creator>
				<category><![CDATA[Self]]></category>

		<guid isPermaLink="false">http://rusty.ozlabs.org/?p=3</guid>
		<description><![CDATA[Jeff Waugh long ago suggested I switch to WordPress.&#160; I had a few toy blogs with WP, and it worked well, but the final motivation to stop banging out raw HTML and feeding it to blosxom was that I have a new Android phone (I lost my second-hand one sometime at the last farm visit, [...]]]></description>
			<content:encoded><![CDATA[<p><a title="Jeff Waugh's Blog" href="http://bethesignal.org">Jeff Waugh</a> long ago suggested I switch to WordPress.&nbsp; I had a few toy blogs with WP, and it worked well, but the final motivation to stop banging out raw HTML and feeding it to blosxom was that I have a new Android phone (I lost my second-hand one sometime at the last farm visit, so it was time to ask the Ozlabbians who know this stuff what to get: the answer was the HTC Magic).&nbsp; And being able to blog on the train increases the chance that I&#8217;ll actually blog regularly.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusty.ozlabs.org/?feed=rss2&#038;p=3</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
