<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'><id>tag:blogger.com,1999:blog-3187374</id><updated>2008-12-22T14:07:13.286-08:00</updated><title type='text'>saladwithsteve</title><subtitle type='html'>enjoying salad since 1978.</subtitle><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default?start-index=26&amp;max-results=25'/><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://saladwithsteve.com/atom.xml'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>770</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3187374.post-8873858360769806816</id><published>2008-12-08T21:02:00.000-08:00</published><updated>2008-12-08T21:11:01.011-08:00</updated><title type='text'>More Varnish: Thoughts from the Author</title><content type='html'>&lt;a href="http://people.freebsd.org/~phk/"&gt;Poul-Henning Kamp&lt;/a&gt;, the lead author of Varnish, was kind enough to respond to my blog post.

&lt;tt&gt;
&lt;p&gt;
Hi Steve,
&lt;/p&gt;
&lt;p&gt;
I read your comments about Varnish and thought I'd better explain
myself, feel free to post this if you want.
&lt;/p&gt;
&lt;p&gt;
The reason why we don't multiplex threads in Varnish is that it has
not become a priority for us yet, and I am not convinced that we
will ever see it become a priority at the cost it bears.
&lt;/p&gt;
&lt;p&gt;
A common misconception is that varnish parks a thread waiting for
the client to send the next request.  We do not, that would be
horribly stupid.  Sessions are multiplexed when idle.
&lt;/p&gt;
&lt;p&gt;
The Varnish worker thread takes over when the request is completely
read and leaves the session again when the answer is delivered to
the network stack (and no further input is pending).
&lt;/p&gt;
&lt;p&gt;
For a cache hit, this takes less than 10 microseconds, and we are
still shaving that number.
&lt;/p&gt;
&lt;p&gt;
The problem about multiplexing is that it is horribly expensive,
both in system calls, cache pressure and complexity.
&lt;/p&gt;
&lt;p&gt;
If we had a system call that was called "write these bytes, but
don't block longer than N seconds", multiplexing could be sensibly
implemented.
&lt;/p&gt;
&lt;p&gt;
But with POSIX mostly being a historical society, it will cost you
around 7 system calls, some surprisingly expensive, to even find
out if multiplexing is necessary in the first place.
&lt;/p&gt;
&lt;p&gt;
In comparison, today Varnish delivers a cache-hit in 7 system calls
*total* of which a few are technically only there for debugging.
&lt;/p&gt;
&lt;p&gt;
The next good reason is that we have no really fiddled with the
sendbuffer sizes yet, but obviously, if you sendbuffer can swallow
the read, the thread does not wait.
&lt;/p&gt;
&lt;p&gt;
And if that fails, a thread blocked in a write(2) system call is
quite cheap to have around.
&lt;/p&gt;
&lt;p&gt;
It uses a little RAM, but it's not that much, and we can probably
tune it down quite a bit.
&lt;/p&gt;
&lt;p&gt;
The scheduler does not bother more with the thread than it has to,
and when it does, the VM hardware system is not kickstarted every
time we cross the user/kernel barrier.
&lt;/p&gt;
&lt;p&gt;
Without getting into spectroscoping comparisons between apples and
oranges, a thread just lounging around, waiting for the network
stack to do its thing, is much, much cheaper than a thread which
does a lot of system calls and fd-table walking, only to perform
a few and small(-ish) writes every time the network stack wakes up.
&lt;/p&gt;
&lt;p&gt;
And the final reason why it may never become necessary to multiplex
threads, is that servers are cheap.
&lt;/p&gt;
&lt;p&gt;
But if we get to the point where we need multiplexing, we will do
it.
&lt;/p&gt;
&lt;p&gt;
But I like the old design principles from the X11 project: we will
not do it, until we have a server that doesn't work without it.
&lt;/p&gt;
&lt;p&gt;
But if you are in the business of delivering ISOs to 56k modems
then yes, Varnish is probably not for you.
&lt;/p&gt;
&lt;p&gt;
Poul-Henning
&lt;/p&gt;
&lt;/tt&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/8873858360769806816/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=8873858360769806816' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/8873858360769806816'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/8873858360769806816'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/12/more-varnish-thoughts-from-author.html' title='More Varnish: Thoughts from the Author'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-8395686947164417365</id><published>2008-12-06T17:15:00.000-08:00</published><updated>2008-12-06T17:22:19.952-08:00</updated><title type='text'>Thoughts on Varnish</title><content type='html'>&lt;p&gt;&lt;a href="http://varnish.projects.linpro.no/"&gt;Varnish&lt;/a&gt; is getting a lot of attention these days around the internet, and with good reason, it&amp;#8217;s a nicely written and speedy cache, and has a nice &lt;span class="caps"&gt;DSL&lt;/span&gt; for caching. It has great features like hot reloading of cache rules and &lt;span class="caps"&gt;ESI&lt;/span&gt;.&lt;/p&gt;


 &lt;p&gt;One thing that&amp;#8217;s really surprised me, though, is that Varnish uses one thread per connection. Most network programs designed for high number of connection don&amp;#8217;t use one thread per connection anymore as it has serious drawbacks.&lt;/p&gt;


 &lt;p&gt;With slow clients, many of your threads are spending a lot of time doing nothing but blocking in &lt;tt&gt;write()&lt;/tt&gt;. In all internet consumer apps, I believe, slow clients make up the majority of your connections. But even though the threads are doing nothing, the OS still has memory and scheduling overhead in dealing with them. You find yourself with an artificially low ceiling on the amount of users you can service with a single machine.&lt;/p&gt;

 &lt;p&gt;What makes a client slow, though? Both speed and latency. Cell phones, 56k modems, and users on high speed links but not geographically close to your data center can all be classified as &amp;#8216;slow&amp;#8217;.&lt;/p&gt;


 &lt;p&gt;One design that is more appropriate for dealing with the slow client problem uses a pool of worker
threads or processes behind the scene and
&lt;a href="http://www.xmailserver.org/linux-patches/nio-improve.html"&gt;epoll&lt;/a&gt; /
&lt;a href="http://people.freebsd.org/~jlemon/kqueue_slides/index.html"&gt;kqueue&lt;/a&gt; / &lt;a href="http://developers.sun.com/solaris/articles/event_completion.html"&gt;event
ports&lt;/a&gt; handling slow clients and
telling the pool of workers that a socket is ready with a change notification. Your cost is still
correlated with growth but at a much lower rate and the number of users you can service will
dramatically increase.&lt;/p&gt;

 &lt;p&gt;So why does Varnish use this older, more troublesome model? Probably because most services aren&amp;#8217;t
going to notice the bottleneck; They simply don&amp;#8217;t have enough concurrent connections to worry about
using a few extra machines. If you&amp;#8217;re never saturated a load balancer or firewall, you&amp;#8217;ve probably
never had to seriously consider the &lt;a href="http://www.kegel.com/c10k.html"&gt;C10k&lt;/a&gt; issues involved.&lt;/p&gt;


 &lt;p&gt;Also, unfortunately, the way most people write load tests is that they are only testing the All Fast
