<?xml version="1.0"?>
<rss version="2.0">
   <channel>
      <title>Yeoldeclue</title>
      <link>http://yeoldeclue.com/cgi-bin/blog/blog.cgi</link>
      <description>Random musings on random stuff...</description>
      <language>en-uk</language>
      <pubDate> Sun, 04 Oct 2009 21:55:16 +0000 </pubDate>
      <lastBuildDate> Sun, 04 Oct 2009 21:55:16 +0000 </lastBuildDate>
      <docs>http://blogs.law.harvard.edu/tech/rss</docs>
      <generator>Kamaelia 0.1</generator>
      <managingEditor>ms@cerenity.org</managingEditor>
      <webMaster>ms@cerenity.org</webMaster>
      <item>
         <title>Kamaelia components from decorated generators. Pythonic concurrency?</title>
         <link>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1254693316</link>
         <author>Michael</author>
         <description><![CDATA[A few months ago, there was a <a href="http://groups.google.com/group/python-concurrency/browse_thread/thread/5325b130e1ae315a">thread</a> on the then google group <a href="http://groups.google.com/group/python-concurrency/">python-concurrency </a>about some standard forms for showing how some libraries deal with concurrent problems. The specific example chosen looked like this:<br><blockquote><font face="Courier New, monospace">#!/bin/sh</font><br><font face="Courier New, monospace">tail -f /var/log/system.log |grep pants</font><br></blockquote>Pete Fein also posted an example of this using generators, based on David Beazley's talk on python generators being used as (limited) coroutines:<br><blockquote><font face="Courier New, monospace">&nbsp;&nbsp;&nbsp; import time<br>&nbsp;&nbsp;&nbsp; import re<br>]]></description>
         <pubDate>Sun, 04 Oct 2009 21:55:16 +0000</pubDate>
         <guid>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1254693316</guid>
      </item>
      <item>
         <title>Restarting Python Northwest. 24th Sept </title>
         <link>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1252967802</link>
         <author>Michael</author>
         <description><![CDATA[]]></description>
         <pubDate>Mon, 14 Sep 2009 22:36:42 +0000</pubDate>
         <guid>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1252967802</guid>
      </item>
      <item>
         <title>Traffic Server to be Open Source?!</title>
         <link>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1246964565</link>
         <author>Michael</author>
         <description><![CDATA[<a href="http://wiki.apache.org/incubator/TrafficServerProposal">If this happens this will be awesome</a>. Traffic Server is some really nice code. It's a large codebase, but it's really cool, and it *scales*. (I used to work at Inktomi, so have been inside the code as well). For those that don't know what it is, it's a very high performance web caching proxy, with a plugin architecture, allowing for the addition of other protocols. It used to support HTTP (&amp; obvious friends), NNTP, RTSP, RTP, WMV, etc.<br>]]></description>
         <pubDate>Tue, 07 Jul 2009 11:02:45 +0000</pubDate>
         <guid>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1246964565</guid>
      </item>
      <item>
         <title>Europython Videos Transcoding</title>
         <link>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1246925071</link>
         <author>Michael</author>
         <description><![CDATA[Since I've had a few questions about this, a short status update. At Europython last week I was recording all the talks I was attending. Including the lightning talks this means I have video from 55 talks. The video files from the camera are too large for blip.tv, so I'm transcoding them down to a smaller size, before uploading them. Since these 55 talks are spread over nearly 80 files, that naturally takes time.<br>]]></description>
         <pubDate>Tue, 07 Jul 2009 00:04:31 +0000</pubDate>
         <guid>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1246925071</guid>
      </item>
      <item>
         <title>Autoloading in python</title>
         <link>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1245597300</link>
         <author>Michael</author>
         <description><![CDATA[Before I started using python, I'd used perl for several years, and one thing which I'd liked about perl was its <a href="http://perldoc.perl.org/perltoot.html#AUTOLOAD%3a-Proxy-Methods">autoload</a> facility. Now in python the closest equivalent that I've seen is __getattr__ for classes, but not __getattr__ for a module. This seemed like a real shame since there are times when autoload can be incredibly useful.<br>If it seems chaotic, consider the Unix PATH variable. Any time you type a name, the shell looks in lots of locations and runs the first one it finds. That's effectively the same sort of idea as autoloading. Yes, you can do some really nasty magic if you want, but then you can do that with the shell to, and generally people get along find.<br>Anyway, vaguely curious about it I decided to do some digging around, and came across <a href="http://mail.python.org/pipermail/python-list/2007-January/594272.html">this post</a> by Leif K Brookes, which suggests this:<br><blockquote>You could wrap it in an object, but that's a bit of a hack.<br>]]></description>
         <pubDate>Sun, 21 Jun 2009 15:15:00 +0000</pubDate>
         <guid>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1245597300</guid>
      </item>
      <item>
         <title>Europython </title>
         <link>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1244651747</link>
         <author>Michael</author>
         <description><![CDATA[&nbsp;I've mentioned this in a couple of places, but mentioning on my blog seems appropriate too.<br>]]></description>
         <pubDate>Wed, 10 Jun 2009 16:35:47 +0000</pubDate>
         <guid>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1244651747</guid>
      </item>
      <item>
         <title>New Tool for helping debugging Kamaelia Systems</title>
         <link>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1244481479</link>
         <author>Michael</author>
         <description><![CDATA[I've added a PythonInterpreter component to Kamaelia in Kamaelia.Experimental.PythonInterpreter. The primary use for this is intended to assist with debugging, but there are other possible uses.<br><h4>Use in a system</h4>This allows a variety of things, from a basic command line console:<br><blockquote><font face="Courier New, monospace">StandaloneInterpreter().run()</font><br></blockquote>Which you can run in the background on any console. For example you could do <br>this:<br><blockquote><font face="Courier New, monospace">&nbsp; &nbsp; ServerCore(protocol=myprotocol, port=1234).activate()<br>&nbsp; &nbsp; StandaloneInterpreter().run()<br></font></blockquote>Alternatively, you can use an embeddable component that speaks to inbox/outbox rather than stdin/stdout. Crudely you can do something like this:<br><blockquote><font face="Courier New, monospace">&nbsp; &nbsp; Pipeline(</font><br><font face="Courier New, monospace">&nbsp; &nbsp; &nbsp; &nbsp; ConsoleReader(),</font><br><font face="Courier New, monospace">&nbsp; &nbsp; &nbsp; &nbsp; InterpreterTransformer(),</font><br><font face="Courier New, monospace">&nbsp; &nbsp; &nbsp; &nbsp; ConsoleEchoer(),</font><br><font face="Courier New, monospace">&nbsp; &nbsp; ).run()</font><br></blockquote>But you can also put it inside a pygame application, reading &amp; writing from a <br>Textbox/TextDisplayer:<br>&nbsp; &nbsp; Pipeline(<br>&nbsp; &nbsp; &nbsp; &nbsp; Textbox(size = (800, 300), position = (100,380)),<br>&nbsp; &nbsp; &nbsp; &nbsp; InterpreterTransformer(),<br>&nbsp; &nbsp; &nbsp; &nbsp; TextDisplayer(size = (800, 300), position = (100,40)),<br>&nbsp; &nbsp; ).run()<br>]]></description>
         <pubDate>Mon, 08 Jun 2009 17:17:59 +0000</pubDate>
         <guid>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1244481479</guid>
      </item>
      <item>
         <title>Going from generator coroutines to Kamaelia Components</title>
         <link>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1242522657</link>
         <author>Michael</author>
         <description><![CDATA[Earlier this evening an <a href="http://groups.google.com/group/unladen-swallow/browse_thread/thread/e2c2f9fd61041f0">announcement by Pete Fein</a> regarding the formation of a <a href="http://groups.google.com/group/python-concurrency">python-concurrency</a> mailing list (aka Python Concurrency Special Interest Group) bounced past my inbox in the <a href="http://groups.google.com/group/unladen-swallow">unladen-swallow</a> mailing list. Naturally, given my work on <a href="http://www.kamaelia.org/Docs/Axon/Axon">Axon</a> (a concurrency library) and <a href="http://www.kamaelia.org/Home">Kamaelia</a> (a bunch of components that use it), it jumped out at me as interesting. (<a href="http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1235690128">5 minute overview</a> for those that don't know what Kamaelia is...)<br>]]></description>
         <pubDate>Sun, 17 May 2009 01:10:56 +0000</pubDate>
         <guid>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1242522657</guid>
      </item>
      <item>
         <title>Bar Camp Leeds UK</title>
         <link>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1241557002</link>
         <author>Michael</author>
         <description><![CDATA[Bar Camp Leeds (UK) is running for its 3rd year running. It'd be great to see other Python people there if you're around. Details:<br><ul><li>May 30th, May 31st</li><li>Old Broadcasting House, Leeds, UK</li><li>Website: <a href="http://barcampleeds.com/">http://barcampleeds.com/</a></li></ul><br>]]></description>
         <pubDate>Tue, 05 May 2009 20:56:42 +0000</pubDate>
         <guid>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1241557002</guid>
      </item>
      <item>
         <title>Schedulers matter</title>
         <link>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1236162413</link>
         <author>Michael</author>
         <description><![CDATA[Improving the scheduler. It's been something we've avoided for quite a while in Kamaelia, but <a href="http://entitycrisis.blogspot.com/">Simon Wittber</a>'s recent post benchmarking <a href="http://code.google.com/p/fibra/">Fibra</a> vs <a href="http://www.stackless.com/">Kamaelia</a> vs <a href="http://www.stackless.com/">stackless</a> is interesting. His key showing that "Stackless is 7x faster than Fibra, and Fibra is 10x faster than Kamaelia" are cool for him :-) ... and naturally led me to think "why". Looking at the code, it struck me that he's doing something more interesting with the scheduler given these code forms:<br><blockquote><font face="Courier New, monospace">scheduler.install(self.messageLoop()) <br><i><font face="Arial, Helvetica, sans-serif"># self.MessageLoop is a regular python generator</font></i><br>...<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yield self.incrementCounter()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yield kickTo.messageQueue.push(self)<br></font></blockquote>If you delve inside the fibra scheduler (which doesn't appear to be <a href="http://code.google.com/p/fibra/source/browse">here</a> unexpectedly) you see the following core:<br><blockquote><font face="Courier New, monospace">&nbsp;&nbsp;&nbsp; <b>def</b> tick(self):<br><i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; """Iterates the scheduler, running all tasks and calling all<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handlers.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; """<br></i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; active = False<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>for</b> handler <b>in</b> self.handlers:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; active = handler.is_waiting() <b>or</b> active<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; active = (len(self.tasks) &gt; 0) <b>or</b> active<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tasks = []<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>while</b> True:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>try</b>:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; task, send_value = self.tasks.pop(0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>except</b> IndexError, e:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>break</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>try</b>:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>if</b> isinstance(send_value, Exception):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = task.throw(send_value)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>else</b>:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = task.send(send_value)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>except</b> StopIteration, e:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = e<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>if</b> r <b>is</b> None:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tasks.append((task, None))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>else</b>:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>try</b>:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handler = self.type_handlers[type(r)]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>except</b> KeyError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>raise</b> RuntimeError("Don't know what to do with yielded type: %s" % type(r))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handler.handle(r, task)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.tasks[:] = tasks<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>return</b> active<br></font></blockquote>The core of this appears to be "when I'm done, do this later" next. If you think that's familiar, it should be - its very <i>similar</i> (at least conceptually) to what twisted does with deferreds. It's not identical, but similar. So what does this mean for the hacksack demo? Well, if we look at self.tasks after each run, by changing:<br><blockquote><font face="Courier New, monospace">&nbsp;&nbsp;&nbsp; <b>def</b> run(self):</font><br><font face="Courier New, monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>while</b> self.tick():</font><br><font face="Courier New, monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>pass</b></font><br></blockquote>to:<br><blockquote><font face="Courier New, monospace">&nbsp;&nbsp;&nbsp; <b>def</b> run(self):</font><br><font face="Courier New, monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>while</b> self.tick():</font><br><font face="Courier New, monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>print</b> "TASKS", [x[0] <b>for</b> x <b>in</b> self.tasks]</font><br></blockquote>It becomes apparent what's happening (though it's fairly obvious from above):<br><blockquote><font face="Courier New, monospace">TASKS [&lt;generator object at 0xb7b04fcc&gt;]<br>TASKS []<br>TASKS [&lt;generator object at 0xb780f94c&gt;]<br>TASKS []<br>TASKS [&lt;generator object at 0xb7a1b04c&gt;]<br>TASKS []<br>TASKS [&lt;generator object at 0xb776fcac&gt;]<br>TASKS []<br>TASKS [&lt;generator object at 0xb79327ac&gt;]<br>TASKS []<br>TASKS [&lt;generator object at 0xb7b0ff2c&gt;]<br>TASKS []<br></font></blockquote>Fundamentally, the reason it's quicker for two reasons:<br><ul><li>It always knows which generator is ready to run next.</li><li>It also defaults to pausing the generator, unless it specifically asks to be run. ie the tasks default to being passive.</li><li>The sender knows who the receiver is. This allows the sender to schedule the receiver explicitly.</li></ul>These two points matter because Axon's scheduler (from jesse's post, hopefully people are aware that Axon is the relevant part of kamaelia here):<br><ul><li>Is effectively a round robin scheduler - essentially for simplicity. The key question we wanted to ask was <i>"does a component model based around inboxes/outboxes make it easier to make easier to write/reuse concurrent software", rather than "how can we build a faster, more responsive scheduler"</i>. As a result the round robin scheduler was always a compromise. There's a <i>little</i> bit of intelligence in there, but not much.<br></li><li>Kamaelia's components default to active, rather than passive. That is they're expected to run continuously unless explicitly paused. This design decision impacts the scheduler as a whole.</li><li>The sender does <b>not</b> know who the receiver is. This requires something different to happen in the scheduler. On the upside, it means that code can be tested easier in isolation, or reused in situations it wasn't originally expected to be used within.<br></li></ul>This leads me to the rather obvious solution here - can we rebuild a better Axon scheduler by reusing fibra and throw away our scheduler? If so that would be really neat - throwing away our scheduler for something faster and more intelligent would be rather fun :) If we can't then we've been pondering improving it - that is making it more intelligent - for a while. Fibra's benchmarks suggest that doing so would be well worth it. The question this raises though is whether doing this would help us in the general case. At present I'm unclear on that, but until you try, you don't know.<br>]]></description>
         <pubDate>Wed, 04 Mar 2009 10:26:54 +0000</pubDate>
         <guid>http://yeoldeclue.com/cgi-bin/blog/blog.cgi?rm=viewpost&amp;nodeid=1236162413</guid>
      </item>
   </channel>
</rss>

