Comments on: My Twisted Apologies http://laurentszyster.be/blog/my-twisted-apologies/ Python on Peers Tue, 07 Feb 2012 14:27:38 +0000 http://wordpress.org/?v=1.5.1.3 by: Laurent Szyster http://laurentszyster.be/blog/my-twisted-apologies/#comment-211 Tue, 07 Feb 2006 16:58:24 +0000 http://laurentszyster.be/blog/my-twisted-apologies/#comment-211 Hi "Hu?", Who ever you may be. As far as I know, it works on Python 2.2, 2.3 and now 2.4, on Linux and Windows. The CPython interpreter simply does not release instances themselves until the __del__ is called *and* all its references released. What else would you expect? There are no arcanes in Python. Don't fear its sources. It is a simple and elegant implementation. That's why CPython is faster than Ruby and Perl. Less resource hungry than Java and twice as fast when implemented with Microsoft's proprietary VM (heck it was written by the author of TurboPascal!). Hi “Hu?”,

Who ever you may be.

As far as I know, it works on Python 2.2, 2.3 and now 2.4, on Linux and Windows. The CPython interpreter simply does not release instances themselves until the __del__ is called *and* all its references released.

What else would you expect?

There are no arcanes in Python.

Don’t fear its sources. It is a simple and elegant implementation.

That’s why CPython is faster than Ruby and Perl. Less resource hungry than Java and twice as fast when implemented with Microsoft’s proprietary VM (heck it was written by the author of TurboPascal!).

]]>
by: Huh? http://laurentszyster.be/blog/my-twisted-apologies/#comment-210 Tue, 07 Feb 2006 15:48:09 +0000 http://laurentszyster.be/blog/my-twisted-apologies/#comment-210 Are you seriously trying to sell a dependancy on the Python GC as a *feature*? The most arcane, unstable (between versions) and unpredictable system the platform provides? *SERIOUSLY*? As long as you're trying to cheese people off with pumped-up claims, you should invite Christian Tismer to comment on your "pure Python continuations". Are you seriously trying to sell a dependancy on the Python GC as a *feature*? The most arcane, unstable (between versions) and unpredictable system the platform provides? *SERIOUSLY*?

As long as you’re trying to cheese people off with pumped-up claims, you should invite Christian Tismer to comment on your “pure Python continuations”.

]]>
by: Allegra » Blog Archive » To the Ravening Hordes: Thank You! http://laurentszyster.be/blog/my-twisted-apologies/#comment-205 Mon, 06 Feb 2006 07:57:39 +0000 http://laurentszyster.be/blog/my-twisted-apologies/#comment-205 [...] My Twisted Apologies drove from their divmod lair a ravening horde of Minions to tear down Allegra’s implementation of continuations in an Python asynchronous loop. They forced me look once more on code that had been left alone for years. Enough to break the “don’t fix something that’s not broken” sceal. And find out that there was an even simpler implementation … with an additionnal functional interface available. [...] […] My Twisted Apologies drove from their divmod lair a ravening horde of Minions to tear down Allegra’s implementation of continuations in an Python asynchronous loop. They forced me look once more on code that had been left alone for years. Enough to break the “don’t fix something that’s not broken” sceal. And find out that there was an even simpler implementation … with an additionnal functional interface available. […]

]]>
by: Laurent Szyster http://laurentszyster.be/blog/my-twisted-apologies/#comment-204 Mon, 06 Feb 2006 03:05:12 +0000 http://laurentszyster.be/blog/my-twisted-apologies/#comment-204 Hi Rene, Nice to have a second comment from somebody else than the "raven hordes of Twisted minions". But, hell, they scared me so much that I looked hard on some code that had been left alone for a few years now. And the result is a sure sign that peer review produces good things, whatever the malicious intentions of the reviewers. I should credit Valentino Volonghi for much of the findings ;-) Hi Rene,