Clients scenario and not a mix of fast clients and slow clients. I&amp;#8217;m guilty of this, too.&lt;/p&gt;


 &lt;p&gt;My executive summary: Varnish is a nice piece of software, and I hope they spend the time to make it
useful for larger sites as well as smaller ones.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/8395686947164417365/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=8395686947164417365' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/8395686947164417365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/8395686947164417365'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/12/thoughts-on-varnish.html' title='Thoughts on Varnish'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-3240946123374487993</id><published>2008-11-17T16:07:00.000-08:00</published><updated>2008-11-17T16:13:57.667-08:00</updated><title type='text'>More RPMs means faster access times. No news there.</title><content type='html'>&lt;p&gt;
When I upgraded my home laptop from a 2-year old MacBook Pro to one of the newly released unibody models, I decided to upgrade from a 5400 RPM drive to a 7200 RPM drive. I ran some &lt;a href="http://code.google.com/p/bonnie-64/"&gt;bonnie-64&lt;/a&gt; benchmarks and noticed a 40% improvement in random seeks/sec and some other impressive numbers. It's helped make my weekend hacking much more pleasant.
&lt;/p&gt;
&lt;p&gt;
Here are the old numbers:
&lt;script src="http://gist.github.com/25675.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
and the new numbers:
&lt;script src="http://gist.github.com/25200.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Bottom line: Recommended&lt;/strong&gt;
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/3240946123374487993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=3240946123374487993' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/3240946123374487993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/3240946123374487993'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/11/more-rpms-means-faster-access-times-no.html' title='More RPMs means faster access times. No news there.'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-8148313687841794358</id><published>2008-09-13T14:56:00.001-07:00</published><updated>2008-09-13T15:23:41.675-07:00</updated><title type='text'>Amazon as Political Pulpit</title><content type='html'>&lt;p&gt;
Check out the &lt;a href="http://www.amazon.com/review/product/B000FKBCX4/ref=dp_db_cm_cr_acr_txt?_encoding=UTF8&amp;showViewpoints=1"&gt;Amazon reviews for Spore&lt;/a&gt;, the new Will Wright game. 2,016 of the 2216 reviews gave it 1 star for the heavy-handed DRM. I use Amazon reviews heavily and I've never seen protest brought to the reviews at this scale before. Let's see if people take notice.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://torrentfreak.com/spore-most-pirated-game-ever-thanks-to-drm-080913/"&gt;TorrentFreak&lt;/a&gt; points out the following:
&lt;blockquote&gt;DRM doesn’t stop people from pirating a game, on the contrary. It only hurts legitimate customers since the DRM is removed from the pirate version."&lt;/blockquote&gt;
&lt;/p&gt;
&lt;p&gt;There are lots of philosophical reasons not to buy things with DRM. For me, the practical reason wins out. I'd rather deal with having to store music CDs and not play some potentially awesome games than deal with losing my data due to short-sighted DRM.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/8148313687841794358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=8148313687841794358' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/8148313687841794358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/8148313687841794358'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/09/amazon-as-political-pulpit.html' title='Amazon as Political Pulpit'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-603801523479358423</id><published>2008-09-12T15:54:00.000-07:00</published><updated>2008-09-12T15:57:12.678-07:00</updated><title type='text'>Alex's Scala Talk at C4[2]</title><content type='html'>&lt;a href="http://al3x.net/"&gt;al3x&lt;/a&gt; gave a &lt;a href="http://www.slideshare.net/al3x/why-scala-presentation/"&gt;talk on Scala&lt;/a&gt; recently at &lt;a href="http://rentzsch.com/c4/twoOpen/"&gt;C4[2]&lt;/a&gt; and it hits a lot of the high points as to why we're using Scala at Twitter to build back-end services. I've been programming in Scala seriously for about a year and a half now and it's positively ruined me for plain Java.</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/603801523479358423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=603801523479358423' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/603801523479358423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/603801523479358423'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/09/alexs-scala-talk-at-c42.html' title='Alex&apos;s Scala Talk at C4[2]'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-1309943230584924692</id><published>2008-07-30T13:33:00.000-07:00</published><updated>2008-07-30T13:43:02.705-07:00</updated><title type='text'>So I don't forget it.</title><content type='html'>A cheesy generic tcp proxy I found cruising the webs built out of &lt;code&gt;netcat&lt;/code&gt;, &lt;code&gt;fifo&lt;/code&gt;s, and &lt;code&gt;tee&lt;/code&gt;:

