[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