Nice to have a second comment from somebody else than the “raven hordes of Twisted minions”. But, hell, they scared me so much that I looked hard on some code that had been left alone for a few years now.

And the result is a sure sign that peer review produces good things, whatever the malicious intentions of the reviewers.

I should credit Valentino Volonghi for much of the findings ;-)

]]>
by: Rene Dudfield http://laurentszyster.be/blog/my-twisted-apologies/#comment-203 Mon, 06 Feb 2006 00:57:41 +0000 http://laurentszyster.be/blog/my-twisted-apologies/#comment-203 I like a simpler still event design. eg. for event in events.get(): # handle event. if event.type == types.something: dosomething() You can also look at the whole list of events, and decide to act on only some. Allowing you to reason about what information you have available to you now. eg. # only act on the last something event in this loop iteration. # since we don't care about other ones. something_events = filter(lambda x:x.type == types.something, events) if something_events: one_something = something_events[-1] For scheduling a task you schedule an event instead. This way you are not throwing around code, but a small amount of data. Data can be more easily modified, and transferred than code in python. I also like splitting tasks up into using processes rather than reinventing scheduling, memory limits, cpu limits, memory protection, etc etc that the OS already provides. Sometimes. Different tools for different jobs. Twisted has support for using threads and processes when async just doesn't cut it. Allegra looks like it is aiming for simple, and to only work for a limited set of tasks. That's a goal that I like. If it can be shown that his approach works correctly, as well as shown to be performant then yah! I think it should address the use cases for processes, and threads when needed. So that if you do need them, then you can switch. Twisted took a while to realise that just using async is not a good idea. Hopefully Allegra does too. # occasional twisted user, simple lover. I like a simpler still event design.

eg.

for event in events.get():
# handle event.
if event.type == types.something:
dosomething()

You can also look at the whole list of events, and decide to act on only some. Allowing you to reason about what information you have available to you now.
eg.

# only act on the last something event in this loop iteration.
# since we don’t care about other ones.
something_events = filter(lambda x:x.type == types.something, events)
if something_events:
one_something = something_events[-1]

For scheduling a task you schedule an event instead. This way you are not throwing around code, but a small amount of data. Data can be more easily modified, and transferred than code in python.

I also like splitting tasks up into using processes rather than reinventing scheduling, memory limits, cpu limits, memory protection, etc etc that the OS already provides. Sometimes. Different tools for different jobs.

Twisted has support for using threads and processes when async just doesn’t cut it.

Allegra looks like it is aiming for simple, and to only work for a limited set of tasks. That’s a goal that I like. If it can be shown that his approach works correctly, as well as shown to be performant then yah! I think it should address the use cases for processes, and threads when needed. So that if you do need them, then you can switch. Twisted took a while to realise that just using async is not a good idea. Hopefully Allegra does too.

# occasional twisted user, simple lover.

]]>
by: Mark Rowe http://laurentszyster.be/blog/my-twisted-apologies/#comment-202 Sun, 05 Feb 2006 04:33:37 +0000 http://laurentszyster.be/blog/my-twisted-apologies/#comment-202 A side-to-side comparison between Deferred and Finalization like you suggest is meaningless, as Finalization implements only a small portion of Deferreds functionality. That's the last I'll say on this as I'm finding your attitude on this whole Allegra v. Twisted thing a touch too self-aggrandizing for my tastes. A side-to-side comparison between Deferred and Finalization like you suggest is meaningless, as Finalization implements only a small portion of Deferreds functionality.

That’s the last I’ll say on this as I’m finding your attitude on this whole Allegra v. Twisted thing a touch too self-aggrandizing for my tastes.

]]>
by: Laurent Szyster http://laurentszyster.be/blog/my-twisted-apologies/#comment-201 Sat, 04 Feb 2006 12:17:20 +0000 http://laurentszyster.be/blog/my-twisted-apologies/#comment-201 Hi Mark, Yes finalization.py is a "hack". But it works. For an asynchronous network peer in CPython only, but that's precisely the plateform targeted and: practicality beats purity (Zen of Python) Yes, this design is forcing its applications not to cycle finalized instances. Is it that hard to code without cycles? As for the relative quality of Deferred and Finalization design, well, we disagree. I suggest you print and put both sources side by side and ask somebody else wich one is more elegant. Regards, Hi Mark,