&lt;p&gt;
&lt;code&gt;
$ mkfifo backpipe&lt;br /&gt;
$ sudo nc -l 80 0&amp;lt;backpipe | tee -a inflow | nc localhost 8080| tee -a outflow 1&amp;gt;backpipe
&lt;/code&gt;
&lt;/p&gt;
This way you can also look at &lt;code&gt;inflow&lt;/code&gt; and &lt;code&gt;outflow&lt;/code&gt; to see what the actual contents were of the transaction.</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/1309943230584924692/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=1309943230584924692' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/1309943230584924692'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/1309943230584924692'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/07/so-i-dont-forget-it.html' title='So I don&apos;t forget it.'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-6066084111512566585</id><published>2008-06-29T18:30:00.000-07:00</published><updated>2008-06-29T18:42:40.862-07:00</updated><title type='text'>Simulating Byzantine failure with SIGSTOP</title><content type='html'>&lt;p&gt;
If your service relies on connecting to an internal network server and
that server isn't accepting connections, your client will obviously throw an
error. This happens often enough that you probably already check for this and do the right thing in your various projects. But what if the server is accepting connections but never
returning any data? This failure case is rare but very deadly.  Chet
mentioned that you could simulate this using &lt;tt&gt;SIGSTOP&lt;/tt&gt; so I
decided to whip up an experiment with &lt;tt&gt;memcached&lt;/tt&gt; as my victim.
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
stevej@t42p:~$ ps auxww |grep memcache
stevej    3451  0.0  0.0   2928  1872 pts/0    T    01:21   0:00 memcached -vv -p 11211
stevej@t42p:~$ kill -stop 3451
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
In another terminal:
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
stevej@t42p:~$ irb
irb(main):001:0&amp;gt; require 'rubygems'
=&amp;gt; true
irb(main):002:0&amp;gt; require 'memcache'
=&amp;gt; true
irb(main):003:0&amp;gt; CACHE = MemCache.new "localhost:11211"
=&amp;gt; &amp;lt;MemCache: 1 servers, 1 buckets, ns: nil, ro: false&amp;gt;
irb(main):004:0&amp;gt; CACHE.get("foo")
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
The client library happily hung for several hours while I did other
things. How can a process that's suspended not timeout incoming
connections?  Well, it's the kernel that services network requests and
the process itself is only reading the buffers. If you want proof,
look at this tcpdump output. Remember, the process has already been
suspended by the time I ran tcpdump here.
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
stevej@t42p:~$ sudo tcpdump -i lo port 11211
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 96 bytes
18:02:40.576255 IP localhost.48124 &amp;gt; localhost.11211: F 2018798159:2018798159(0) ack 2012359105 win 257 &amp;lt;nop,nop,timestamp 15455978 14281170&amp;gt;
18:02:40.577037 IP localhost.11211 &amp;gt; localhost.48124: . ack 1 win 256 &amp;lt;nop,nop,timestamp 15455979 15455978&amp;gt;
18:03:19.037410 IP localhost.35662 &amp;gt; localhost.11211: S 2731273926:2731273926(0) win 32792 &amp;lt;mss 16396,sackOK,timestamp 15465593 0,nop,wscale 7&amp;gt;
18:03:19.037435 IP localhost.11211 &amp;gt; localhost.35662: S 2723119696:2723119696(0) ack 2731273927 win 32768 &amp;lt;mss 16396,sackOK,timestamp 15465593 15465593,nop,wscale 7&amp;gt;
18:03:19.037449 IP localhost.35662 &amp;gt; localhost.11211: . ack 1 win 257 &amp;lt;nop,nop,timestamp 15465593 15465593&amp;gt;
18:03:19.037768 IP localhost.35662 &amp;gt; localhost.11211: P 1:10(9) ack 1 win 257 &amp;lt;nop,nop,timestamp 15465593 15465593&amp;gt;
18:03:19.037776 IP localhost.11211 &amp;gt; localhost.35662: . ack 10 win 256 &amp;lt;nop,nop,timestamp 15465593 15465593&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
So a connect timeout wouldn't help here, you need a recv timeout or
something else. Restarting your client process won't help at all,
it'll simply get stuck in the same place. In Ruby, the easiest thing
to do is to use the Timeout module. Sadly, it only has second
granularity but that's a lot better than hanging for several
hours. You can also set use Socket#setsockopt with a recv timeout if
you need finer grained timeout resolution.
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
stevej@t42p:~$ irb
irb(main):001:0&amp;gt; require 'rubygems'
=&amp;gt; true
irb(main):002:0&amp;gt; require 'memcache'
=&amp;gt; true
irb(main):003:0&amp;gt; CACHE = MemCache.new "localhost:11211"
=&amp;gt; &amp;lt;MemCache: 1 servers, 1 buckets, ns: nil, ro: false&amp;gt;
irb(main):004:0&amp;gt; require 'timeout'
=&amp;gt; false
irb(main):005:0&amp;gt; foo = Timeout::timeout(1) do
irb(main):006:1*   CACHE.get("foo")
irb(main):007:1&amp;gt; end
/usr/lib/ruby/1.8/timeout.rb:54:in `cache_get': execution expired (Timeout::Error)
        from /usr/lib/ruby/gems/1.8/gems/memcache-client-1.5.0/lib/memcache.rb:209:in `get'
        from (irb):6:in `irb_binding'
        from /usr/lib/ruby/1.8/timeout.rb:56:in `timeout'
        from (irb):5:in `irb_binding'
        from /usr/lib/ruby/1.8/irb/workspace.rb:52:in `irb_binding'
        from /usr/lib/ruby/1.8/irb/workspace.rb:52
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
Do you want to guess what happened when I sent &lt;tt&gt;SIGCONT&lt;/tt&gt; to memcache? My client processes, even the ones that had been hanging for hours, immediately returned with the expected data.
&lt;/p&gt;
&lt;p&gt;
The obvious thing to do is to write a new MemCache subclass decorating
all the calls to &lt;tt&gt;get&lt;/tt&gt;, &lt;tt&gt;put&lt;/tt&gt;, &lt;tt&gt;get_multi&lt;/tt&gt;, etc
with safer versions. Don't naively trust that the expected data made
it to the cache.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/6066084111512566585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=6066084111512566585' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/6066084111512566585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/6066084111512566585'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/06/simulating-byzantine-failure-with.html' title='Simulating Byzantine failure with SIGSTOP'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-3039676046970075339</id><published>2008-05-22T12:55:00.000-07:00</published><updated>2008-05-22T12:59:14.304-07:00</updated><title type='text'>More on Twitter!</title><content type='html'>Al3x wrote up a nice blog post &lt;a href="http://dev.twitter.com/2008/05/twittering-about-architecture.html"&gt;talking about the future of twitter.&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/3039676046970075339/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=3039676046970075339' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/3039676046970075339'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/3039676046970075339'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/05/more-on-twitter.html' title='More on Twitter!'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-3466801752925680881</id><published>2008-05-21T20:44:00.000-07:00</published><updated>2008-05-21T21:38:42.452-07:00</updated><title type='text'>How work's going?</title><content type='html'>&lt;p&gt;
Since I started working at Twitter last month, I put up a standard work disclaimer along the side. It &lt;strong&gt;always&lt;/strong&gt; applies.
&lt;/p&gt;
&lt;p&gt;
Jack posted on the company blog: &lt;a href="http://blog.twitter.com/2008/05/i-have-this-graph-up-on-my-screen-all.html"&gt;I have this graph up on my screen all the time. It should be flat. This week has been rough.&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
So we have open job postings for something called a &lt;a href="http://twitter.com/help/jobs#syseng"&gt;Systems Engineer&lt;/a&gt;, which is what I do at Twitter. Systems Engineering means building systems where graphs like that stay flat and where downtime means it was either planned or making sure that particular problem won't happen again (if it can be avoided: typical engineering trade-offs apply). 
&lt;/p&gt;
&lt;p&gt;
Our problems are really interesting, I think. Lots of users, lots of connections, lots of messages flowing through the system, lots of endpoints, and lots of details to keep straight. All of this needs to be turned into a cohesive system that's simple to reason about and to run in order for me to consider my job a success. It's a tall order but it's what I signed up to do. I've been watching Twitter for a long time (I'm user #150) so I walked into things with my eyes wide open.
&lt;/p&gt;
&lt;p&gt;
If you've been reading this blog for a while, you know that I'm more interested in engineering than hacking together a site. Thinking and then doing. Measuring and then reasoning. Making guesses and then testing them. There's a natural tension between cowboying around and Analysis Paralysis and you have to learn to walk that tightrope if you want to succeed and I think at Twitter, we work pretty hard to Do the Right Thing.
&lt;/p&gt;
&lt;p&gt;
I'm writing this quick post because we're looking for great people who are interested in engineering big systems and in helping to make Twitter the utility-class company we see ourselves as needing to be. If you think you either have the skills or can learn them, please send us your resume to jobs@twitter.com.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/3466801752925680881/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=3466801752925680881' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/3466801752925680881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/3466801752925680881'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/05/how-works-going.html' title='How work&apos;s going?'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-1381376733325481333</id><published>2008-05-19T21:26:00.001-07:00</published><updated>2008-05-19T21:30:25.259-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dtrace'/><title type='text'>Fun DTrace script</title><content type='html'>&lt;pre&gt;
&lt;code&gt;
#!/usr/sbin/dtrace -s

syscall:::entry
/pid == $1/
{
 @sys[probefunc, ustack()] = count();
}

END {
    trunc(@sys, 2);
}
&lt;/code&gt;
&lt;/pre&gt;

Tells you the 2 most often called system call/stack trace pair. Running it against firefox 3 beta while using Google Reader shows:

&lt;pre&gt;
&lt;code&gt;
$ sudo ./syscalldist.d 240
dtrace: script './syscalldist.d' matched 428 probes
^C
CPU     ID                    FUNCTION:NAME
  1      2                             :END 

  munmap                                            
              libSystem.B.dylib`munmap$UNIX2003+0xa
              libSystem.B.dylib`free+0x6a
              CoreGraphics`CGEventCreateFromDataAndSource+0xbce
              CoreGraphics`CGSDecodeEventRecord+0x6a
              CoreGraphics`CGSDispatchDatagramsFromStream+0x28f
              CoreGraphics`snarfEvents+0x12a
              CoreGraphics`CGSGetNextEventRecordInternal+0x9f
              CoreGraphics`CGEventCreateNextEvent+0x2c
              HIToolbox`PullEventsFromWindowServerOnConnection(unsigned int, unsigned char)+0x58
              CoreFoundation`__CFMachPortPerform+0x75
              CoreFoundation`CFRunLoopRunSpecific+0xf51
              CoreFoundation`CFRunLoopRunInMode+0x58
              HIToolbox`RunCurrentEventLoopInMode+0x11b
              HIToolbox`ReceiveNextEventCommon+0x176
              HIToolbox`BlockUntilNextEventMatchingListInMode+0x6a
              AppKit`_DPSNextEvent+0x291
              AppKit`-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]+0x80
              AppKit`-[NSApplication run]+0x31b
              XUL`JSD_GetValueForObject+0xad6ce
              XUL`XRE_GetFileFromPath+0x61c563
              961
  mmap                                              
              libSystem.B.dylib`mmap+0xa
              libSystem.B.dylib`large_and_huge_malloc+0xcb
              libSystem.B.dylib`szone_malloc+0x1cf
              libSystem.B.dylib`malloc_zone_malloc+0x51
              libSystem.B.dylib`malloc+0x37
              CoreGraphics`CGEventCreateFromDataAndSource+0x15e
              CoreGraphics`CGSDecodeEventRecord+0x6a
              CoreGraphics`CGSDispatchDatagramsFromStream+0x28f
              CoreGraphics`snarfEvents+0x12a
              CoreGraphics`CGSGetNextEventRecordInternal+0x9f
              CoreGraphics`CGEventCreateNextEvent+0x2c
              HIToolbox`PullEventsFromWindowServerOnConnection(unsigned int, unsigned char)+0x58
              CoreFoundation`__CFMachPortPerform+0x75
              CoreFoundation`CFRunLoopRunSpecific+0xf51
              CoreFoundation`CFRunLoopRunInMode+0x58
              HIToolbox`RunCurrentEventLoopInMode+0x11b
              HIToolbox`ReceiveNextEventCommon+0x176
              HIToolbox`BlockUntilNextEventMatchingListInMode+0x6a
              AppKit`_DPSNextEvent+0x291
              AppKit`-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]+0x80
              997
