[PEAK] PEAK and Twisted, revisited

Phillip J. Eby pje at telecommunity.com
Sun Apr 18 00:52:22 EDT 2004


At 12:49 AM 4/17/04 +0200, ueck at net-labs.de wrote:

> > Note, however, that if your server needs to operate in an async manner, 
> you
> > will need both a service area pool and a thread pool.  The same might also
> > apply to your client software, if it needs to be asynchronous as well.
>
>will peak.query coop async operation, i.e. yields results ?

My main target for asynchrony in peak.query will be for change events 
(facts added/removed) rather than for results.  I anticipate that it will 
be quite possible to implement async query methodology as well, but I think 
it adds needless overhead to use something like Twisted's adbapi compared 
to just writing a half-async threaded or forking server.  Given that in my 
day job I write apps to run on multiprocessor boxes, I prefer to use 
half-async + fork as a model for request handling.  Synchronous code is 
much easier to write than async code, and forking eliminates most worries 
about race conditions, as well as bypassing any GIL bottleneck.


>are there plans to make the other frameworks usable with peak.events:
>- naming (lookup)
>- web (DOMlet.renderFor, ...)
>- storage (yielding Elements based on query-results)

Not really.  There aren't really very many things that work well as async 
code, in my view.  Certain programming tasks are naturally asynchronous, 
and these are essentially event-driven activities such as GUIs and reactive 
or rule-based systems.  And if one wishes to write highly-scalable 
networking code, either in client or server form, or if one wishes to 
mingle clients and servers, then event-driven is also the way to go.  But 
in my book it seems silly to write the actual processing of requests in an 
asynchronous format.

Look at it this way...  no matter what, you eventually get down to code 
that waits for something, thereby stopping your event flow.  Twisted adbapi 
handles this by farming off the smallest possible bits of work to threads: 
individual blocking operations.  But this is wasteful, because there is a 
significant amount of overhead involved in transferring the work between 
threads.  Similarly, rendering a page asynchronously is dreadfully 
wasteful, whether you use peak.events yielding or deferred 
callbacks.  Either way, you incur extra function call overheads for 
breaking the work into smaller pieces.

I prefer to handle this sort of thing in larger chunks.  For most web 
applications, there's little reason to incrementally render a page, and no 
network I/O taking place during the page's rendering.  So why do it 
asynchronously?  Instead, bundle up the incoming request, and hand it off 
to a thread.  Then you're not forced to make every API you work with 
asynchronous.  In the case of Twisted, I suggest using deferToThread() to 
invoke such operation chunks, e.g.:

         yield self.reactor.deferToThread(self.processRequest, request)
         response = events.resume()

Then you can write the interesting parts of your application as synchronous 
code, and it's a lot easier to write correct synchronous code than 
asynchronous code!


>i think if one make a desicion towards async operations it's
>a fairly strong commitment. so most of the parts of peak are
>likely to be used with peak.events and should give other
>tasks a chance to process.

Not really.  It would make the other APIs much harder to write correctly 
and to test fully.  It would also be horribly inefficient both for the 
developer trying to work with the API and for the computer that's executing it.

Asynchrony is *hard*.  Even casting it in pseudo-synchronous form as 
peak.events does, you still have to think about all sorts of remote 
interaction issues in any moderately complex application.  You really don't 
want to add even one iota of asynchrony more than your application actually 
needs.




More information about the PEAK mailing list