Yes finalization.py is a “hack”. But it works. For an asynchronous network peer in CPython only, but that’s precisely the plateform targeted and:

practicality beats purity (Zen of Python)

Yes, this design is forcing its applications not to cycle finalized instances.

Is it that hard to code without cycles?

As for the relative quality of Deferred and Finalization design, well, we disagree. I suggest you print and put both sources side by side and ask somebody else wich one is more elegant.

Regards,

]]>
by: Mark Rowe http://laurentszyster.be/blog/my-twisted-apologies/#comment-200 Sat, 04 Feb 2006 07:01:52 +0000 http://laurentszyster.be/blog/my-twisted-apologies/#comment-200 A few random points: You keep stating that Allegra's finalizations are "piggy-backed on the CPython Garbage Collector" which a simple examination of the module shows is untrue. It is based on Python's object finalization. This is orthogonal to the rest of the discussion, but I find it a little unnerving that you're suggesting people use code that makes heavy use of __del__ while apparently being unclear on the rammifcations. The garbage collector exists in Python primarily to clean up objects involved in reference cycles, which is one point that Pythons reference counting doesn't cope with. As the gc module documentation states, the presence of __del__ methods and are a part of a reference cycle will cause the entire cycle to be uncollectable. I believe this is one of the points that Valentino was trying to make earlier. Secondly, Finalization.__del__ method references a global object. Under some circumstances this can cause an exception to be raised. Quoting the Python documentations warning on the __del__ method: "Also, when __del__() is invoked in response to a module being deleted (e.g., when execution of the program is done), other globals referenced by the __del__() method may already have been deleted". Comments in the source of the allegra.finalization module say that the various classes and methods based on Finalization "make[s] Allegra's web peer a very interesting pateform for some business network applications development". Using globals from __del__ strikes me as going against that reliability that business network applications would require. Finally, Deferred feels a lot better designed than the Finalization class in Allegra. Deferred can be used completely independently of Twisteds reactor, while Finalization is tied to Allegras concept of a main loop. Deferreds design is trivial to port to other languages, while Finalization relies on an object finalization method that can resurrect the object being finalized. Finalization's reliance on the __del__ method feels very much like a hack as the Python language specification makes no guarantees about when, if at all, __del__ will be called on objects. Just my 2¢. A few random points:

You keep stating that Allegra’s finalizations are “piggy-backed on the CPython Garbage Collector” which a simple examination of the module shows is untrue. It is based on Python’s object finalization. This is orthogonal to the rest of the discussion, but I find it a little unnerving that you’re suggesting people use code that makes heavy use of __del__ while apparently being unclear on the rammifcations. The garbage collector exists in Python primarily to clean up objects involved in reference cycles, which is one point that Pythons reference counting doesn’t cope with. As the gc module documentation states, the presence of __del__ methods and are a part of a reference cycle will cause the entire cycle to be uncollectable. I believe this is one of the points that Valentino was trying to make earlier.

Secondly, Finalization.__del__ method references a global object. Under some circumstances this can cause an exception to be raised. Quoting the Python documentations warning on the __del__ method: “Also, when __del__() is invoked in response to a module being deleted (e.g., when execution of the program is done), other globals referenced by the __del__() method may already have been deleted”. Comments in the source of the allegra.finalization module say that the various classes and methods based on Finalization “make[s] Allegra’s web peer a very interesting pateform for some business network applications development”. Using globals from __del__ strikes me as going against that reliability that business network applications would require.