&lt;/pre&gt;
&lt;/code&gt;
Thrilling, I know!</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/1381376733325481333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=1381376733325481333' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/1381376733325481333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/1381376733325481333'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/05/fun-dtrace-script.html' title='Fun DTrace script'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-3156855466887560153</id><published>2008-05-18T20:33:00.000-07:00</published><updated>2008-05-19T21:45:06.746-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dtrace'/><title type='text'>DTrace for Java 6 on Leopard</title><content type='html'>&lt;p&gt;
When Java 6 for Leopard was released a few weeks ago, one thing that nobody seemed to notice was that Java now had DTrace probes on par with Java on Solaris.
&lt;/p&gt;
&lt;p&gt;
What you expect is there:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.solarisinternals.com/wiki/index.php/DTrace_Topics_Java"&gt;DTrace Topics: Java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://java.sun.com/javase/6/docs/technotes/guides/vm/dtrace.html"&gt;DTrace Probes in HotSpot VM&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
With one exception: &lt;code&gt;jstack&lt;/code&gt; doesn't appear to work. &lt;code&gt;ustack&lt;/code&gt; works fine.
&lt;/p&gt;

&lt;p&gt;
&lt;pre&gt;
&lt;code&gt;
$ sudo dtrace -x jstackstrsize=2048 -n 'syscall::read:entry /execname == "java"/ { jstack(); }' 

dtrace: description 'syscall::read:entry ' matched 1 probe
CPU     ID                    FUNCTION:NAME
  3  17600                       read:entry 

  2  17600                       read:entry 

  3  17600                       read:entry 

  3  17600                       read:entry 

  2  17600                       read:entry 

  2  17600                       read:entry 

  2  17600                       read:entry 

  2  17600                       read:entry
&lt;/code&gt;
&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;
There should be java stack traces under each read:entry line. (This is true even with &lt;code&gt;-XX:+ExtendedDTraceProbes&lt;/code&gt; enabled)
&lt;/p&gt;

&lt;p&gt;
I used robey's scarling for my guinea pig and had a lot of fun poking around at it with dtrace.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/3156855466887560153/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=3156855466887560153' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/3156855466887560153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/3156855466887560153'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/05/dtrace-for-java-6-on-leopard.html' title='DTrace for Java 6 on Leopard'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-2679085493260527358</id><published>2008-05-11T10:32:00.000-07:00</published><updated>2008-05-11T10:41:35.891-07:00</updated><title type='text'>John McCarthy has a good sense of humor</title><content type='html'>From an informal talk he gave at Stanford recently that was written up in &lt;a href="http://news.ycombinator.com/item?id=185348"&gt;Hacker News&lt;/a&gt;:

&lt;blockquote&gt;
&lt;pre&gt;
Q. Can computers know?

A. This is largely a question of definition. If a camera looked at a table, we could
say it "knows" that there are four containers of liquid on the table (which was true).

Q. Is there any definition of "know" in which computers cannot succeed?

A. Well, I suppose the biblical sense.

Q. Ha, well, what makes you think that?

