<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>Apparatus</title>
	
	<link>http://www.apparatusproject.org/blog</link>
	<description>Make stuff to do things</description>
	<lastBuildDate>Thu, 17 Sep 2009 16:18:12 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Apparatus" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="apparatus" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Twisted.web vs Tornado, part deux</title>
		<link>http://www.apparatusproject.org/blog/2009/09/twisted-web-vs-tornado-part-deux/</link>
		<comments>http://www.apparatusproject.org/blog/2009/09/twisted-web-vs-tornado-part-deux/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 16:18:12 +0000</pubDate>
		<dc:creator>Matt Heitzenroder</dc:creator>
				<category><![CDATA[apparatus]]></category>

		<guid isPermaLink="false">http://www.apparatusproject.org/blog/?p=353</guid>
		<description><![CDATA[The first time I conducted a performance test between Twisted.web and Tornado, the results were not very meaningful in retrospect.  I have three good reasons for redoing the performance tests:

Apache Benchmark errors &#8211; the twisted.web test would crash ab once the concurrency reached a certain level, thus not revealing the real performance of twisted.web.
Unrealistic server [...]]]></description>
			<content:encoded><![CDATA[<p class="dropcap-first"><span style="background-color: #ffffff;">The <a href="http://www.apparatusproject.org/blog/2009/09/twisted-web-vs-tornado-performance-test/">first time I conducted a performance test between Twisted.web and Tornado</a>, the results were not very meaningful in retrospect.  I have three good reasons for redoing the performance tests:</span></p>
<ol>
<li>Apache Benchmark errors &#8211; the twisted.web test <a href="http://www.apparatusproject.org/blog/2009/09/twisted-web-vs-tornado-performance-test/#comment-16540725">would crash ab</a> once the concurrency reached a certain level, thus not revealing the real performance of twisted.web.</li>
<li>Unrealistic server environment &#8211; I did test of my MacBookPro, not a dedicated server.</li>
<li>Controversy &#8211; the ensuing conversation of twisted.web vs tornado warrants a more accurate test with better tools and hardware.</li>
</ol>
<p>This time, I performed the test with the aid of my friend <a href="http://www.travisswicegood.com/">Travis</a> (thank you!) using <a href="http://grinder.sourceforge.net/">The Grinder</a>, a legitimate load testing tool and several virtual machines from the <a href="http://www.rackspacecloud.com/">Rackspace Cloud</a>.  The servers were Ubuntu Jaunty 9.04 with 2GB or RAM and quad-core 2GHz processors.</p>
<p><a href="http://grinder.sourceforge.net/">The Grinder</a> script that I used to conduct the test just did a simple request. The Grinder <a href="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/grinder.py">test</a> and <a href="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/grinder.pref">preferences</a> are available for download. I changed the IP address in the Grinder test to switch between twisted.web and tornado. The following command was used to start the tests:</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> 100 200 300 400 500 750 <span style="color: #000000;">1000</span>; <span style="color: #000000; font-weight: bold;">do</span> java -Dgrinder.threads=<span style="color: #007800;">$i</span> <span style="color: #660033;">-cp</span> grinder-3.2<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>grinder.jar net.grinder.Grinder grinder.pref; <span style="color: #000000; font-weight: bold;">done</span>;</div></td></tr></tbody></table></div>
<p>I used  the same, simple &#8221;hello, world&#8221; response apps for <a href="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/twisted.web.py">twisted.web</a> and <a href="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/helloworld.py">tornado</a> as I did for the previous test.  Each app was run as a single threaded application. I also used Python 2.6.2.</p>
<p>The raw data that resulted from The Grinder and html output from the <a href="http://track.sourceforge.net/analyzer.html">GrinderAnalysis</a> is <a href="http://www.apparatusproject.org/~matt/www-py-tests.zip">available for download</a>.</p>
<p>The following results were compiled into a spreadsheet from the GrinderAnalysis tool. The X-axis is an individual test that represents number of concurrent requests.  The Y-axis is the<strong> mean response time in milliseconds</strong>.  Lower mean response time is better.</p>
<p><img class="aligncenter size-full wp-image-354" title="Python HTTP Server Performance" src="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/Screen-shot-2009-09-17-at-Sep-17-12.07.15-AM.png" alt="Python HTTP Server Performance" width="589" height="364" /></p>
<p>Below are examples of the <strong>response times</strong> graphs (blue) that I used to compile the above spreadsheet.  The entire output from GrinderAnalytics is <a href="http://www.apparatusproject.org/~matt/www-py-tests.zip">available for download</a>, as mentioned above.  <strong>Transactions per second</strong> <a href="http://grinder.sourceforge.net/g3/manual.html#Results">(TPS)</a> is the graph in the green and is maximum number of iterations of the grinder test that successfully ran in a one second interval.</p>
<h2>100 Concurrent Requests</h2>
<p><a href="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/twisted.web.perf.png"><img class="aligncenter size-full wp-image-367" title="twisted.web.perf" src="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/twisted.web.perf.png" alt="twisted.web.perf" width="640" height="460" /></a><a href="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/Tornado.perf.png"><img class="aligncenter size-full wp-image-368" title="Tornado.perf" src="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/Tornado.perf.png" alt="Tornado.perf" width="640" height="460" /></a></p>
<h2>500 Concurrent Requests</h2>
<h2><a href="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/twisted.web.perf1.png"><img class="aligncenter size-full wp-image-369" title="twisted.web.perf" src="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/twisted.web.perf1.png" alt="twisted.web.perf" width="640" height="460" /></a><a href="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/Tornado.perf1.png"><img class="aligncenter size-full wp-image-370" title="Tornado.perf" src="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/Tornado.perf1.png" alt="Tornado.perf" width="640" height="460" /></a></h2>
<h2>1000 Concurrent Requests</h2>
<p><a href="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/twisted.web.perf2.png"><img class="aligncenter size-full wp-image-371" title="twisted.web.perf" src="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/twisted.web.perf2.png" alt="twisted.web.perf" width="640" height="460" /></a><a href="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/Tornado.perf2.png"><img class="aligncenter size-full wp-image-372" title="Tornado.perf" src="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/Tornado.perf2.png" alt="Tornado.perf" width="640" height="460" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.apparatusproject.org/blog/2009/09/twisted-web-vs-tornado-part-deux/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Twisted.web vs Tornado Performance Test</title>
		<link>http://www.apparatusproject.org/blog/2009/09/twisted-web-vs-tornado-performance-test/</link>
		<comments>http://www.apparatusproject.org/blog/2009/09/twisted-web-vs-tornado-performance-test/#comments</comments>
		<pubDate>Fri, 11 Sep 2009 15:43:39 +0000</pubDate>
		<dc:creator>Matt Heitzenroder</dc:creator>
				<category><![CDATA[apparatus]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[tornado]]></category>
		<category><![CDATA[twisted]]></category>
		<category><![CDATA[twisted.web]]></category>

		<guid isPermaLink="false">http://www.apparatusproject.org/blog/?p=342</guid>
		<description><![CDATA[If you look about this blog, there have been a number posts about the twisted framework.  Dan, Igor, and I have been playing with txAMQP for sometime.  We&#8217;ve never run any twisted code in a high-scale production environment, we&#8217;re just enthusiasts.  So when I read the comments from the Tornado announcement and in the HackerNews thread, [...]]]></description>
			<content:encoded><![CDATA[<p class="dropcap-first">If you look about this blog, there have been a <a href="http://www.apparatusproject.org/blog/tag/twisted/">number posts about the twisted framework</a>.  Dan, Igor, and I have been playing with <a href="http://www.apparatusproject.org/blog/tag/txamqp/">txAMQP</a> for sometime.  We&#8217;ve never run any twisted code in a high-scale production environment, we&#8217;re just enthusiasts.  So when I read the comments from the<a href="http://bret.appspot.com/entry/tornado-web-server#comment-16314810"> Tornado announcement</a> and in the <a href="http://news.ycombinator.com/item?id=815771">HackerNews thread</a>, I asked #twisted.web on freenode:</p>
<blockquote><p><strong><em>&#8220;Who runs a large-scale production environment with twisted.web?&#8221;</em></strong></p></blockquote>
<p>The channel member responded that I speak to abstractbill since he&#8217;s written twisted code for justin.tv. He had <a href="http://news.ycombinator.com/item?id=815837">already commented on hackernews</a> and therefore, I already knew where he stood.  <a href="http://bret.appspot.com/entry/tornado-web-server#comment-16318168">Users were asking</a> and I just needed to see for myself:</p>
<blockquote><p><strong><em>&#8220;What&#8217;s the performance difference between Twisted.web and Tornado?&#8221;</em></strong><span style="background-color: #ffffff; "><strong><em> </em></strong></span></p></blockquote>
<p>So I performed the following tests <a href="http://www.tornadoweb.org/documentation#performance">using Apache Benchmark the same</a> test that <a href="http://bret.appspot.com/">finiteloop</a> used. However, I varied concurrent connections in addition to the benchmarked performance of requests per second.</p>
<p>The performance test was performed on my MacBookPro Intel Core Duo 2.4GHz, 4GB of RAM.  Each python webserver was run in one, single thread.  The code for the tests is available for <a href="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/twisted.web.py">Twisted.web</a> and <a href="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/helloworld.py">Tornado</a>.  Both webservers  benchmarked by increasing the concurrent connections until the servers closed the connection and prevented <a href="http://httpd.apache.org/docs/2.0/programs/ab.html">ab</a> from completing the test.</p>
<p><img class="aligncenter size-full wp-image-343" title="http_test_chart" src="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/http_test_chart.png" alt="http_test_chart" width="413" height="283" /><img class="aligncenter size-full wp-image-344" title="httpd_test_data" src="http://www.apparatusproject.org/blog/wp-content/uploads/2009/09/httpd_test_data.png" alt="httpd_test_data" width="585" height="54" /></p>
<p><a href="http://github.com/facebook/tornado">Tornado</a> outperforms <a href="http://twistedmatrix.com/trac/wiki/TwistedWeb">Twisted.web</a>, but in the scale of those numbers the difference is negligible as finiteloop <a href="http://bret.appspot.com/entry/tornado-web-server#comment-16389114">suggests</a>.  What is noticeable is that after 50 concurrent connections, twisted.web&#8217;s webserver began to close the connection and not complete the test.</p>
<p>The results do not really stop me from wanting to continue using twisted.web, however there is some room for improvement in the twisted.web framework.  I applaud Facebook for releasing <a href="http://www.tornadoweb.org/">Tornado</a> as open source and FriendFeed for create a really nice async webserver in python. I look forward to it&#8217;s continued development.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.apparatusproject.org/blog/2009/09/twisted-web-vs-tornado-performance-test/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Memory Profiling in Twisted Code with Heapy</title>
		<link>http://www.apparatusproject.org/blog/2009/09/memory-profiling-in-twisted-code-with-heapy/</link>
		<comments>http://www.apparatusproject.org/blog/2009/09/memory-profiling-in-twisted-code-with-heapy/#comments</comments>
		<pubDate>Tue, 01 Sep 2009 05:20:42 +0000</pubDate>
		<dc:creator>Matt Heitzenroder</dc:creator>
				<category><![CDATA[apparatus]]></category>
		<category><![CDATA[guppy]]></category>
		<category><![CDATA[heapy]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[profiling]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://www.apparatusproject.org/blog/?p=328</guid>
		<description><![CDATA[I was prototyping an HTTP server using the Python framework Twisted.  After cobbling my code together, I was demoing to Igor and Dan.  Igor, decided to flood the HTTP server with requests to see how it would hold over time.  Turns out we were leaking memory.
A short Google later and a nice [...]]]></description>
			<content:encoded><![CDATA[<p class="dropcap-first">I was prototyping an HTTP server using the Python framework <a href="http://twistedmatrix.com/trac/">Twisted</a>.  After cobbling my code together, I was demoing to <a href="http://twitter.com/igorgue">Igor</a> and <a href="http://twitter.com/reverri">Dan</a>.  Igor, decided to flood the HTTP server with requests to see how it would hold over time.  Turns out we were leaking memory.</p>
<p>A short Google later and a nice <a href="http://stackoverflow.com/questions/110259/python-memory-profiler">StackOverflow </a>thread, we decided to profile the HTTP server with <a href="http://guppy-pe.sourceforge.net/#Heapy">Heapy</a>.  Heapy is part of package called <a href="http://guppy-pe.sourceforge.net/">Guppy</a>.  Simple install is done like this</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$<span style="color: #000000; font-weight: bold;">&amp;</span>gt; pip <span style="color: #c20cb9; font-weight: bold;">install</span> guppy</div></td></tr></tbody></table></div>
<p>The code below is an example of a simplified HTTP server.  I blatantly put in a memory leak for the purposes of demonstrating on how I found it.</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">web</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">resource</span>, server<br />
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">internet</span> <span style="color: #ff7700;font-weight:bold;">import</span> reactor</div></td></tr></tbody></table></div>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">memory_leak = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">class</span> RootResource<span style="color: black;">&#40;</span><span style="color: #dc143c;">resource</span>.<span style="color: black;">Resource</span><span style="color: black;">&#41;</span>:<br />
<span style="color: #ff7700;font-weight:bold;">def</span> render_GET<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request<span style="color: black;">&#41;</span>:<br />
<span style="color: #808080; font-style: italic;"># Obvious Memory Leak</span><br />
memory_leak.<span style="color: black;">append</span><span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;OK&quot;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> getChild<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name, request<span style="color: black;">&#41;</span>:<br />
<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:<br />
port = 8080<br />
<span style="color: #dc143c;">site</span> = server.<span style="color: black;">Site</span><span style="color: black;">&#40;</span>RootResource<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
reactor.<span style="color: black;">listenTCP</span><span style="color: black;">&#40;</span>port, <span style="color: #dc143c;">site</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;"># Dubugging Memory - outputs file to heap_profile.txt from cwd</span><br />
<span style="color: #ff7700;font-weight:bold;">from</span> guppy <span style="color: #ff7700;font-weight:bold;">import</span> hpy<br />
h = hpy<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">def</span> memory_profile<span style="color: black;">&#40;</span>h, reactor<span style="color: black;">&#41;</span>:<br />
f = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'heap_profile.txt'</span>, <span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span><br />
f.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Memory Statistics: <span style="color: #000099; font-weight: bold;">\n</span>%s'</span> <span style="color: #66cc66;">%</span> h.<span style="color: black;">heap</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
f.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#41;</span><br />
f.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Traversing Heap: <span style="color: #000099; font-weight: bold;">\n</span>%s'</span> <span style="color: #66cc66;">%</span> h.<span style="color: black;">heap</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">get_rp</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">40</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
f.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#41;</span><br />
f.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;"># Print profile every 5m after execution for 1h</span><br />
<span style="color: #ff7700;font-weight:bold;">for</span> increment <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">60</span>, <span style="color: #ff4500;">3600</span>, <span style="color: #ff4500;">300</span><span style="color: black;">&#41;</span>:<br />
reactor.<span style="color: black;">callLater</span><span style="color: black;">&#40;</span>increment, memory_profile, h, reactor<span style="color: black;">&#41;</span><br />
<span style="color: #808080; font-style: italic;"># Kill reactor a minute later to give heap time to write.</span><br />
reactor.<span style="color: black;">callLater</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3660</span>, reactor.<span style="color: black;">stop</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;"># Now open the page repeatively</span><br />
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">web</span>.<span style="color: black;">client</span> <span style="color: #ff7700;font-weight:bold;">import</span> getPage<br />
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">internet</span>.<span style="color: black;">task</span> <span style="color: #ff7700;font-weight:bold;">import</span> LoopingCall<br />
gp = LoopingCall<span style="color: black;">&#40;</span>getPage, <span style="color: #483d8b;">'http://localhost:8080'</span><span style="color: black;">&#41;</span><br />
reactor.<span style="color: black;">callLater</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, gp.<span style="color: black;">start</span>, <span style="color: #ff4500;">0.1</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp;reactor.<span style="color: black;">run</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>If you look through the comments you&#8217;ll be able to see that I create a function called <em>memory_profile()</em>, which just spits out two profiles from heapy to a file.  A few lines past this, you can see I use the reactor&#8217;s <em>callLater()</em> to call at 300s increments.  The last thing I do is kill the reactor with <em>reactor.callLater(3660, reactor.stop)</em>.  I give heapy 60 seconds to write the last profile to the file (which is more than plenty of time).</p>
<p>The following output is two profiles, one at 1 minute, another 5 minutes after.</p>
<pre>Memory Statistics:
Partition of a set of 104996 objects. Total size = 9162436 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0  43217  41  2949300  32   2949300  32 str
     1    590   1   988840  11   3938140  43 dict of twisted.web.server.Request
     2   4369   4   848588   9   4786728  52 dict (no owner)
     3  18370  17   757704   8   5544432  61 tuple
     4   8059   8   470316   5   6014748  66 list
     5   4724   4   321232   4   6335980  69 types.CodeType
     6    590   1   309160   3   6645140  73 dict of twisted.internet.tcp.Server
     7    204   0   307344   3   6952484  76 dict of module
     8   4754   5   285240   3   7237724  79 function
     9    467   0   209740   2   7447464  81 type
&lt;222 more rows. Type e.g. '_.more' to view.&gt;

Traversing Heap:
Reference Pattern by &lt;[dict of] class&gt;.
 0: _ --- [-] 105004 (Queue.Queue | __builtin__.PyCObject | __builtin__.cell ...
 1: a      [-] 590 dict of twisted.web.server.Request: 0x15e18a0..., 0x15e1b98
 2: aa ---- [-] 590 twisted.web.server.Request: 0x1564b98, 0x15d8850...
 3: a3       [-] 1 list: 0x12634b8*590
 4: a4 ------ [S] 1 dict of module: __main__
 5: b      [-] 18370 tuple: 0x4a76f0*1, 0x4a7730*1, 0x4a77f0*1, 0x4a7810*1...
 6: ba ---- [S] 4724 types.CodeType: site.py:82:makepath...
 7: bb      [-] 590 dict of twisted.internet.tcp.Server: 0x15e3710..., 0x162f310
 8: bba ---- [-] 590 twisted.internet.tcp.Server: 0x157ef90, 0x15e3150...
 9: bbaa      [^ 1] 590 dict of twisted.web.server.Request: 0x15e1b98...

Memory Statistics:
Partition of a set of 261479 objects. Total size = 25045732 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0   3543   1  5938068  24   5938068  24 dict of twisted.web.server.Request
     1  87519  33  4638728  19  10576796  42 str
     2  19145   7  2917228  12  13494024  54 dict (no owner)
     3  46449  18  2620132  10  16114156  64 list
     4   3543   1  1856532   7  17970688  72 dict of twisted.internet.tcp.Server
     5   7086   3   992040   4  18962728  76 dict of twisted.internet.address.IPv4Address
     6   7086   3   992040   4  19954768  80 dict of twisted.web.http_headers.Headers
     7   7086   3   992040   4  20946808  84 dict of twisted.web.http_headers._DictHeaders
     8  21326   8   864116   3  21810924  87 tuple
     9   4724   2   321232   1  22132156  88 types.CodeType
&lt;226 more rows. Type e.g. '_.more' to view.&gt;

Traversing Heap:
Reference Pattern by &lt;[dict of] class&gt;.
 0: _ --- [-] 261479 (Queue.Queue | __builtin__.PyCObject | __builtin__.cell ...
 1: a      [-] 3543 dict of twisted.web.server.Request: 0x15e18a0..., 0x15e1b98
 2: aa ---- [-] 3543 twisted.web.server.Request: 0x1564b98, 0x15d8850...
 3: a3       [-] 1 list: 0x12634b8*3543
 4: a4 ------ [S] 1 dict of module: __main__
 5: b      [-] 3543 dict of twisted.internet.tcp.Server: 0x15e3710..., 0x162f310
 6: ba ---- [-] 3543 twisted.internet.tcp.Server: 0x157ef90, 0x15e3150...
 7: baa      [^ 1] 3543 dict of twisted.web.server.Request: 0x15e1b98...
 8: c ---- [-] 25140 list: 0x4a8850*1, 0x4a8878*2, 0x4a88a0*2, 0x4a8ee0*202...
 9: ca      [^ 1] 3543 dict of twisted.web.server.Request: 0x15e1b98...</pre>
<p>I am looking for a pattern here.  Specifically what I am interested in is:</p>
<pre>Partition of a set of 104996 objects. Total size = 9162436 bytes.</pre>
<p>Then again in the second profile:</p>
<pre>Partition of a set of 261479 objects. Total size = 25045732 bytes.</pre>
<p>I can see that my number of objects is rapidly increasing and I can see that we went from ~9MB to ~25MB in very short order.</p>
<p>Now to figure out where it is coming from, I want to &#8220;Traverse&#8221; the heap.  This will help me go in the right direction.  It&#8217;s pretty clear from as I look at the change from the &#8220;Traversing Heap&#8221; from the first set to the second set, that the Request object is becoming increasing an issue.</p>
<p>Twisted is extremely well written and does not have memory leaks &#8220;out of the box&#8221;, so the issue is in my code.  Thankfully I do not have complex code and it&#8217;s very easy to see what&#8217;s going on with the Request object.  Appending the Request object to a global list is pretty stupid&#8230; thank god it&#8217;s only an example :P</p>
<p>The major lesson learned from my experience is to profile memory often and to set up automated tests to do so.  Had our development gone much longer without examining our code, we would have likely pulled our hair out.  Also critical for us to find the source of our leak, was to let the test run for a length of time and try to find a pattern.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.apparatusproject.org/blog/2009/09/memory-profiling-in-twisted-code-with-heapy/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using prefetch with txAMQP and RabbitMQ 1.6.0</title>
		<link>http://www.apparatusproject.org/blog/2009/08/using-prefetch-with-txamqp-and-rabbitmq-1-6-0/</link>
		<comments>http://www.apparatusproject.org/blog/2009/08/using-prefetch-with-txamqp-and-rabbitmq-1-6-0/#comments</comments>
		<pubDate>Fri, 14 Aug 2009 00:23:37 +0000</pubDate>
		<dc:creator>Dan Reverri</dc:creator>
				<category><![CDATA[apparatus]]></category>
		<category><![CDATA[amqp]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[rabbitmq]]></category>
		<category><![CDATA[twisted]]></category>
		<category><![CDATA[txamqp]]></category>

		<guid isPermaLink="false">http://app.arat.us/blog/?p=316</guid>
		<description><![CDATA[I&#8217;m hoping this might be useful to someone. I wrote a quick script that uses &#8220;channel.basic_qos(prefetch_count=1)&#8221; with txAMQP and RabbitMQ 1.6.0. It is available here:
http://app.arat.us/blog/wp-content/uploads/2009/08/prefetch.py
You can run it as follows:
1234567891011python prefetch.py localhost 5672 / guest guest path/to/specs/amqp0-8.xml 
* Slow consumer received message: Message 1 *
Fast consumer received message: Message 2
Fast consumer received message: Message 3
* [...]]]></description>
			<content:encoded><![CDATA[<p class="dropcap-first">I&#8217;m hoping this might be useful to someone. I wrote a quick script that uses &#8220;channel.basic_qos(prefetch_count=1)&#8221; with txAMQP and RabbitMQ 1.6.0. It is available here:<br />
<a href="http://app.arat.us/blog/wp-content/uploads/2009/08/prefetch.py">http://app.arat.us/blog/wp-content/uploads/2009/08/prefetch.py</a></p>
<p>You can run it as follows:</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">python prefetch.py localhost <span style="color: #000000;">5672</span> <span style="color: #000000; font-weight: bold;">/</span> guest guest path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>specs<span style="color: #000000; font-weight: bold;">/</span>amqp0-8.xml <br />
<span style="color: #000000; font-weight: bold;">*</span> Slow consumer received message: Message <span style="color: #000000;">1</span> <span style="color: #000000; font-weight: bold;">*</span><br />
Fast consumer received message: Message <span style="color: #000000;">2</span><br />
Fast consumer received message: Message <span style="color: #000000;">3</span><br />
<span style="color: #000000; font-weight: bold;">*</span> Slow consumer received message: Message <span style="color: #000000;">4</span> <span style="color: #000000; font-weight: bold;">*</span><br />
Fast consumer received message: Message <span style="color: #000000;">5</span><br />
Fast consumer received message: Message <span style="color: #000000;">6</span><br />
<span style="color: #000000; font-weight: bold;">*</span> Slow consumer received message: Message <span style="color: #000000;">7</span> <span style="color: #000000; font-weight: bold;">*</span><br />
Fast consumer received message: Message <span style="color: #000000;">8</span><br />
Fast consumer received message: Message <span style="color: #000000;">9</span><br />
<span style="color: #000000; font-weight: bold;">*</span> Slow consumer received message: Message <span style="color: #000000;">10</span> <span style="color: #000000; font-weight: bold;">*</span></div></td></tr></tbody></table></div>
<p>Notice that the fast consumer grabs twice as many messages as the slow consumer.</p>
<p>I have not found a clean way of ending the script, you have to force quit with CTRL+C. Let me know if you have any suggestions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.apparatusproject.org/blog/2009/08/using-prefetch-with-txamqp-and-rabbitmq-1-6-0/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Py2JSON – Python Classes To JSON-Schema SMD</title>
		<link>http://www.apparatusproject.org/blog/2009/07/py2json-classes-to-json-schema/</link>
		<comments>http://www.apparatusproject.org/blog/2009/07/py2json-classes-to-json-schema/#comments</comments>
		<pubDate>Tue, 28 Jul 2009 12:00:42 +0000</pubDate>
		<dc:creator>Igor Guerrero</dc:creator>
				<category><![CDATA[apparatus]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[json-schema]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://app.arat.us/blog/?p=289</guid>
		<description><![CDATA[As we work with Python and JSON-Schema, we found the necessity to create JSON-Schemas from Python classes, but we didn&#8217;t find any existing libraries to make this task easier, so we wrote one :)
Py2JSON is a library that will create from a given Python class a JSON-Schema string that you can later save to a file for [...]]]></description>
			<content:encoded><![CDATA[<p class="dropcap-first">As we work with <a href="http://www.python.org/">Python</a> and <a href="http://www.json.com/json-schema-proposal/">JSON-Schema</a>, we found the necessity to create JSON-Schemas from Python classes, but we didn&#8217;t find any existing libraries to make this task easier, so we wrote one :)</p>
<p><a href="github.com/igorgue/py2json">Py2JSON</a> is a library that will create from a given Python class a JSON-Schema string that you can later save to a file for example.</p>
<p>Development is done in Github: <a href="http://github.com/igorgue/py2json">http://github.com/igorgue/py2json</a></p>
<p>You can report issues or enhancement request here: <a href="http://github.com/igorgue/py2json/issues">http://github.com/igorgue/py2json/issues</a></p>
<h2>Getting and Installing Py2JSON</h2>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">igor<span style="color: #000000; font-weight: bold;">@</span>igorlaptop:~$ git clone git:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>igorgue<span style="color: #000000; font-weight: bold;">/</span>py2json.git<br />
igor<span style="color: #000000; font-weight: bold;">@</span>igorlaptop:~$ <span style="color: #7a0874; font-weight: bold;">cd</span> py2json<span style="color: #000000; font-weight: bold;">/</span><br />
igor<span style="color: #000000; font-weight: bold;">@</span>igorlaptop:~<span style="color: #000000; font-weight: bold;">/</span>py2json$ python setup.py <span style="color: #c20cb9; font-weight: bold;">install</span><br />
igor<span style="color: #000000; font-weight: bold;">@</span>igorlaptop:~<span style="color: #000000; font-weight: bold;">/</span>py2json$ python <span style="color: #660033;">-c</span> <span style="color: #ff0000;">'import py2json'</span><br />
igor<span style="color: #000000; font-weight: bold;">@</span>igorlaptop:~<span style="color: #000000; font-weight: bold;">/</span>py2json$</div></td></tr></tbody></table></div>
<p>If you don&#8217;t get any error then you&#8217;ve successfully installed py2json (sudo might be required in some UNIX environments). Here a example, using py2json to generate a JSON-Schema string:</p>
<h2>Examples</h2>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> py2json <span style="color: #ff7700;font-weight:bold;">import</span> Py2JSON<br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">class</span> Foo<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:<br />
... <span style="color: #483d8b;">&quot;&quot;&quot;this class does foo&quot;&quot;&quot;</span><br />
... <span style="color: #ff7700;font-weight:bold;">def</span> bar<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #dc143c;">string</span>=<span style="color: #483d8b;">'this is a string'</span><span style="color: black;">&#41;</span>:<br />
... &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">string</span><br />
...<br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span> smd = Py2JSON<span style="color: black;">&#40;</span>Foo<span style="color: black;">&#41;</span><br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span> smd.<span style="color: black;">schema</span><br />
<span style="color: #483d8b;">'{&quot;services&quot;: {&quot;bar&quot;: {&quot;target&quot;: &quot;bar&quot;, &quot;parameters&quot;: [{&quot;default&quot;: &quot;this is a string&quot;, &quot;optional&quot;: false, &quot;type&quot;: &quot;string&quot;, &quot;name&quot;: &quot;string&quot;}]}}, &quot;envelope&quot;: &quot;JSON&quot;, &quot;target&quot;: null, &quot;transport&quot;: &quot;REST&quot;, &quot;additionalParameters&quot;: true}'</span><br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span></div></td></tr></tbody></table></div>
<p>To exclude a method you can use the exclude parameter:</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">class</span> Foo<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:<br />
... <span style="color: #483d8b;">&quot;&quot;&quot;this class does foo&quot;&quot;&quot;</span><br />
... <span style="color: #ff7700;font-weight:bold;">def</span> bar<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #dc143c;">string</span>=<span style="color: #483d8b;">'this is a string'</span><span style="color: black;">&#41;</span>:<br />
... &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">string</span><br />
... <span style="color: #ff7700;font-weight:bold;">def</span> bar2<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, integer=123<span style="color: black;">&#41;</span>:<br />
... &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> integer<br />
...<br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span> smd = Py2JSON<span style="color: black;">&#40;</span>Foo, excluded_methods=<span style="color: black;">&#91;</span><span style="color: #483d8b;">'bar2'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span> smd.<span style="color: black;">schema</span><br />
<span style="color: #483d8b;">'{&quot;services&quot;: {&quot;bar&quot;: {&quot;target&quot;: &quot;bar&quot;, &quot;parameters&quot;: [{&quot;default&quot;: &quot;this is a string&quot;, &quot;optional&quot;: false, &quot;type&quot;: &quot;string&quot;, &quot;name&quot;: &quot;string&quot;}]}}, &quot;envelope&quot;: &quot;JSON&quot;, &quot;target&quot;: null, &quot;transport&quot;: &quot;REST&quot;, &quot;additionalParameters&quot;: true}'</span><br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span></div></td></tr></tbody></table></div>
<p>You can use it to store the schema in a string too:</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&gt;&gt;&gt;</span> f = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'foo.js'</span>, <span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span><br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span> smd = Py2JSON<span style="color: black;">&#40;</span>Foo<span style="color: black;">&#41;</span><br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span> f.<span style="color: black;">write</span><span style="color: black;">&#40;</span>smd.<span style="color: black;">schema</span><span style="color: black;">&#41;</span><br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span> f.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'foo.js'</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;services&quot;</span>: <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;bar&quot;</span>: <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;target&quot;</span>: <span style="color: #483d8b;">&quot;bar&quot;</span>, <span style="color: #483d8b;">&quot;parameters&quot;</span>: <span style="color: black;">&#91;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;default&quot;</span>: <span style="color: #483d8b;">&quot;this is a string&quot;</span>, <span style="color: #483d8b;">&quot;optional&quot;</span>: false, <span style="color: #483d8b;">&quot;type&quot;</span>: <span style="color: #483d8b;">&quot;string&quot;</span>, <span style="color: #483d8b;">&quot;name&quot;</span>: <span style="color: #483d8b;">&quot;string&quot;</span><span style="color: black;">&#125;</span><span style="color: black;">&#93;</span><span style="color: black;">&#125;</span><span style="color: black;">&#125;</span>, <span style="color: #483d8b;">&quot;envelope&quot;</span>: <span style="color: #483d8b;">&quot;JSON&quot;</span>, <span style="color: #483d8b;">&quot;target&quot;</span>: null, <span style="color: #483d8b;">&quot;transport&quot;</span>: <span style="color: #483d8b;">&quot;REST&quot;</span>, <span style="color: #483d8b;">&quot;additionalParameters&quot;</span>: true<span style="color: black;">&#125;</span><br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span></div></td></tr></tbody></table></div>
<p>Py2JSON is a work in progress, suggestions are welcome, patches are awesome :), right now it lacks of a lot of things; since we do not need them right now are not implementing, such as storing attributes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.apparatusproject.org/blog/2009/07/py2json-classes-to-json-schema/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Installing Git on ChunckHost</title>
		<link>http://www.apparatusproject.org/blog/2009/07/installing-git-on-chunckhost/</link>
		<comments>http://www.apparatusproject.org/blog/2009/07/installing-git-on-chunckhost/#comments</comments>
		<pubDate>Thu, 23 Jul 2009 17:56:31 +0000</pubDate>
		<dc:creator>Matt Heitzenroder</dc:creator>
				<category><![CDATA[apparatus]]></category>
		<category><![CDATA[chunkhost]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[hardy]]></category>
		<category><![CDATA[source]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://app.arat.us/blog/?p=268</guid>
		<description><![CDATA[Igor pointed me to ChunkHost&#8217;s free Beta recently, so I signed up.
First and foremost, I have no known affiliation with any related to ChunkHost.
Secondly, my first impression of ChunckHost was great &#8211; the signup and automation was completely fluid.  It was very easy to signup and receive root to a freshly minted Ubuntu 8.04.  All [...]]]></description>
			<content:encoded><![CDATA[<p class="dropcap-first">Igor pointed me to<a href="http://www.chunkhost.com/"> ChunkHost&#8217;s free Beta</a> recently, so I signed up.</p>
<p>First and foremost, I have no known affiliation with any related to <a href="http://www.chunkhost.com/">ChunkHost</a>.</p>
<p>Secondly, my first impression of <a href="http://www.chunkhost.com/">ChunckHost</a> was great &#8211; the signup and automation was completely fluid.  It was very easy to signup and receive root to a freshly minted Ubuntu 8.04.  All I had to do was put in my account information and then click sign-up  and root was emailed to me within minutes. +1 <a href="http://www.chunkhost.com/">ChunkHost</a>.</p>
<p>I decided to write this blog partly about them. One reason is because of the swift and smooth customer experience. The other reason is because my steps to install git might be different than yours because of the vendors Virtual machine.</p>
<p>The first thing I wanted to do as I christen the server was to install <a href="http://git-scm.com/">git from source</a>. These are the steps I did to complete that task:</p>
<h2>Getting Git</h2>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #666666; font-style: italic;"># apt-get update</span></div></td></tr></tbody></table></div>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #666666; font-style: italic;"># apt-get upgrade</span><br />
<br />
root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #666666; font-style: italic;"># apt-get install build-essential</span><br />
<br />
root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #666666; font-style: italic;"># apt-get install wget</span><br />
<br />
root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #666666; font-style: italic;"># wget http://kernel.org/pub/software/scm/git/git-1.6.3.3.tar.bz2</span><br />
<br />
root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #666666; font-style: italic;"># tar -xjf git-1.6.3.3.tar.bz2</span></div></td></tr></tbody></table></div>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #666666; font-style: italic;"># cd git-1.6.3.3/</span></div></td></tr></tbody></table></div>
<p>Now I have the latest source it&#8217;s time to compile it.</p>
<h2>Make</h2>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #000000; font-weight: bold;">/</span>git-1.6.3.3<span style="color: #666666; font-style: italic;"># ./configure</span></div></td></tr></tbody></table></div>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp;</div></td></tr></tbody></table></div>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #000000; font-weight: bold;">/</span>git-1.6.3.3<span style="color: #666666; font-style: italic;"># ./make</span></div></td></tr></tbody></table></div>
<p>At this point I had an issue where I received this error:</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff0000;">'Z_DEFAULT_COMPRESSION'</span> undeclared here <span style="color: #7a0874; font-weight: bold;">&#40;</span>not <span style="color: #000000; font-weight: bold;">in</span> a <span style="color: #000000; font-weight: bold;">function</span><span style="color: #7a0874; font-weight: bold;">&#41;</span></div></td></tr></tbody></table></div>
<p>I realized after reading a <a href="http://ubuntuforums.org/archive/index.php/t-1117939.html">forum thread</a> I figured I needed to do this:</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #000000; font-weight: bold;">/</span>git-1.6.3.3<span style="color: #666666; font-style: italic;"># apt-get build-deps git-core</span></div></td></tr></tbody></table></div>
<p>For good measure, I built openssl after reading through of <a href="http://ubuntuforums.org/archive/index.php/t-1117939.html">that thread</a>.</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #000000; font-weight: bold;">/</span>git-1.6.3.3<span style="color: #666666; font-style: italic;"># apt-get install openssl</span></div></td></tr></tbody></table></div>
<p>Then I was able to make</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #000000; font-weight: bold;">/</span>git-1.6.3.3<span style="color: #666666; font-style: italic;"># make &amp;amp;&amp;amp; make install</span></div></td></tr></tbody></table></div>
<p>Success.  If you have questions or tips, please post them. I hope this helps!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.apparatusproject.org/blog/2009/07/installing-git-on-chunckhost/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Installing ZeroMQ v1.0.0</title>
		<link>http://www.apparatusproject.org/blog/2009/07/installing-zeromq-v1/</link>
		<comments>http://www.apparatusproject.org/blog/2009/07/installing-zeromq-v1/#comments</comments>
		<pubDate>Wed, 15 Jul 2009 07:18:47 +0000</pubDate>
		<dc:creator>Matt Heitzenroder</dc:creator>
				<category><![CDATA[apparatus]]></category>
		<category><![CDATA[amqp]]></category>
		<category><![CDATA[hardy]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[zeromq]]></category>

		<guid isPermaLink="false">http://app.arat.us/blog/?p=274</guid>
		<description><![CDATA[ZeroMQ released 1.0.0 yesterday (congrats!) and I decided to take it for a spin.  I needed to create a buildslave anyway and I decided to capture my steps as I installed ZeroMQ.  The following steps were completed on an Ubuntu Hardy and Python 2.6.2
Simple Install
I am not sure if it&#8217;s necessary or not for [...]]]></description>
			<content:encoded><![CDATA[<p class="dropcap-first"><a href="http://www.zeromq.org"><img class="alignright" title="ZeroMQ" src="http://www.zeromq.org/local--files/theme:css/logo.gif" alt="" width="267" height="83" /></a><a href="http://www.zeromq.org/">ZeroMQ</a> <a href="http://lists.zeromq.org/pipermail/zeromq-dev/2009-July/000935.html">released 1.0.0</a> yesterday (congrats!) and I decided to take it for a spin.  I needed to create a <a href="http://buildbot.net/trac">buildslave</a> anyway and I decided to capture my steps as I installed ZeroMQ.  The following steps were completed on an Ubuntu Hardy and Python 2.6.2</p>
<h2>Simple Install</h2>
<p>I am not sure if it&#8217;s necessary or not for my application, but I wanted to include support for both AMQP and Python.</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #000000; font-weight: bold;">/</span>src<span style="color: #000000; font-weight: bold;">/</span>zmq-1.0.0 <span style="color: #666666; font-style: italic;"># ./configure --with-python --with-amqp</span><br />
root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #000000; font-weight: bold;">/</span>src<span style="color: #000000; font-weight: bold;">/</span>zmq-1.0.0 <span style="color: #666666; font-style: italic;"># make</span><br />
root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #000000; font-weight: bold;">/</span>src<span style="color: #000000; font-weight: bold;">/</span>zmq-1.0.0 <span style="color: #666666; font-style: italic;"># make install</span></div></td></tr></tbody></table></div>
<p>After that I was done&#8230; time to fire it up</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #000000; font-weight: bold;">/</span>src<span style="color: #000000; font-weight: bold;">/</span>zmq-1.0.0 <span style="color: #666666; font-style: italic;"># zmq_server</span></div></td></tr></tbody></table></div>
<p>But it returned this error</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">zmq_server: error <span style="color: #000000; font-weight: bold;">while</span> loading shared libraries: libzmq.so.1:<br />
cannot open shared object <span style="color: #c20cb9; font-weight: bold;">file</span>: No such <span style="color: #c20cb9; font-weight: bold;">file</span> or directory</div></td></tr></tbody></table></div>
<p><a href="http://www.linuxquestions.org/questions/linux-newbie-8/error-while-loading-shared-libraries-612832/#post3019133">Oh yeah&#8230; need to update the libraries</a>.  Let me try again:</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #000000; font-weight: bold;">/</span>src<span style="color: #000000; font-weight: bold;">/</span>zmq-1.0.0 <span style="color: #666666; font-style: italic;"># ldconfig -v</span><br />
root<span style="color: #000000; font-weight: bold;">@</span>roder:~<span style="color: #000000; font-weight: bold;">/</span>src<span style="color: #000000; font-weight: bold;">/</span>zmq-1.0.0 <span style="color: #666666; font-style: italic;"># zmq_server</span></div></td></tr></tbody></table></div>
<p>Voila!  Now to play with it.</p>
<p>&#8230;to be continued.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.apparatusproject.org/blog/2009/07/installing-zeromq-v1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How-To for github_buildbot.py</title>
		<link>http://www.apparatusproject.org/blog/2009/07/how-to-github_buildbot-py/</link>
		<comments>http://www.apparatusproject.org/blog/2009/07/how-to-github_buildbot-py/#comments</comments>
		<pubDate>Tue, 14 Jul 2009 06:00:17 +0000</pubDate>
		<dc:creator>Matt Heitzenroder</dc:creator>
				<category><![CDATA[apparatus]]></category>
		<category><![CDATA[buildbot]]></category>
		<category><![CDATA[ci]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[howto]]></category>

		<guid isPermaLink="false">http://app.arat.us/blog/?p=244</guid>
		<description><![CDATA[
github_buildbot.py is a small web server that responds to JSON that is POST&#8217;ed to it from GitHub.com and initiates a build on Buildbot instance.  You may find the latest source code at GitHub.
Getting Started
In short:

start github_buildbot.py
add your github_buildbot server url to a post-receive service hook in GitHub (ie: http://example.com:4000)
configure your buildmaster&#8217;s master.cfg to point to [...]]]></description>
			<content:encoded><![CDATA[<p class="dropcap-first"><div id="attachment_265" class="wp-caption alignright" style="width: 180px"><img class="size-full wp-image-265 " title="github_buildbot" src="http://app.arat.us/blog/wp-content/uploads/2009/07/github_buildbot.png" alt="github_buildbot" width="170" height="189" /><p class="wp-caption-text">GitHub &amp; Buildbot - together at last</p></div></p>
<p>github_buildbot.py is a small web server that responds to JSON that is POST&#8217;ed to it from GitHub.com and initiates a build on Buildbot instance.  You may find the <a href="http://github.com/djmitche/buildbot/blob/master/contrib/github_buildbot.py">latest source code at GitHub</a>.</p>
<h2>Getting Started</h2>
<p>In short:</p>
<ol>
<li>start github_buildbot.py</li>
<li>add your github_buildbot server url to a post-receive service hook in GitHub (ie: http://example.com:4000)</li>
<li>configure your buildmaster&#8217;s master.cfg to point to /tmp/your_project_name.git</li>
<li>commit and enjoy</li>
</ol>
<h2 style="font-size: 1.5em; ">How it works</h2>
<ol>
<li>Creates a webserver that listens to port 4000</li>
<li>Accepts JSON POSTs from GitHub</li>
<li>Clones a bare repository locally in a specified directory or the system temp directory by default</li>
<li>Submits changesets to Buildmaster to build</li>
</ol>
<h2 style="font-size: 1.5em; ">How it works: verbose</h2>
<h3>Start it up</h3>
<p>To start github_buildbot.py, locate the source of Buildbot on your buildmaster and change directory to the ./contrib.  Ensure that github_buildbot is executable and then start it by:</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">./github_buildbot.<span style="color: black;">py</span></div></td></tr></tbody></table></div>
<p>By default, github_buildbot.py starts a webserver on port 4000.  This can altered by doing something like:</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #000000; font-weight: bold;">/</span>github_buildbot.py <span style="color: #660033;">-p</span> <span style="color: #000000;">8888</span></div></td></tr></tbody></table></div>
<p>or</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #000000; font-weight: bold;">/</span>github_buildbot.py <span style="color: #660033;">--port</span>=<span style="color: #000000;">8888</span></div></td></tr></tbody></table></div>
<h3 style="font-size: 1.17em; ">The local clone</h3>
<p>The Buildbot buildmaster requires that the source directory is locally accessible when you configure the master.cfg in the buildmaster.</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">from buildbot.steps.source import Git</div>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp;<span style="color: #ff7700;font-weight:bold;">from</span> buildbot.<span style="color: black;">steps</span>.<span style="color: black;">source</span> <span style="color: #ff7700;font-weight:bold;">import</span> Git<br />
f1 = factory.<span style="color: black;">BuildFactory</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
f1.<span style="color: black;">addStep</span><span style="color: black;">&#40;</span>Git<span style="color: black;">&#40;</span>repourl=<span style="color: #483d8b;">'/tmp/apparatus.git'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>The default for github_buildbot.py is to create a &#8220;mirror&#8221; (which in essence, is the same as &#8220;bare&#8221;) repository in the operating system&#8217;s temporary directory.  For example, the /tmp directory in POSIX systems. Putting source code in the /tmp directory isn&#8217;t necessarily good for everyone, so further down I will discuss how to specify the directory.  When github_buildbot.py clones the github repository, it will name the local mirror after the name of the project and append &#8216;.git&#8217; to it.  In our case, the resulting local mirror is &#8216;apparatus.git&#8217;.  Therefore, when configuring the Buildbot, specify the directory (by default the OS temp dir) and project name appended with a &#8216;.git&#8217;</p>
<h3 style="font-size: 1.17em; ">Private or Public?</h3>
<p>If you are using a private repository, it is critical that you start github_buildbot.py with a user whose ssh identity matches a contributor on the GitHub repository.</p>
<h3 style="font-size: 1.17em; ">Something different</h3>
<p>In order to specify another build directory other than the operating system&#8217;s temporary directory (ie: /tmp), you may use the following flag:</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #000000; font-weight: bold;">/</span>github_buildbot.py <span style="color: #660033;">-d</span> <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">dir</span></div></td></tr></tbody></table></div>
<p>or</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #000000; font-weight: bold;">/</span>github_buildbot.py <span style="color: #660033;">--dir</span>=<span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">dir</span></div></td></tr></tbody></table></div>
<p>If, for some reason, that the buildmaster is not localhost:9989, you may specify the buildmaster like this:</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #000000; font-weight: bold;">/</span>github_buildbot.py <span style="color: #660033;">-m</span> HOST:PORT</div></td></tr></tbody></table></div>
<p>or</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #000000; font-weight: bold;">/</span>github_buildbot.py <span style="color: #660033;">--buildmaster</span>=host:port</div></td></tr></tbody></table></div>
<p>It is also possible, that you have an alias for github.com in your .ssh/config directory &#8211; especially if you have multiple accounts on one machine.  If you need to specify another &#8220;location&#8221; other than github.com, you can do so like this:</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #000000; font-weight: bold;">/</span>github_buildbot.py <span style="color: #660033;">-g</span> <span style="color: #c20cb9; font-weight: bold;">hostname</span></div></td></tr></tbody></table></div>
<p>or</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #000000; font-weight: bold;">/</span>github_buildbot.py <span style="color: #660033;">--github</span>=<span style="color: #c20cb9; font-weight: bold;">hostname</span></div></td></tr></tbody></table></div>
<h3 style="font-size: 1.17em; ">Configuring GitHub</h3>
<p>GitHub has made this dead simple with<a href="http://github.com/guides/post-receive-hooks"> Service Hooks</a>.  Add the URL to a post-receive service hook, including the port, to the service hooks section in GitHub.</p>
<div id="attachment_250" class="wp-caption aligncenter" style="width: 310px"><img class="size-full wp-image-250 " title="Service Hooks" src="http://app.arat.us/blog/wp-content/uploads/2009/07/Picture-1.png" alt="Service Hooks" width="300" height="175" /><p class="wp-caption-text">Service Hooks</p></div>
<div id="attachment_251" class="wp-caption aligncenter" style="width: 254px"><img class="size-full wp-image-251 " title="Post Receive URLs" src="http://app.arat.us/blog/wp-content/uploads/2009/07/Picture-3.png" alt="Post Receive URLs" width="244" height="86" /><p class="wp-caption-text">Post Receive URLs</p></div>
<div id="attachment_252" class="wp-caption aligncenter" style="width: 589px"><img class="size-full wp-image-252 " title="Input" src="http://app.arat.us/blog/wp-content/uploads/2009/07/Picture-2.png" alt="Inputing the Post-Receive URLs" width="579" height="211" /><p class="wp-caption-text">Inputing the Post-Receive URLs</p></div>
<p>Onceyou have the github_buildbot.py web server running and the service hook enabled in GitHub, you may want to test using &#8220;Test Hook&#8221; in GitHub.  This will send the last few commits to the specified URL.  You can then debug as necessary if there are any issues.</p>
<h3>Help Me</h3>
<p>If you still need help, probably best to join the #buildbot IRC channel on irc.freenode.net .</p>
<p>Otherwise, you can do this:</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #000000; font-weight: bold;">/</span>github_buildbot.py <span style="color: #660033;">--help</span></div></td></tr></tbody></table></div>
<p>or</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #000000; font-weight: bold;">/</span>github_buildbot.py <span style="color: #660033;">-h</span></div></td></tr></tbody></table></div>
<div id="attachment_215" class="wp-caption aligncenter" style="width: 605px"><img class="size-full wp-image-215 " title="github-buildbot" src="http://app.arat.us/blog/wp-content/uploads/2009/07/picture-11.png" alt="--help of github_buildbot.py" width="595" height="387" /><p class="wp-caption-text">--help of github_buildbot.py</p></div>
<p>However, if you&#8217;re feeling lucky, try turning on logging:</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #000000; font-weight: bold;">/</span>github_buildbot.py <span style="color: #660033;">-L</span> debug</div></td></tr></tbody></table></div>
<p>or</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #000000; font-weight: bold;">/</span>github_buildbot.py <span style="color: #660033;">--level</span>=debug</div></td></tr></tbody></table></div>
<p>You can find all log entries in your operating system&#8217;s temporary directory with the filename &#8220;github_buildbot.log&#8221;.  However, if you&#8217;d like to configure that, you can do that too!</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #000000; font-weight: bold;">/</span>github_buildbot.py <span style="color: #660033;">-l</span> <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>new_log_file.log</div></td></tr></tbody></table></div>
<p>or</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #000000; font-weight: bold;">/</span>github_buildbot.py <span style="color: #660033;">--log</span>=<span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>new_log_file.log</div></td></tr></tbody></table></div>
]]></content:encoded>
			<wfw:commentRss>http://www.apparatusproject.org/blog/2009/07/how-to-github_buildbot-py/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>GitHub &amp; Buildbot Redux</title>
		<link>http://www.apparatusproject.org/blog/2009/07/github-buildbot-redux/</link>
		<comments>http://www.apparatusproject.org/blog/2009/07/github-buildbot-redux/#comments</comments>
		<pubDate>Tue, 07 Jul 2009 11:32:58 +0000</pubDate>
		<dc:creator>Matt Heitzenroder</dc:creator>
				<category><![CDATA[apparatus]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[buildbot]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[conventions]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>

		<guid isPermaLink="false">http://app.arat.us/blog/?p=212</guid>
		<description><![CDATA[The first time I posted about this was after I hastily  assembled a github/buildbot integration.
I knew then that I wanted to take a few more passes to clean it up.  I did that with the help of Dan over the weekend.
Now it&#8217;s much better.  If you&#8217;re interested in the changes, you can see a dramatic difference by viewing [...]]]></description>
			<content:encoded><![CDATA[<p class="dropcap-first">The first time I posted about this was after I <a href="http://app.arat.us/blog/?p=136">hastily  assembled</a> a <a href="http://github.com">github</a>/<a href="http://buildbot.net/">buildbot</a> integration.</p>
<div id="attachment_215" class="wp-caption alignright" style="width: 310px"><a href="http://app.arat.us/blog/wp-content/uploads/2009/07/picture-11.png"><img class="size-medium wp-image-215  " title="github-buildbot" src="http://app.arat.us/blog/wp-content/uploads/2009/07/picture-11.png" alt="--help of github_buildbot.py" width="300" height="195" /></a><p class="wp-caption-text">--help of github_buildbot.py</p></div>
<p>I knew then that I wanted to take a few more passes to clean it up.  I did that with the help of Dan over the weekend.</p>
<p>Now it&#8217;s much better.  If you&#8217;re interested in the changes, you can see a dramatic difference by <a href="http://github.com/roder/buildbot/commit/c4fb6105538f93accd8734ef40c11930410a1d75">viewing the diff</a>.</p>
<p>However, the easiest way to see the newly refactored code is by looking at .<a href="http://github.com/roder/buildbot/blob/master/contrib/github_buildbot.py">/contrib/github_buildbot.py</a>.</p>
<p>One of the best new features about the new code is it&#8217;s ability to control it from command line parameters.</p>
<p>It&#8217;s also sporting a nice amount of refactored code, which means we deleting a lot of overly complicated code. Two things made that possible, Dan and Github&#8217;s <a href="http://github.com/guides/post-receive-hooks">service hook in JSON</a>.</p>
<p>When the local directory is created, it is no longer a working directory with a branch checked out.  Now the buildmaster&#8217;s local repository is just a bare clone (thanks <a href="http://github.com/igorgue">Igor</a>). I added documentation and cleaned things up with <a href="http://www.logilab.org/project/pylint">pylint</a> (which I&#8217;ll be blogging about my experiences with that shortly) to be more inline with <a href="http://www.python.org/dev/peps/pep-0008/">PEP 8</a>.</p>
<p>Finally and most importantly, Dan and I fixed a &#8220;changes&#8221; bug that would repeat the commits from the JSON n+1 more times.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.apparatusproject.org/blog/2009/07/github-buildbot-redux/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The importance of unit testing and functional testing</title>
		<link>http://www.apparatusproject.org/blog/2009/07/the-importance-of-unit-testing-and-functional-testing/</link>
		<comments>http://www.apparatusproject.org/blog/2009/07/the-importance-of-unit-testing-and-functional-testing/#comments</comments>
		<pubDate>Wed, 01 Jul 2009 07:00:21 +0000</pubDate>
		<dc:creator>Dan Reverri</dc:creator>
				<category><![CDATA[apparatus]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[functional testing]]></category>
		<category><![CDATA[unit-testing]]></category>

		<guid isPermaLink="false">http://app.arat.us/blog/?p=159</guid>
		<description><![CDATA[I recently read a blog article, Benefits of automated functional testing, which included a section arguing that unit testing was not as important as functional testing. I agree that functional testing is important (and the author provides several good arguments for it) but I am concerned about the negativity against unit testing. The author makes [...]]]></description>
			<content:encoded><![CDATA[<p class="dropcap-first">I recently read a blog article, <a href="http://sdk.org.nz/2009/02/25/why-unit-testing-is-a-waste-of-time/">Benefits of automated functional testing</a>, which included a section arguing that unit testing was not as important as functional testing. I agree that functional testing is important (and the author provides several good arguments for it) but I am concerned about the negativity against unit testing. The author makes the following argument in favor of functional testing which I think is a great argument in favor of all testing:</p>
<blockquote><p>The complexity that does arise in this kind of software is all down to interactions between components, messy and changing business requirements and how the whole blob integrates at runtime.</p></blockquote>
<p>I think the &#8220;interactions&#8221; issue is one that can be addressed by unit tests. The interaction between components boils down to one component making a request of another component; for example calling a method with an agreed upon set of arguments. The requesting component will have an expectation for the return of the method. If the called method does not meet the expectations of the request then a failure will occur. Unit tests can be used to verify that a method returns in an expected way.</p>
<p>With unit tests in place developers can confidently re-factor their code knowing that any violated expectations will be revealed when running those tests. It would be nice to account for every possible scenarios and test for every fringe case but that is unrealistic. Unit tests can be used to make an agreement with other developers saying &#8220;this code will do A when given B at all times&#8221;; developers are free to go outside the bounds of these expectations but do so knowing that their use of that unit of code is untested.</p>
<p>I&#8217;ve been sitting on a draft of a post regarding the importance of both functional and unit testing. I&#8217;ve included it below:</p>
<p>I&#8217;ve been thinking about a way to explain the importance of both functional and unit testing. I&#8217;ve been trying to come up with an appropriate analogy and have settled on the following:</p>
<p>Let&#8217;s imagine a particular software application is a physical structure such as a bridge. The materials used in the construction of the bridge are analogous to the units of a software application. The shape of the bridge is analogous to the functional operations of a software application.</p>
<p>When determining the strength of a bridge, the shape of the bridge plays a significant role, however, a determination of strength is not complete without knowing the material being used to construct the bridge.</p>
<p>Unit tests measure the quality of material used to build the application.</p>
<p>Functional tests measure the strength of the application structure.</p>
<p>The overall quality of the application is dependent on both.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.apparatusproject.org/blog/2009/07/the-importance-of-unit-testing-and-functional-testing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