Finally, Deferred feels a lot better designed than the Finalization class in Allegra. Deferred can be used completely independently of Twisteds reactor, while Finalization is tied to Allegras concept of a main loop. Deferreds design is trivial to port to other languages, while Finalization relies on an object finalization method that can resurrect the object being finalized. Finalization’s reliance on the __del__ method feels very much like a hack as the Python language specification makes no guarantees about when, if at all, __del__ will be called on objects.

Just my 2¢.

]]>
by: Damjan http://laurentszyster.be/blog/my-twisted-apologies/#comment-199 Sat, 04 Feb 2006 04:19:45 +0000 http://laurentszyster.be/blog/my-twisted-apologies/#comment-199 > Besides the fact that documentation is pretty clear on what deferreds are: I wouldn't say so, I even have the Twisted book (from O'Reiley) and it's still not clear to me when to use deferred's and when to use something else.. and what? > Besides the fact that documentation is pretty clear on what deferreds are:

I wouldn’t say so, I even have the Twisted book (from O’Reiley) and it’s still not clear to me when to use deferred’s and when to use something else.. and what?

]]>
by: Laurent Szyster http://laurentszyster.be/blog/my-twisted-apologies/#comment-198 Sat, 04 Feb 2006 02:50:13 +0000 http://laurentszyster.be/blog/my-twisted-apologies/#comment-198 Hi Glyph, I'm glad this does not turn into a nasty war flame with you, although you should maybe prevent one of you "minions" to make a laughing stock of himself ;-) Twisted integration with GUI on different plateforms and its large set of packages are undeniable assets for Python, but I believe that there is still room for a more compact and purely network oriented library. Allegra will probably never outgrow its 50 modules, even if they can still be improved. The application domain it targets are "pure" network peers that do not require what Twisted can supply. As tarlano rightly pointed out: "When you need everything that twisted offers (reactor, interfaces, demonizer, configurator, adaptors, etc.) then twisted is the best choice for your requirements, but that is not always. I think that both have their merits and that both should be respected for their design decision." Regarding Deferred, why don't you have a long hard look at Allegra's finalization.py module. After all, its implementation of asynchronous continuations is piggy-backed on the CPython Garbage Collector, which is itself allready made of stable and optimized C code. I don't see wether it is possible and how this could be retrofited into Twisted code base, but I assume you will. Kind Regards, Hi Glyph,

I’m glad this does not turn into a nasty war flame with you, although you should maybe prevent one of you “minions” to make a laughing stock of himself ;-)

Twisted integration with GUI on different plateforms and its large set of packages are undeniable assets for Python, but I believe that there is still room for a more compact and purely network oriented library.

Allegra will probably never outgrow its 50 modules, even if they can still be improved. The application domain it targets are “pure” network peers that do not require what Twisted can supply. As tarlano rightly pointed out:

“When you need everything that twisted offers (reactor, interfaces, demonizer, configurator, adaptors, etc.) then twisted is the best choice for your requirements, but that is not always. I think that both have their merits and that both should be respected for their design decision.”

Regarding Deferred, why don’t you have a long hard look at Allegra’s finalization.py module. After all, its implementation of asynchronous continuations is piggy-backed on the CPython Garbage Collector, which is itself allready made of stable and optimized C code.

I don’t see wether it is possible and how this could be retrofited into Twisted code base, but I assume you will.