A. They don't satisfy the necessary axioms (laughter)
&lt;/pre&gt;
&lt;/blockquote&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/2679085493260527358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=2679085493260527358' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/2679085493260527358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/2679085493260527358'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/05/john-mccarthy-has-good-sense-of-humor.html' title='John McCarthy has a good sense of humor'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-6377490104933287377</id><published>2008-04-21T20:08:00.000-07:00</published><updated>2008-04-21T20:12:44.217-07:00</updated><title type='text'>What are you doing?</title><content type='html'>reading @&lt;a href="http://blog.twitter.com/2008/04/welcome-john-and-steve.html"&gt;biz&lt;/a&gt; out me as a Twitter employee.</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/6377490104933287377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=6377490104933287377' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/6377490104933287377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/6377490104933287377'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/04/what-are-you-doing.html' title='What are you doing?'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-5210323149609574287</id><published>2008-04-15T09:36:00.000-07:00</published><updated>2008-04-20T08:19:37.714-07:00</updated><title type='text'>curious what delicious is saying about something?</title><content type='html'>&lt;a href="javascript:location.href='http://del.icio.us/url/check?&amp;url='+encodeURIComponent(location.href)"&gt;Here's a bookmarklet that checks the current URL you're visiting with del.icio.us&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/5210323149609574287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=5210323149609574287' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/5210323149609574287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/5210323149609574287'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/04/curious-what-delicious-is-saying-about.html' title='curious what delicious is saying about something?'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-4527552100593290558</id><published>2008-04-13T11:41:00.000-07:00</published><updated>2008-04-13T11:52:19.500-07:00</updated><title type='text'>My first Thrift app</title><content type='html'>&lt;p&gt;
When you find yourself working on big systems, a useful technique is
to decompose it into services. Moving from a big monolithic server to
a bunch of separate services can be a big challenge but if you had
foresight, many of your services were already decoupled in your system
from day 1 even though you were deploying it monolithicly.
&lt;/p&gt;
&lt;p&gt;
A common technique for decomposing services is using RPC. At Google, we
used protocol buffers, which were briefly descibed in the &lt;a href="http://labs.google.com/papers/sawzall-sciprog.pdf"&gt;Sawzall&lt;/a&gt;
paper.
&lt;/p&gt;
&lt;p&gt;
Basically, you describe your data and the interface that process the
data in a language-independent format (a DDL, essentially) and use code
generators to turn that DDL into set of objects in your target
langauge that can create and send those structures over the wire. This
makes it easy to write servers in one language and clients in another
and the generated code deals with serialization.
&lt;/p&gt;
&lt;p&gt;
I found that using a DDL to describe your code and services was really
nice. When building a new service, you could simply reference your DDL
in the design doc and have a meanginful discussion about the service
without getting into the details of how it would be written until you had
the semantics nailed down.
&lt;/p&gt;

&lt;p&gt;
Facebook, as they were growing, decided to move to a homegrown binary
RPC mechanism similar to protocol buffers called &lt;a href="http://developers.facebook.com/thrift/"&gt;Thrift&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
Let's say I wanted to write a simple service that would tell the
client what time it was on the server. Here would be the DDL file
describing both the data and the service plus a little extra to help
out the generated code files.
&lt;/p&gt;
&lt;pre name="code" class="thrift"&gt;
# time.thrift
namespace java tserver.gen
namespace ruby TServer.Gen

typedef i64 Timestamp

service TimeServer {
  // Simply returns the current time.
  Timestamp time()
}
&lt;/pre&gt;

&lt;p&gt;
After running &lt;tt&gt;thrift --gen java --gen rb time.thrift&lt;/tt&gt; on the
file, I'd have an interface and server that I could implement in Java
and a client that I could use in Ruby.
&lt;/p&gt;
&lt;p&gt;
Based on the generated java code, I could write a short server in Scala:
&lt;/p&gt;

&lt;pre name="code" class="scala"&gt;
&lt;code&gt;
package tserver

import tserver.gen._
import com.facebook.thrift.TException
import com.facebook.thrift.TProcessor
import com.facebook.thrift.TProcessorFactory
import com.facebook.thrift.protocol.TProtocol
import com.facebook.thrift.protocol.TProtocolFactory
import com.facebook.thrift.transport.TServerTransport
import com.facebook.thrift.transport.TServerSocket
import com.facebook.thrift.transport.TTransport
import com.facebook.thrift.transport.TTransportFactory
import com.facebook.thrift.transport.TTransportException
import com.facebook.thrift.server.TServer
import com.facebook.thrift.server.TThreadPoolServer
import com.facebook.thrift.protocol.TBinaryProtocol

/**
 * TimeServer.time returns the current time according to the server.
 */
class TimeServer extends TimeServer.Iface {
  override def time: Long = {
    val now = System.currentTimeMillis
    println("somebody just asked me what time it is: " + now)
    now
  }
}

object SimpleServer extends Application {
  try {
    val serverTransport = new TServerSocket(7911)
    val processor = new TimeServer.Processor(new TimeServer())
    val protFactory = new TBinaryProtocol.Factory(true, true)
    val server = new TThreadPoolServer(processor, serverTransport,
      protFactory)
    
    println("starting server")
    server.serve();     
  } catch { 
    case x: Exception =&amp;gt; x.printStackTrace();
  }
}
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;
(Geez, most of that space was taken up in my obsessive need to separate
out all my imports. You can thank Google for that bit of OCD.)
&lt;/p&gt;
&lt;p&gt;
The client is even shorter:
&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
&lt;code&gt;
#!/usr/bin/ruby
$:.push('~/thrift/lib/rb/lib')
$:.push('../gen-rb')

require 'thrift/transport/tsocket'
require 'thrift/protocol/tbinaryprotocol'
require 'TimeServer'

transport = TBufferedTransport.new(TSocket.new("localhost", 7911))
protocol = TBinaryProtocol.new(transport)
client = TimeServer::Client.new(protocol)

transport.open()

puts "I wonder what time it is. Let's ask!"
puts client.time()
&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;
The ruby client took about 20ms to get an answer from the Scala server.
&lt;/p&gt;
&lt;p&gt;
Thrift advantages:&lt;br /&gt;
&lt;ul&gt;
  &lt;li&gt;Pipelined connections means you spend less time in connection setup/teardown and TCP likes longer-lived connections.&lt;/li&gt;
  &lt;li&gt;Asynchronous requests. Asynchronous replies would be nice too but would be trickier to use.&lt;/li&gt;
  &lt;li&gt;Binary representation is much more efficient to transmit and process than, say, XML.&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
Thrift drawbacks: &lt;br /&gt;
&lt;ul&gt;
  &lt;li&gt;Integrating generated source into your build system can be tricky. 
      Typically, you rarely have to regenerate your stubs but debugging generated code can be a huge pain.&lt;/li&gt;
  &lt;li&gt;It's Java server should move away from ServerSocket to NIO for increased throughput. 
      That's probably not more than a week's work as long as the existing code isn't too tightly coupled.&lt;/li&gt;
  &lt;li&gt;Currently it doesn't build cleanly on the Mac. I did some work and got it working but I don't think it's used
      extensively on the Mac so if that's your primary platform, you should be prepared to send them patches from time to time.&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
