<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	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/"
		>
<channel>
	<title>Comments on: generator based concurrent programming in python</title>
	<atom:link href="http://www.rhonabwy.com/wp/2007/11/13/generator-based-concurrent-programming-in-python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.rhonabwy.com/wp/2007/11/13/generator-based-concurrent-programming-in-python/</link>
	<description>Mac, iOS, DevOps, and daily life in Seattle</description>
	<lastBuildDate>Tue, 24 Aug 2010 12:39:30 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
	<item>
		<title>By: Rhonabwy &#187; generator based concurrent programming - redux</title>
		<link>http://www.rhonabwy.com/wp/2007/11/13/generator-based-concurrent-programming-in-python/comment-page-1/#comment-49801</link>
		<dc:creator>Rhonabwy &#187; generator based concurrent programming - redux</dc:creator>
		<pubDate>Wed, 28 Nov 2007 02:50:53 +0000</pubDate>
		<guid isPermaLink="false">http://www.rhonabwy.com/wp/2007/11/13/generator-based-concurrent-programming-in-python/#comment-49801</guid>
		<description>[...] A little earlier in November, I wrote up a little concurrent programming exercise using Kamaelia. Michael Sparks commented a bit on it, and suggested some improvements - which was really cool. He&#8217;s the guy that make Kamaelia, and helped me a few months back when I was first investigating &#8220;hey, will this work?&#8221; [...]</description>
		<content:encoded><![CDATA[<p>[...] A little earlier in November, I wrote up a little concurrent programming exercise using Kamaelia. Michael Sparks commented a bit on it, and suggested some improvements &#8211; which was really cool. He&#8217;s the guy that make Kamaelia, and helped me a few months back when I was first investigating &#8220;hey, will this work?&#8221; [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Joe</title>
		<link>http://www.rhonabwy.com/wp/2007/11/13/generator-based-concurrent-programming-in-python/comment-page-1/#comment-49312</link>
		<dc:creator>Joe</dc:creator>
		<pubDate>Wed, 21 Nov 2007 23:37:27 +0000</pubDate>
		<guid isPermaLink="false">http://www.rhonabwy.com/wp/2007/11/13/generator-based-concurrent-programming-in-python/#comment-49312</guid>
		<description>You helped to me a while back on the Kamaelia mailing list and got me headed in this direction - so thank you! And thank you for this tweak on the code!

I expected there were some optimizations in there that I could make, but hadn&#039;t yet teased out. In fact, I knew about pause() keeping things off the run loop until it was &quot;woken&quot; - but I hadn&#039;t gone back and read through the code to see if the way I was injecting messages into an &quot;inbox&quot; would properly awake the target.

It is more memory hungry than Stackless - to be expected since they ripped out the whole stack frame setup, their smallest tasklets are just tiny amounts of memory. Even still - it was the scaling aspect that I really wanted to dig into and see. 

I fully expect I&#039;ll keep fiddling and teasing with this setup for a while. I&#039;ll post more on my blog as I roll it forward.</description>
		<content:encoded><![CDATA[<p>You helped to me a while back on the Kamaelia mailing list and got me headed in this direction &#8211; so thank you! And thank you for this tweak on the code!</p>
<p>I expected there were some optimizations in there that I could make, but hadn&#8217;t yet teased out. In fact, I knew about pause() keeping things off the run loop until it was &#8220;woken&#8221; &#8211; but I hadn&#8217;t gone back and read through the code to see if the way I was injecting messages into an &#8220;inbox&#8221; would properly awake the target.</p>
<p>It is more memory hungry than Stackless &#8211; to be expected since they ripped out the whole stack frame setup, their smallest tasklets are just tiny amounts of memory. Even still &#8211; it was the scaling aspect that I really wanted to dig into and see. </p>
<p>I fully expect I&#8217;ll keep fiddling and teasing with this setup for a while. I&#8217;ll post more on my blog as I roll it forward.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Michael Sparks</title>
		<link>http://www.rhonabwy.com/wp/2007/11/13/generator-based-concurrent-programming-in-python/comment-page-1/#comment-49305</link>
		<dc:creator>Michael Sparks</dc:creator>
		<pubDate>Wed, 21 Nov 2007 23:12:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.rhonabwy.com/wp/2007/11/13/generator-based-concurrent-programming-in-python/#comment-49305</guid>
		<description>Gah, formatting is broken there, the code looks like this:
Changing this part of your code:
....def main(self):
........yield 1
........while 1:
............if self.dataReady(&#039;inbox&#039;):

To 
....def main(self):
........yield 1
........while 1:
............while not self.anyReady():
................self.pause()
................yield 1
............while self.dataReady(&#039;inbox&#039;): # Note change from &quot;if&quot;

Oh, the reason why the stackless version would be interesting is because it&#039;d give a relatively simple optimisation path for code if needed :-)</description>
		<content:encoded><![CDATA[<p>Gah, formatting is broken there, the code looks like this:<br />
Changing this part of your code:<br />
&#8230;.def main(self):<br />
&#8230;&#8230;..yield 1<br />
&#8230;&#8230;..while 1:<br />
&#8230;&#8230;&#8230;&#8230;if self.dataReady(&#8216;inbox&#8217;):</p>
<p>To<br />
&#8230;.def main(self):<br />
&#8230;&#8230;..yield 1<br />
&#8230;&#8230;..while 1:<br />
&#8230;&#8230;&#8230;&#8230;while not self.anyReady():<br />
&#8230;&#8230;&#8230;&#8230;&#8230;.self.pause()<br />
&#8230;&#8230;&#8230;&#8230;&#8230;.yield 1<br />
&#8230;&#8230;&#8230;&#8230;while self.dataReady(&#8216;inbox&#8217;): # Note change from &#8220;if&#8221;</p>
<p>Oh, the reason why the stackless version would be interesting is because it&#8217;d give a relatively simple optimisation path for code if needed <img src='http://www.rhonabwy.com/wp/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Michael Sparks</title>
		<link>http://www.rhonabwy.com/wp/2007/11/13/generator-based-concurrent-programming-in-python/comment-page-1/#comment-49304</link>
		<dc:creator>Michael Sparks</dc:creator>
		<pubDate>Wed, 21 Nov 2007 23:07:58 +0000</pubDate>
		<guid isPermaLink="false">http://www.rhonabwy.com/wp/2007/11/13/generator-based-concurrent-programming-in-python/#comment-49304</guid>
		<description>Hi,

Yes the project is still going :-) Interesting benchmark.

First of all, your code, on my machine:

/media/usbdisk/Kamaelia&gt; python /usr/lib/python2.5/timeit.py &quot;import hackysack&quot; &quot;hackysack.runit(10,1000)&quot;
10 loops, best of 3: 182 msec per loop

/media/usbdisk/Kamaelia&gt; python /usr/lib/python2.5/timeit.py &quot;import hackysack&quot; &quot;hackysack.runit(100,1000)&quot;
10 loops, best of 3: 820 msec per loop

/media/usbdisk/Kamaelia&gt; python /usr/lib/python2.5/timeit.py &quot;import hackysack&quot; &quot;hackysack.runit(1000,1000)&quot;
10 loops, best of 3: 9.23 sec per loop

I kinda lost patience at this point - so I made a simple change:

Changing this part of your code:
    def main(self):
        yield 1
        while 1:
            if self.dataReady(&#039;inbox&#039;):

To 
    def main(self):
        yield 1
        while 1:
            while not self.anyReady():
                self.pause()
                yield 1
            while self.dataReady(&#039;inbox&#039;): # Note change from &quot;if&quot;

Yields the following change:

I suppose the difference here from threads is that when we pause, we do actually
pause and get removed from the run queue.

/media/usbdisk/Kamaelia&gt; python /usr/lib/python2.5/timeit.py &quot;import hackysack&quot; &quot;hackysack.runit(10,1000)&quot;
10 loops, best of 3: 206 msec per loop

/media/usbdisk/Kamaelia&gt; python /usr/lib/python2.5/timeit.py &quot;import hackysack&quot; &quot;hackysack.runit(100,1000)&quot;
10 loops, best of 3: 267 msec per loop

/media/usbdisk/Kamaelia&gt; python /usr/lib/python2.5/timeit.py &quot;import hackysack&quot; &quot;hackysack.runit(1000,1000)&quot;
10 loops, best of 3: 816 msec per loop

I can&#039;t reliably test above that because I don&#039;t have enough memory. However, even with that caveat:

/media/usbdisk/Kamaelia&gt; python /usr/lib/python2.5/timeit.py &quot;import hackysack&quot; &quot;hackysack.runit(5000,1000)&quot;
10 loops, best of 3: 2.77 sec per loop

That figure includes my machine swapping. Despite that, I think that&#039;s somewhat better :-)

I&#039;ve got a feeling that this is much more memory hungry - probably need to look into that. The optimisations to allow this were aimed at allowing the system to use next to zero cpu when it can (since we were doing the changes to allow shelling out to transcoders to utlise as much CPU as possible). As a result memory wasn&#039;t a consideration at the time.

(these are running on an Open SuSE 10.3 laptop : Intel(R) Pentium(R) M processor 1.60GHz, 496 MB RAM, Python 2.5.1 &amp; firefox sitting in the background eating up 372MB RAM....)

Looking at the Why Stackless link, this is still slower than stackless (which makes sense, stackless *does* remove a layer of complexity), but it appears to have similar scaling properties. Also, I suspect part of the issue is the fact that our scheduler is implemented in python rather than C. 

It&#039;s tempting to see what would happen with the same code running under stackless, and then changed such the the components were tasklets rather than generators. (inboxes/outboxes could then be implemented using channels after all)</description>
		<content:encoded><![CDATA[<p>Hi,</p>
<p>Yes the project is still going <img src='http://www.rhonabwy.com/wp/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Interesting benchmark.</p>
<p>First of all, your code, on my machine:</p>
<p>/media/usbdisk/Kamaelia&gt; python /usr/lib/python2.5/timeit.py &#8220;import hackysack&#8221; &#8220;hackysack.runit(10,1000)&#8221;<br />
10 loops, best of 3: 182 msec per loop</p>
<p>/media/usbdisk/Kamaelia&gt; python /usr/lib/python2.5/timeit.py &#8220;import hackysack&#8221; &#8220;hackysack.runit(100,1000)&#8221;<br />
10 loops, best of 3: 820 msec per loop</p>
<p>/media/usbdisk/Kamaelia&gt; python /usr/lib/python2.5/timeit.py &#8220;import hackysack&#8221; &#8220;hackysack.runit(1000,1000)&#8221;<br />
10 loops, best of 3: 9.23 sec per loop</p>
<p>I kinda lost patience at this point &#8211; so I made a simple change:</p>
<p>Changing this part of your code:<br />
    def main(self):<br />
        yield 1<br />
        while 1:<br />
            if self.dataReady(&#8216;inbox&#8217;):</p>
<p>To<br />
    def main(self):<br />
        yield 1<br />
        while 1:<br />
            while not self.anyReady():<br />
                self.pause()<br />
                yield 1<br />
            while self.dataReady(&#8216;inbox&#8217;): # Note change from &#8220;if&#8221;</p>
<p>Yields the following change:</p>
<p>I suppose the difference here from threads is that when we pause, we do actually<br />
pause and get removed from the run queue.</p>
<p>/media/usbdisk/Kamaelia&gt; python /usr/lib/python2.5/timeit.py &#8220;import hackysack&#8221; &#8220;hackysack.runit(10,1000)&#8221;<br />
10 loops, best of 3: 206 msec per loop</p>
<p>/media/usbdisk/Kamaelia&gt; python /usr/lib/python2.5/timeit.py &#8220;import hackysack&#8221; &#8220;hackysack.runit(100,1000)&#8221;<br />
10 loops, best of 3: 267 msec per loop</p>
<p>/media/usbdisk/Kamaelia&gt; python /usr/lib/python2.5/timeit.py &#8220;import hackysack&#8221; &#8220;hackysack.runit(1000,1000)&#8221;<br />
10 loops, best of 3: 816 msec per loop</p>
<p>I can&#8217;t reliably test above that because I don&#8217;t have enough memory. However, even with that caveat:</p>
<p>/media/usbdisk/Kamaelia&gt; python /usr/lib/python2.5/timeit.py &#8220;import hackysack&#8221; &#8220;hackysack.runit(5000,1000)&#8221;<br />
10 loops, best of 3: 2.77 sec per loop</p>
<p>That figure includes my machine swapping. Despite that, I think that&#8217;s somewhat better <img src='http://www.rhonabwy.com/wp/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>I&#8217;ve got a feeling that this is much more memory hungry &#8211; probably need to look into that. The optimisations to allow this were aimed at allowing the system to use next to zero cpu when it can (since we were doing the changes to allow shelling out to transcoders to utlise as much CPU as possible). As a result memory wasn&#8217;t a consideration at the time.</p>
<p>(these are running on an Open SuSE 10.3 laptop : Intel(R) Pentium(R) M processor 1.60GHz, 496 MB RAM, Python 2.5.1 &amp; firefox sitting in the background eating up 372MB RAM&#8230;.)</p>
<p>Looking at the Why Stackless link, this is still slower than stackless (which makes sense, stackless *does* remove a layer of complexity), but it appears to have similar scaling properties. Also, I suspect part of the issue is the fact that our scheduler is implemented in python rather than C. </p>
<p>It&#8217;s tempting to see what would happen with the same code running under stackless, and then changed such the the components were tasklets rather than generators. (inboxes/outboxes could then be implemented using channels after all)</p>
]]></content:encoded>
	</item>
</channel>
</rss>