Kind Regards,

]]>
by: Glyph Lefkowitz http://laurentszyster.be/blog/my-twisted-apologies/#comment-197 Sat, 04 Feb 2006 02:00:38 +0000 http://laurentszyster.be/blog/my-twisted-apologies/#comment-197 Since the ravening hordes of Twisted minions seem to be doing a good job of tearing apart your misunderstanding of Twisted, I'll just say "thank you" for the apology. Although there are some mistakes, I appreciated the more technical tone of this entry. The reason I chose the title "slaying medusa" was not to insult you. I had hoped that the fact that I linked to the unicorn-vs-warewolf battle T-shirt was an indication that it was somewhat tongue-in-cheek. I called it "slaying medusa" because Twisted is supposed to be a full replacement for Medusa, both for simple and complex applications. Both Zope and Bittorrent are moving towards Twisted-derived loops. The whole point of the effort is to concentrate effort in Python towards an environment where you can write asynchronous code that can be run regardless of its "container", i.e. on Windows, on UNIX, in a PyGTK app, in a Tkinter app, in a PyQT app. If there is some documentation that would make this choice easier, please feel free to let us know. I note that you're concerned about efficiency, but opitimizing some Twisted functionality into C would be a lot easier than writing a whole new framework, and would benefit a lot more code - not to mention giving a 10x or 20x speedup instead of the 1.1x or so that you get from using tuples rather than classes. (There is already a C implementation of Deferred, it just needs more testing.) Since the ravening hordes of Twisted minions seem to be doing a good job of tearing apart your misunderstanding of Twisted, I’ll just say “thank you” for the apology. Although there are some mistakes, I appreciated the more technical tone of this entry.

The reason I chose the title “slaying medusa” was not to insult you. I had hoped that the fact that I linked to the unicorn-vs-warewolf battle T-shirt was an indication that it was somewhat tongue-in-cheek. I called it “slaying medusa” because Twisted is supposed to be a full replacement for Medusa, both for simple and complex applications. Both Zope and Bittorrent are moving towards Twisted-derived loops. The whole point of the effort is to concentrate effort in Python towards an environment where you can write asynchronous code that can be run regardless of its “container”, i.e. on Windows, on UNIX, in a PyGTK app, in a Tkinter app, in a PyQT app.

If there is some documentation that would make this choice easier, please feel free to let us know. I note that you’re concerned about efficiency, but opitimizing some Twisted functionality into C would be a lot easier than writing a whole new framework, and would benefit a lot more code - not to mention giving a 10x or 20x speedup instead of the 1.1x or so that you get from using tuples rather than classes. (There is already a C implementation of Deferred, it just needs more testing.)

]]>
by: Valentino Volonghi aka Dialtone http://laurentszyster.be/blog/my-twisted-apologies/#comment-196 Sat, 04 Feb 2006 01:20:34 +0000 http://laurentszyster.be/blog/my-twisted-apologies/#comment-196 Now... callLater is 8 lines (counting asserts and split lines for arguments). LoopingCall functionality (the _reschedule method) is 11 lines. Do you really think you can be so arrogant as to think that they are separated because twisted developers like adding extra complexity just for fun? You can't be that bad, can you? The work of the gc is (another surprise surprise) to collect instances (what a surprise, maybe that's why it's called collector) and if you prevent it to collect instances then it is not working, thus I fail to understand the quotes around to work, maybe you are not sure of what you are talking about?. If guaranteeing a certain call time is not part of Finalization applications, what is it for? Can you imagine a python where you expect something to be called when you call it, but instead it gets called 5 seconds later? Of course you may have no interest in any guarantee on the calls your application makes. (And I'm not going to talk about the semantics change in those instances of course, let alone the fact that you are requiring inheritance to implement a function call, now talk about quality). And as a closure: Don't worry about me in the twisted community. Think about yourself which is already pretty hard from what I can read. Now… callLater is 8 lines (counting asserts and split lines for arguments).
LoopingCall functionality (the _reschedule method) is 11 lines. Do you really think you can be so arrogant as to think that they are separated because twisted developers like adding extra complexity just for fun? You can’t be that bad, can you?

The work of the gc is (another surprise surprise) to collect instances (what a surprise, maybe that’s why it’s called collector) and if you prevent it to collect instances then it is not working, thus I fail to understand the quotes around to work, maybe you are not sure of what you are talking about?. If guaranteeing a certain call time is not part of Finalization applications, what is it for? Can you imagine a python where you expect something to be called when you call it, but instead it gets called 5 seconds later? Of course you may have no interest in any guarantee on the calls your application makes. (And I’m not going to talk about the semantics change in those instances of course, let alone the fact that you are requiring inheritance to implement a function call, now talk about quality).