If you're looking to move towards decoupled services, Thrift is worth a hard look.
&lt;/p&gt;
&lt;p&gt;
Here's a tarball with my &lt;a href="http://saladwithsteve.com//code/timeserver.tar.gz"&gt;time
server&lt;/a&gt;. It contains all the generated code as well as
libthrift.jar and a Makefile to run the example server.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/4527552100593290558/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=4527552100593290558' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/4527552100593290558'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/4527552100593290558'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/04/my-first-thrift-app.html' title='My first Thrift app'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-444274540799770784</id><published>2008-04-06T18:25:00.000-07:00</published><updated>2008-04-06T18:53:08.429-07:00</updated><title type='text'>GVN and gold</title><content type='html'>&lt;p&gt;
Two things popped up on my radar recently:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://code.google.com/p/gvn/"&gt;gvn&lt;/a&gt;, Google's wrappers around Subversion to help them work in their code-review heavy workflow. Even if you're not into code reviews, &lt;code&gt;tkdiff&lt;/code&gt; integration is a nice improvement over &lt;code&gt;colordiff&lt;/code&gt; or &lt;code&gt;FileMerge&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.airs.com/blog/archives/164"&gt;gold&lt;/a&gt;, a new ELF linker built with giant binaries in mind. When you're building 900MB+ static binaries routinely, linking speed matters. gold claims to be at least 5x faster currently. Even if you have a massive distcc cluster, linking is still serial. One of gold's future design goals is to be concurrent and that would be pretty awesome. Imagine how fast I could link with a concurrent linker on my 8-core Mac Pro! Not that using an ELF linker under Leopard helps much since OS X uses Mach-O binaries but hey, there's always cross-compiling.
&lt;/p&gt;
&lt;p&gt;
BTW, Ian Lance Taylor, the author of gold, has &lt;a href="http://www.airs.com/blog/archives/38"&gt;an excellent series of blog articles on linkers.&lt;/a&gt;
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/444274540799770784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=444274540799770784' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/444274540799770784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/444274540799770784'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/04/gvn-and-gold.html' title='GVN and gold'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-6855696975621938799</id><published>2008-03-14T09:45:00.000-07:00</published><updated>2008-03-14T09:51:06.166-07:00</updated><title type='text'>It's not just you</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://saladwithsteve.com/uploaded_images/down-791122.png"&gt;&lt;img alt="[downorjustyou]" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://saladwithsteve.com/uploaded_images/down-791087.png" border="0" alt="" /&gt;&lt;/a&gt;

Since it's back now, check out &lt;a href="http://downforeveryoneorjustme.com/"&gt;al3x's neat new site&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/6855696975621938799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=6855696975621938799' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/6855696975621938799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/6855696975621938799'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/03/its-not-just-you.html' title='It&apos;s not just you'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-8257988765334743789</id><published>2008-03-01T21:20:00.000-08:00</published><updated>2008-03-01T21:58:51.426-08:00</updated><title type='text'>White People think Indian Food is Hot.</title><content type='html'>I just finished reading a &lt;a href="http://www.amazon.com/Buddha-Penguin-Lives-Karen-Armstrong/dp/0670891932"&gt;secular biography of the Buddha&lt;/a&gt; recently and Stacy and I were chatting about the Buddha's magic &lt;a href="http://en.wikipedia.org/wiki/Iddhi"&gt;Iddhi&lt;/a&gt; powers which he acquired as a highly skilled yogin. She said her first impressions of yoga came from watching Dhalsim's stretchy limbs in Street Fighter II. As a kid, she figured there must be some small kernel of truth to that. Equally stupid is that, as a kid, that's exactly where I got my first impressions of Indian food from. The manual says that Dhalsim got his "Yoga Flame" from the hot curry he ate.

&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/c6Y7HjZCRfo"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/c6Y7HjZCRfo" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;

I couldn't imagine a food so hot that you felt like you were breathing fire. Wasn't that a bad meal? Wouldn't you ask for your money back? How could a place like that stay in business? These types of comics didn't help, either:
&lt;p&gt;
&lt;a href="http://www.cartoonstock.com/directory/h/hot_foods_gifts.asp"/&gt;&lt;img src="http://www.cartoonstock.com/newscartoons/cartoonists/mfl/lowres/mfln343l.jpg"/&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
This clichéd comedic target was common in the magazines that adults read when I was a kid, the particular one I've always remembered had a guy running to the bathroom with flames coming out of his pants in a restaurant with a clearly Indian name. At 10, I recognized the dangers that the comic bravely warned me of. I knew that often political comics took aim at targets that the media didn't dare attack and figured this must be the same.
&lt;/p&gt;
&lt;p&gt;
The first time somebody actually offered me Indian food, I was very nervous. It had a dangerously bright orange color but smelled and tasted great. Thankfully fire did not come out of my ass and set my pants on fire.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/8257988765334743789/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=8257988765334743789' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/8257988765334743789'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/8257988765334743789'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/03/white-people-think-indian-food-is-hot.html' title='White People think Indian Food is Hot.'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-4668932024792123408</id><published>2008-02-17T09:58:00.000-08:00</published><updated>2008-02-17T10:47:26.004-08:00</updated><title type='text'>JavaScript undefined vs. null</title><content type='html'>&lt;p&gt;
I was reading a modern, popular book on JavaScript last night and was disappointed by the handling of null. The author started out doing a lot of checking like:
&lt;/p&gt;
&lt;code&gt;
if (foo == null) {
&amp;nbsp;&amp;nbsp;alert('foo is not set.');
}
&lt;/code&gt;
&lt;p&gt;
Then told the reader that they could just remove the &lt;code&gt;== null&lt;/code&gt; because javascript knows you mean &lt;code&gt;"== null"&lt;/code&gt;
&lt;/p&gt;
&lt;p&gt;
What?! This isn't why you don't check for equality with null. It's because &lt;code&gt;foo == null&lt;/code&gt; doesn't even remotely do what most people think it does in this context.
&lt;/p&gt;
&lt;p&gt;
It's a commonly held belief that uninitialized properties in JavaScript are set to &lt;code&gt;null&lt;/code&gt; as default values. People believe this mostly for 2 reasons: 1) &lt;code&gt;foo == null&lt;/code&gt; returns true if foo is undefined and 2) authors don't teach JavaScript properly.
&lt;/p&gt;
&lt;p&gt;
A property, when it has no definition, is undefined. Put that way, it's pretty obvious.
&lt;/p&gt;
&lt;p&gt;
&lt;code&gt;null&lt;/code&gt; is an object. It's type is &lt;code&gt;null&lt;/code&gt;. &lt;code&gt;undefined&lt;/code&gt; is not an object, it's type is &lt;code&gt;undefined&lt;/code&gt;. That part is less obvious.
&lt;/p&gt;
&lt;p&gt;
The real trouble is that &lt;code&gt;==&lt;/code&gt; does type coercion. &lt;code&gt;===&lt;/code&gt; checks for both type and value and is the most intuitive form of equality in JavaScript, in my opinion.
&lt;/p&gt;
&lt;p&gt;
I fired up a &lt;a href="http://www.billyreisinger.com/jash/"&gt;Jash&lt;/a&gt; console to hopefully clear things up for you.
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
&amp;gt;&amp;gt; window.hello
null
&amp;gt;&amp;gt; window.hello.something
window.hello has no properties
&amp;gt;&amp;gt; window.hello == null
true
&amp;gt;&amp;gt; window.hello === null
false
&amp;gt;&amp;gt; window.hello === undefined
true
&amp;gt;&amp;gt; if (window.hello) { alert('truthy'); } else { alert('falsy'); } // will print falsy.
null
&amp;gt;&amp;gt; window.hello == undefined
true
&amp;gt;&amp;gt; null == undefined
true // there's the rub, sir.
&amp;gt;&amp;gt; null
null
&amp;gt;&amp;gt; undefined
null
&amp;gt;&amp;gt; typeof null
object
&amp;gt;&amp;gt; typeof undefined
undefined
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
So people write
&lt;pre&gt;
if (foo == null) {
&amp;nbsp;&amp;nbsp; foo = "Joe";
}
&lt;/pre&gt;

When what they really mean is
&lt;pre&gt;
if (!foo) {
&amp;nbsp;&amp;nbsp; foo = "Joe";
}
&lt;/pre&gt;

If you find yourself with a lot of &lt;code&gt;null&lt;/code&gt; checks in your JavaScript, set aside some time and watch Douglas Crockford's &lt;a href="http://video.yahoo.com/watch/111593"&gt;"The JavaScript Programming Language"&lt;/a&gt; talk on Yahoo Video. It's part 1 of a 3-part series of excellent and enlightening talks.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/4668932024792123408/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=4668932024792123408' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/4668932024792123408'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/4668932024792123408'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/02/javascript-undefined-vs-null.html' title='JavaScript undefined vs. null'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-7025017327244635511</id><published>2008-02-10T20:55:00.000-08:00</published><updated>2008-02-10T21:08:22.664-08:00</updated><title type='text'>Ubuntu on the Mac Pro</title><content type='html'>&lt;p&gt;
Last year I bought a Mac Pro to replace my aging Linux PC. It was a pretty significant upgrade, from a HyperThreaded 2.5Ghz Pentium 4 to a dual-processor, quad-core 3Ghz Xeon with 8G of RAM. Leopard is nice but I wanted to try and get Ubuntu running on it.
&lt;/p&gt;
&lt;p&gt;
Here's the setup, I have 4 drives:
&lt;ul&gt;
&lt;li&gt;750G - Leopard&lt;/li&gt;
&lt;li&gt;200G - Windows&lt;/li&gt;
&lt;li&gt;750G - Backups&lt;/li&gt;
&lt;li&gt;750G - To be Ubuntu&lt;/li&gt;
&lt;/ul&gt;
and wanted to install Ubuntu on the 4th drive.
&lt;/p&gt;