And as a closure:
Don’t worry about me in the twisted community. Think about yourself which is already pretty hard from what I can read.

]]>
by: Laurent Szyster http://laurentszyster.be/blog/my-twisted-apologies/#comment-194 Sat, 04 Feb 2006 00:11:00 +0000 http://laurentszyster.be/blog/my-twisted-apologies/#comment-194 To Valentino: > callLater and LoopingCall are (surprise surprise) different! I do very well understand that LoopingCall and callLater are different interfaces. What you obviously do not to understand is how it is possible to achieve more with a single interface and a simpler implementation. So, spend another 10 minutes on the 21 lines of code that implement the async_schedule interface. Or even better, try it. > the presence of __del__ holds the gc from working The presence of a __del__ method bound to an instance does not prevent the GC "to work", it simply prevents it to collect that instance when caught in a circular references. Which is exactly what Finalization requires in order to produce the effect of continuations. As for the timing of garbage collection, it does not matter to the applications of Finalization. > I’m happy you don’t like twisted. I may not be found of Twisted sophistication, but it's community does not deserve the bad name your giving it with such silly comments. So, think twice before you send more flames: you are hurting what you love. To Valentino:

> callLater and LoopingCall are (surprise surprise) different!

I do very well understand that LoopingCall and callLater are different interfaces. What you obviously do not to understand is how it is possible to achieve more with a single interface and a simpler implementation. So, spend another 10 minutes on the 21 lines of code that implement the async_schedule interface. Or even better, try it.

> the presence of __del__ holds the gc from working

The presence of a __del__ method bound to an instance does not prevent the GC “to work”, it simply prevents it to collect that instance when caught in a circular references.

Which is exactly what Finalization requires in order to produce the effect of continuations. As for the timing of garbage collection, it does not matter to the applications of Finalization.

> I’m happy you don’t like twisted.

I may not be found of Twisted sophistication, but it’s community does not deserve the bad name your giving it with such silly comments. So, think twice before you send more flames: you are hurting what you love.

]]>
by: Valentino Volonghi aka Dialtone http://laurentszyster.be/blog/my-twisted-apologies/#comment-193 Fri, 03 Feb 2006 23:34:54 +0000 http://laurentszyster.be/blog/my-twisted-apologies/#comment-193 When there is abundance of documentation it's because that something is hard. When there is no documentation it's bad because users cannot understand it. I'm sure users won't ever stop complaning about anything at all but still at least try a bit :). callLater and LoopingCall are (surprise surprise) different! One keeps calling the function, the other doesn't (I'll let the reader match the correspondence). Of course one is implemented using the other. Then you should feel a bit 'pressed' to explain how you can talk about quality while using __del__ for finalization. Let's talk about cyclic references (where the presence of __del__ holds the gc from working) and the fact the there is _no_ guarantee of _when_ something is garbage collected. There are so many problems with your concept of 'quality' that I'm happy you don't like twisted. When there is abundance of documentation it’s because that something is hard. When there is no documentation it’s bad because users cannot understand it. I’m sure users won’t ever stop complaning about anything at all but still at least try a bit :).

callLater and LoopingCall are (surprise surprise) different! One keeps calling the function, the other doesn’t (I’ll let the reader match the correspondence). Of course one is implemented using the other.

Then you should feel a bit ‘pressed’ to explain how you can talk about quality while using __del__ for finalization. Let’s talk about cyclic references (where the presence of __del__ holds the gc from working) and the fact the there is _no_ guarantee of _when_ something is garbage collected. There are so many problems with your concept of ‘quality’ that I’m happy you don’t like twisted.

]]>