&lt;p&gt;
Here are the basic steps I followed:
&lt;ol&gt;
&lt;li&gt; Install &lt;a href="http://refit.sourceforge.net/"&gt;refit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; Install from LiveCD (7.10)&lt;/li&gt;
&lt;li&gt; Select manual Manual Partition and from the advanced options, choose hd3,0. I setup my disk with one ext3 partition and 1 swap partition.&lt;/li&gt;
&lt;li&gt; After install, boot the linux disk from the refit menu&lt;/li&gt;
&lt;li&gt; Grub will get to stage 1.5, you will see the menu but be unable to start the system, it will complain about unknown partition type&lt;/li&gt;
&lt;li&gt; hit 'c'&lt;/li&gt;
&lt;/ol&gt;
&lt;/p&gt;
&lt;p&gt;
Here's a transcript of my tinkering with grub to find the right drive with my initrd and kernel on it so I could boot my fancy Apple-branded Linux machine.
&lt;/p&gt;
&lt;pre&gt;
grub&gt; root (hd&amp;lt;TAB&amp;gt;
&lt;/pre&gt;
showed a bunch of drives with various partitions but most importantly showed that hd0,0 had the Linux partition I was looking for. Even though with the ubuntu installer, we told it to use hd3, here we use hd0. the boot manager has shuffled the order of the drives. Telling the ubuntu installer to use hd0,0 will only result in an unbootable disk.
&lt;pre&gt;
grub&gt; root (hd0,0)
grub&gt; kernel /boot/vmlinuz&amp;lt;TAB&amp;gt;
&lt;/pre&gt;
will show you some vmlinuz files. typically just the one ubuntu installed. pick it.
&lt;pre&gt;
grub&gt; kernel /boot/vmlinuz-2.6.22-14-generic root=/dev/sdd1 ro
grub&gt; initrd /boot/initrd.img-2.6.22-14-generic
grub&gt; boot
&lt;/pre&gt;
&lt;p&gt;
Now your system will boot. Edit your /boot/grub/menu.lst to point the root (hd0,0)
&lt;/p&gt;
&lt;p&gt;
Now reboot and you will be in Ubuntu. Your wifi adapter won't work. &lt;a href="https://help.ubuntu.com/community/WifiDocs/Driver/bcm43xx/Feisty_No-Fluff#head-bc33832c0547766a33c3a84f13f971ca757b2851"&gt;Follow these steps to enable ndiswrapper to use the windows drivers.&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
I used a usb thumb drive to move the windows drivers zip file between my laptop and desktop.
&lt;/p&gt;
&lt;p&gt;
Once you have networking up, don't forget to enable ssh so you can login in case you screw up your X config. 
&lt;/p&gt;
&lt;p&gt;
Edit /etc/apt/sources.list to include what you might want.
&lt;/p&gt;

&lt;p&gt;
I have an ATI Radeon X1950 Pro video card. To get it working, I simply installed &lt;a href="http://albertomilone.com/nvidia_scripts1.html"&gt;Envy&lt;/a&gt; which downloaded the right drivers and installed them for me. 
&lt;/p&gt;
&lt;p&gt;
But it didn't span monitors, they were just clones so I ran aticonfig (which &lt;a href="http://albertomilone.com/nvidia_scripts1.html"&gt;Envy&lt;/a&gt; installed for me)
&lt;pre&gt;
aticonfig --initial=dual-head --overlay-on=1
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
And we were good to go.
&lt;/p&gt;

&lt;p&gt;
Banshee imported all my music from my iPod after converting it's database from an iTunes format it didn't recognize.
&lt;/p&gt;
&lt;p&gt;
Using hibernate left the Mac's wifi adapter in a weird state. Rebooting it didn't help but booting into OS X and back into Linux corrected the wifi card.
&lt;/p&gt;
&lt;p&gt;
The fan speed still isn't quite right, various fans will become louder and softer at odd intervals. I will try monkeying with lm-sensors later.
&lt;/p&gt;
&lt;p&gt;
I have nice smooth fonts by running Emacs 23 from &lt;a href="http://peadrop.com/blog/2007/01/06/pretty-emacs/"&gt;Alexandre Vassalotti&lt;/a&gt;'s repo and the &lt;a href="http://www.ghostscript.com/~raph/type/myfonts/inconsolata.html"&gt;Inconsolata&lt;/a&gt; font for programming.
&lt;/p&gt;
&lt;p&gt;
Overall, it's a great Linux machine and maybe one day it won't be so much trouble to get running. Hopefully my instructions will help you get it up and running. 
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/7025017327244635511/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=7025017327244635511' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/7025017327244635511'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/7025017327244635511'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2008/02/ubuntu-on-mac-pro.html' title='Ubuntu on the Mac Pro'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-6037078286459074825</id><published>2007-11-19T22:32:00.000-08:00</published><updated>2007-11-19T22:39:23.730-08:00</updated><title type='text'>Lift Tutorial</title><content type='html'>&lt;p&gt;
I've been working on &lt;a href="http://liftweb.net/"&gt;lift&lt;/a&gt; quite a bit lately, fitting it in with some other projects and my obsessive need for football. (Both NFL and Madden)
&lt;/p&gt;
&lt;p&gt;
If you're interested in trying it out, give the &lt;a href="http://liftweb.net/index.php/HowTo_start_a_new_liftwebapp"&gt;lift tutorial&lt;/a&gt; I wrote a try. Please &lt;a href="http://groups.google.com/group/liftweb"&gt;drop us a note&lt;/a&gt; if you have any problems.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/6037078286459074825/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=6037078286459074825' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/6037078286459074825'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/6037078286459074825'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2007/11/lift-tutorial.html' title='Lift Tutorial'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-4786591912309100020</id><published>2007-10-21T16:57:00.000-07:00</published><updated>2007-10-21T17:29:14.456-07:00</updated><title type='text'>Tomato Wifi!</title><content type='html'>&lt;p&gt;
While doing that podcast with Daniel, I noticed I was seeing 30% or so packet loss on my wifi network. After rebooting some equipment and keeping an eye on things, I decided to scrap my faulty Airport Express base stations and replace them with &lt;a href="http://www.linksys.com/servlet/Satellite?c=L_Product_C2&amp;childpagename=US%2FLayout&amp;cid=1133202177241&amp;pagename=Linksys%2FCommon%2FVisitorWrapper"&gt;Linksys WRT54GL&lt;/a&gt;s running a custom opensource firmware called &lt;a href="http://www.polarcloud.com/tomato"&gt;Tomato&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;
While the instructions are good, they assume you already have the router up and running. The first thing I realized was to throw the windows install cd away and just plug my mac into the switch on the back. The router will be listening on &lt;a href="http://192.168.1.1"&gt;192.168.1.1:80&lt;/a&gt; with a username and password of admin/admin. &lt;a href="http://en.wikibooks.org/wiki/Tomato_Firmware"&gt;The instructions&lt;/a&gt; will carry you from that point.
&lt;/p&gt;
&lt;p&gt;
I have a 3 story house so I bought two routers and bridged them together with &lt;a href="http://en.wikipedia.org/wiki/Wireless_Distribution_System"&gt;WDS&lt;/a&gt;. My only complaint is that Tomato's WDS &lt;a href="http://www.polarcloud.com/tomatofaq#how_do_i_use_wds"&gt;is difficult to setup.&lt;/a&gt; The Airport Express admin utility did a wonderful job of easily bridging the two aiport express base stations together.
&lt;/p&gt;
&lt;p&gt;
Except for one of the routers dying after only a few days, which Amazon was nice enough to replace for free with next-day shipping, things have been great on Tomato. 4 bars everywhere I go in the house.
&lt;/p&gt;
&lt;small&gt;[Hat tip to &lt;a href="http://www.somebits.com/weblog/tech/good/tomato-firmware.html"&gt;Nelson for the recommendation.&lt;/a&gt;]&lt;/small&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/4786591912309100020/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=4786591912309100020' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/4786591912309100020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/4786591912309100020'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2007/10/tomato-wifi.html' title='Tomato Wifi!'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-833032289943435889</id><published>2007-10-06T21:33:00.001-07:00</published><updated>2007-10-06T21:36:29.417-07:00</updated><title type='text'>My interview with Daniel Brusilovsky</title><content type='html'>Daniel runs the Apple Universe podcast and &lt;a href="http://appleuniverse.mypodcast.com/2007/10/Apple_Universe_Episode_61_Blogging_with_Blogger-46676.html"&gt;interviewed me today&lt;/a&gt;. We had a fun chat, check it out!</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/833032289943435889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=833032289943435889' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/833032289943435889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/833032289943435889'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2007/10/my-interview-with-daniel-brusilovsky.html' title='My interview with Daniel Brusilovsky'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-343462069046631543</id><published>2007-09-28T23:21:00.000-07:00</published><updated>2007-09-28T23:43:16.180-07:00</updated><title type='text'>What's next?</title><content type='html'>&lt;p&gt;
&lt;a href="http://www.allthingsdistributed.com/"&gt;Werner Vogels&lt;/a&gt; on &lt;a href="http://en.wikipedia.org/wiki/Michael_Stonebraker"&gt;Michael Stonebraker&lt;/a&gt;'s 50X challenge:
&lt;/p&gt;

&lt;p&gt;
&lt;a href="http://www.allthingsdistributed.com/2007/09/50_x.html"&gt;&lt;blockquote&gt;
I like this challenge, given that 50X is likely to be able to make impact, where 2-4X in general can be easily compensated for by the next generation hardware. But something bugs me about the challenge and also about some of the demonstrations in the papers; 50X is still focused on scaling-up, just as many of the current database systems do, instead of scaling out, which is what the world really needs. The evidence in the paper is indeed about single box performance. This continuing N=1 thinking will never yield systems that can break through the current scalability limitations of enterprise software, regardless whether it runs 50 times faster or not.
&lt;/blockquote&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
I couldn't agree more. It's exciting to see so many people arguing for new kinds of databases, especially distributed databases. Why do I hate on relational databases? It's not the relational part, it's the part where they fail at 3am and wake me up. Joins are nice but I need my beauty sleep.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/343462069046631543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=343462069046631543' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/343462069046631543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/343462069046631543'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2007/09/whats-next.html' title='What&apos;s next?'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3187374.post-7781520936486448786</id><published>2007-09-21T22:39:00.001-07:00</published><updated>2007-09-22T00:01:20.707-07:00</updated><title type='text'>43 Folders makes the switch...</title><content type='html'>&lt;p&gt;
that I expect a number of others to follow. They just switched from a blogging system to a content management system. Lots of sites that have daily articles aren't blogs but  until recently it was easier to have separate blogs and auxiliary sites than to setup a full-blown CMS. These sites are easy to distinguish: they'll have forums, wikis, or other miscellany that aren't simply chronologically ordered notes of interest. For instance, 43 Folders has a Forum, Job Board, and sub-sites like gtd and &lt;a href="http://www.43folders.com/izero/"&gt;Inbox Zero&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
I always assumed CMS's would get easier to setup and use and some of the more popular sites would switch to them. I fully expect this to become a growing trend and am glad to see traditional blogging tools start to get some competition for serious users.
&lt;/p&gt;
&lt;small&gt;Update: Earlier, I mentioned in this post that &lt;a href="http://photomatt.net/"&gt;Matt&lt;/a&gt; pointed to a site that switched from WordPress to a CMS. I misread it. It was the other way around. Thanks, Jeremy. I hate it when you're right.&lt;/small&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/7781520936486448786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=3187374&amp;postID=7781520936486448786' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/7781520936486448786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3187374/posts/default/7781520936486448786'/><link rel='alternate' type='text/html' href='http://saladwithsteve.com/2007/09/43-folders-makes-switch.html' title='43 Folders makes the switch...'/><author><name>Steve Jenson</name><uri>http://www.blogger.com/profile/09686593839106107926</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry></feed>