Hello Reza,<div><br></div><div>I tried the solution you provided and I have to say, that changed a lot!</div><div>You gave me a better understanding of how things work with Twisted, and I really appreciate your response!</div>
<div><br></div><div>Thanks for your help!</div><div>Best regards,</div><div>Dirk Moors </div><div><br><div class="gmail_quote">2009/10/13  <span dir="ltr">&lt;<a href="mailto:twisted-python-request@twistedmatrix.com">twisted-python-request@twistedmatrix.com</a>&gt;</span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">Send Twisted-Python mailing list submissions to<br>
        <a href="mailto:twisted-python@twistedmatrix.com">twisted-python@twistedmatrix.com</a><br>
<br>
To subscribe or unsubscribe via the World Wide Web, visit<br>
        <a href="http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python" target="_blank">http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python</a><br>
or, via email, send a message with subject or body &#39;help&#39; to<br>
        <a href="mailto:twisted-python-request@twistedmatrix.com">twisted-python-request@twistedmatrix.com</a><br>
<br>
You can reach the person managing the list at<br>
        <a href="mailto:twisted-python-owner@twistedmatrix.com">twisted-python-owner@twistedmatrix.com</a><br>
<br>
When replying, please edit your Subject line so it is more specific<br>
than &quot;Re: Contents of Twisted-Python digest...&quot;<br>
<br>
<br>
Today&#39;s Topics:<br>
<br>
   1. Re: Twisted Python vs. &quot;Blocking&quot; Python: Weird   performance<br>
      on small operations. (Reza Lotun)<br>
   2. Re: Twisted-Python Digest, Vol 67, Issue 22 (Dirk Moors)<br>
<br>
<br>
----------------------------------------------------------------------<br>
<br>
Message: 1<br>
Date: Tue, 13 Oct 2009 15:04:06 +0100<br>
From: Reza Lotun &lt;<a href="mailto:rlotun@gmail.com">rlotun@gmail.com</a>&gt;<br>
Subject: Re: [Twisted-Python] Twisted Python vs. &quot;Blocking&quot; Python:<br>
        Weird   performance on small operations.<br>
To: Twisted general discussion &lt;<a href="mailto:twisted-python@twistedmatrix.com">twisted-python@twistedmatrix.com</a>&gt;<br>
Message-ID:<br>
        &lt;<a href="mailto:95bb10690910130704o7c0ff2besf00dcf5918990dcf@mail.gmail.com">95bb10690910130704o7c0ff2besf00dcf5918990dcf@mail.gmail.com</a>&gt;<br>
Content-Type: text/plain; charset=UTF-8<br>
<br>
Hi Dirk,<br>
<br>
I took a look at your code sample and got the async benchmark to run<br>
with the following values:<br>
*** Starting Asynchronous Benchmarks.<br>
<br>
  -&gt; Asynchronous Benchmark (1 runs) Completed in 0.000181913375854 seconds.<br>
  -&gt; Asynchronous Benchmark (10 runs) Completed in 0.000736951828003 seconds.<br>
  -&gt; Asynchronous Benchmark (100 runs) Completed in 0.00641012191772 seconds.<br>
  -&gt; Asynchronous Benchmark (1000 runs) Completed in 0.0741751194 seconds.<br>
  -&gt; Asynchronous Benchmark (10000 runs) Completed in 0.675071001053 seconds.<br>
  -&gt; Asynchronous Benchmark (100000 runs) Completed in 7.29738497734 seconds.<br>
<br>
*** Asynchronous Benchmarks Completed in 8.16032314301 seconds.<br>
<br>
Which, though still quite a bit slower than the synchronous version,<br>
is still much better than the 40 sec. mark that you were experiencing.<br>
My modified version simply returned defer.succeed from your aync<br>
block-compute functions.<br>
<br>
i.e. Instead of your initial example:<br>
def int2binAsync(anInteger):<br>
    def packStruct(i):<br>
        #Packs an integer, result is 4 bytes<br>
        return struct.pack(&quot;i&quot;, i)<br>
<br>
    d = defer.Deferred()<br>
    d.addCallback(packStruct)<br>
<br>
    reactor.callLater(0,<br>
                      d.callback,<br>
                      anInteger)<br>
<br>
    return d<br>
<br>
my version does:<br>
<br>
def int2binAsync(anInteger):<br>
    return defer.succeed(struct.pack(&#39;i&#39;, anInteger))<br>
<br>
A few things to note in general however:<br>
1) Twisted shines for block I/O operations - i.e. networking. A<br>
compute intesive process will not necessarily yield any gains in<br>
performance by using Twisted since the Python GIL exists (a global<br>
lock).<br>
<br>
2) If you are doing computations that use a C module (unforunately<br>
struct pre 2.6 I believe doesn&#39;t use a C module), there may be a<br>
chance that the C module releases the GIL, allowing you to do those<br>
computations in a thread. In this case you&#39;d be better off using<br>
deferToThread as suggested earlier.<br>
<br>
3) There is some (usually minimal but it exists) overhead to using<br>
Twisted. Instead of computing a bunch of stuff serially and returning<br>
your answer as in your sync example, you&#39;re wrapping everything up in<br>
deferreds and starting a reactor - it&#39;s definitely going to be a bit<br>
slower than the pure synchronous version for this case.<br>
<br>
Hope that makes sense.<br>
<br>
Cheers,<br>
Reza<br>
<br>
<br>
--<br>
Reza Lotun<br>
mobile: +44 (0)7521 310 763<br>
email:  <a href="mailto:rlotun@gmail.com">rlotun@gmail.com</a><br>
work:   <a href="mailto:reza@tweetdeck.com">reza@tweetdeck.com</a><br>
twitter: @rlotun<br>
<br>
<br>
<br>
------------------------------<br>
<br>
Message: 2<br>
Date: Tue, 13 Oct 2009 16:18:35 +0200<br>
From: Dirk Moors &lt;<a href="mailto:dirkmoors@gmail.com">dirkmoors@gmail.com</a>&gt;<br>
Subject: Re: [Twisted-Python] Twisted-Python Digest, Vol 67, Issue 22<br>
To: <a href="mailto:twisted-python@twistedmatrix.com">twisted-python@twistedmatrix.com</a><br>
Message-ID:<br>
        &lt;<a href="mailto:cf75a1410910130718m53645515oc65f0890366a12f2@mail.gmail.com">cf75a1410910130718m53645515oc65f0890366a12f2@mail.gmail.com</a>&gt;<br>
Content-Type: text/plain; charset=&quot;iso-8859-1&quot;<br>
<br>
Hello Valeriy,<br>
<br>
I tried the thing you suggested, and I attached the (updated) code.<br>
Unfortunatly, the new code was even slower, producing the following results:<br>
<br>
*** Starting Asynchronous Benchmarks. (Using Twisted, with<br>
&quot;deferred-decorator&quot;)<br>
  -&gt; Asynchronous Benchmark (1 runs) Completed in 56.0279998779 seconds.<br>
  -&gt; Asynchronous Benchmark (10 runs) Completed in 56.0130000114 seconds.<br>
  -&gt; Asynchronous Benchmark (100 runs) Completed in 56.010999918 seconds.<br>
  -&gt; Asynchronous Benchmark (1000 runs) Completed in 56.0410001278 seconds.<br>
  -&gt; Asynchronous Benchmark (10000 runs) Completed in 56.3069999218 seconds.<br>
  -&gt; Asynchronous Benchmark (100000 runs) Completed in 58.8910000324<br>
seconds.<br>
*** Asynchronous Benchmarks Completed in 59.4659998417 seconds.<br>
<br>
I suspect that this would me more inefficient because with the deferToThread<br>
function in place, every single operation will be executed in its own<br>
thread, which means:<br>
(1 x 2) + (10 x 2) + (100 x 2) + (1000 x 2) + (10000 x 2) + (100000 x 2)<br>
threads....which is...a lot.<br>
<br>
Maybe the problem lies in the way I test the code? I understand that using<br>
the asynchronous testcode this way (generating the deferreds using a<br>
FOR-loop), a lot of deferreds are generated before the reactor starts<br>
calling the deferred-callbacks.....would there be another, better way to<br>
test the code?<br>
The reason I need to now which one is faster (async vs sync functions) is<br>
because I need to decide on whetehr or not I should re-evaluate the code I<br>
just recently finished building.<br>
<br>
Any other ideas maybe?<br>
<br>
Thanks in advance,<br>
Dirk<br>
<br>
<br>
________________________________________________________________________________________________________________________________________________________<br>
&gt; Message: 3<br>
&gt; Date: Tue, 13 Oct 2009 09:41:19 -0400<br>
&gt; From: Valeriy Pogrebitskiy &lt;<a href="mailto:vpogrebi@verizon.net">vpogrebi@verizon.net</a>&gt;<br>
&gt; Subject: Re: [Twisted-Python] Twisted Python vs. &quot;Blocking&quot; Python:<br>
&gt;        Weird performance on small operations.<br>
&gt; To: Twisted general discussion &lt;<a href="mailto:twisted-python@twistedmatrix.com">twisted-python@twistedmatrix.com</a>&gt;<br>
&gt; Message-ID: &lt;<a href="mailto:EDB2B354-B25D-4A98-AC9D-B9745CA6C3AB@verizon.net">EDB2B354-B25D-4A98-AC9D-B9745CA6C3AB@verizon.net</a>&gt;<br>
&gt; Content-Type: text/plain; charset=&quot;us-ascii&quot;<br>
&gt;<br>
&gt; Dirk,<br>
&gt;<br>
&gt; Using deferred directly in your bin2intAsync() may be somewhat less<br>
&gt; efficient than some other way described in Recipe 439358: [Twisted]<br>
&gt;  From blocking functions to deferred functions<br>
&gt;<br>
&gt; recipe (<a href="http://code.activestate.com/recipes/439358/" target="_blank">http://code.activestate.com/recipes/439358/</a>)<br>
&gt;<br>
&gt; You would get same effect (asynchronous execution) - but potentially<br>
&gt; more efficiently - by just decorating your synchronous methods as:<br>
&gt;<br>
&gt; from twisted.internet.threads import deferToThread<br>
&gt; deferred = deferToThread.__get__<br>
&gt; ....<br>
&gt; @deferred<br>
&gt; def int2binAsync(anInteger):<br>
&gt;     #Packs an integer, result is 4 bytes<br>
&gt;     return struct.pack(&quot;i&quot;, anInteger)<br>
&gt;<br>
&gt; @deferred<br>
&gt; def bin2intAsync(aBin):<br>
&gt;     #Unpacks a bytestring into an integer<br>
&gt;     return struct.unpack(&quot;i&quot;, aBin)[0]<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; Kind regards,<br>
&gt;<br>
&gt; Valeriy Pogrebitskiy<br>
&gt; <a href="mailto:vpogrebi@verizon.net">vpogrebi@verizon.net</a><br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; On Oct 13, 2009, at 9:18 AM, Dirk Moors wrote:<br>
&gt;<br>
&gt; &gt; Hello Everyone!<br>
&gt; &gt;<br>
&gt; &gt; My name is Dirk Moors, and since 4 years now, I&#39;ve been involved in<br>
&gt; &gt; developing a cloud computing platform, using Python as the<br>
&gt; &gt; programming language. A year ago I discovered Twisted Python, and it<br>
&gt; &gt; got me very interested, upto the point where I made the decision to<br>
&gt; &gt; convert our platform (in progress) to a Twisted platform. One year<br>
&gt; &gt; later I&#39;m still very enthousiastic about the overal performance and<br>
&gt; &gt; stability, but last week I encountered something I did&#39;t expect;<br>
&gt; &gt;<br>
&gt; &gt; It appeared that it was less efficient to run small &quot;atomic&quot;<br>
&gt; &gt; operations in different deferred-callbacks, when compared to running<br>
&gt; &gt; these &quot;atomic&quot; operations together in &quot;blocking&quot; mode. Am I doing<br>
&gt; &gt; something wrong here?<br>
&gt; &gt;<br>
&gt; &gt; To prove the problem to myself, I created the following example<br>
&gt; &gt; (Full source- and test code is attached):<br>
&gt; &gt;<br>
&gt; ---------------------------------------------------------------------------------------------------------------------------------------------------------------------<br>
&gt; &gt; import struct<br>
&gt; &gt;<br>
&gt; &gt; def int2binAsync(anInteger):<br>
&gt; &gt;     def packStruct(i):<br>
&gt; &gt;         #Packs an integer, result is 4 bytes<br>
&gt; &gt;         return struct.pack(&quot;i&quot;, i)<br>
&gt; &gt;<br>
&gt; &gt;     d = defer.Deferred()<br>
&gt; &gt;     d.addCallback(packStruct)<br>
&gt; &gt;<br>
&gt; &gt;     reactor.callLater(0,<br>
&gt; &gt;                       d.callback,<br>
&gt; &gt;                       anInteger)<br>
&gt; &gt;<br>
&gt; &gt;     return d<br>
&gt; &gt;<br>
&gt; &gt; def bin2intAsync(aBin):<br>
&gt; &gt;     def unpackStruct(p):<br>
&gt; &gt;         #Unpacks a bytestring into an integer<br>
&gt; &gt;         return struct.unpack(&quot;i&quot;, p)[0]<br>
&gt; &gt;<br>
&gt; &gt;     d = defer.Deferred()<br>
&gt; &gt;     d.addCallback(unpackStruct)<br>
&gt; &gt;<br>
&gt; &gt;     reactor.callLater(0,<br>
&gt; &gt;                       d.callback,<br>
&gt; &gt;                       aBin)<br>
&gt; &gt;     return d<br>
&gt; &gt;<br>
&gt; &gt; def int2binSync(anInteger):<br>
&gt; &gt;     #Packs an integer, result is 4 bytes<br>
&gt; &gt;     return struct.pack(&quot;i&quot;, anInteger)<br>
&gt; &gt;<br>
&gt; &gt; def bin2intSync(aBin):<br>
&gt; &gt;     #Unpacks a bytestring into an integer<br>
&gt; &gt;     return struct.unpack(&quot;i&quot;, aBin)[0]<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; ---------------------------------------------------------------------------------------------------------------------------------------------------------------------<br>
&gt; &gt;<br>
&gt; &gt; While running the testcode I got the following results:<br>
&gt; &gt;<br>
&gt; &gt; (1 run = converting an integer to a byte string, converting that<br>
&gt; &gt; byte string back to an integer, and finally checking whether that<br>
&gt; &gt; last integer is the same as the input integer.)<br>
&gt; &gt;<br>
&gt; &gt; *** Starting Synchronous Benchmarks. (No Twisted =&gt; &quot;blocking&quot; code)<br>
&gt; &gt;   -&gt; Synchronous Benchmark (1 runs) Completed in 0.0 seconds.<br>
&gt; &gt;   -&gt; Synchronous Benchmark (10 runs) Completed in 0.0 seconds.<br>
&gt; &gt;   -&gt; Synchronous Benchmark (100 runs) Completed in 0.0 seconds.<br>
&gt; &gt;   -&gt; Synchronous Benchmark (1000 runs) Completed in 0.00399994850159<br>
&gt; &gt; seconds.<br>
&gt; &gt;   -&gt; Synchronous Benchmark (10000 runs) Completed in 0.0369999408722<br>
&gt; &gt; seconds.<br>
&gt; &gt;   -&gt; Synchronous Benchmark (100000 runs) Completed in 0.362999916077<br>
&gt; &gt; seconds.<br>
&gt; &gt; *** Synchronous Benchmarks Completed in 0.406000137329 seconds.<br>
&gt; &gt;<br>
&gt; &gt; *** Starting Asynchronous Benchmarks . (Twisted =&gt; &quot;non-blocking&quot;<br>
&gt; &gt; code)<br>
&gt; &gt;   -&gt; Asynchronous Benchmark (1 runs) Completed in 34.5090000629<br>
&gt; &gt; seconds.<br>
&gt; &gt;   -&gt; Asynchronous Benchmark (10 runs) Completed in 34.5099999905<br>
&gt; &gt; seconds.<br>
&gt; &gt;   -&gt; Asynchronous Benchmark (100 runs) Completed in 34.5130000114<br>
&gt; &gt; seconds.<br>
&gt; &gt;   -&gt; Asynchronous Benchmark (1000 runs) Completed in 34.5859999657<br>
&gt; &gt; seconds.<br>
&gt; &gt;   -&gt; Asynchronous Benchmark (10000 runs) Completed in 35.2829999924<br>
&gt; &gt; seconds.<br>
&gt; &gt;   -&gt; Asynchronous Benchmark (100000 runs) Completed in 41.492000103<br>
&gt; &gt; seconds.<br>
&gt; &gt; *** Asynchronous Benchmarks Completed in 42.1460001469 seconds.<br>
&gt; &gt;<br>
&gt; &gt; Am I really seeing factor 100x??<br>
&gt; &gt;<br>
&gt; &gt; I really hope that I made a huge reasoning error here but I just<br>
&gt; &gt; can&#39;t find it. If my results are correct then I really need to go<br>
&gt; &gt; and check my entire cloud platform for the places where I decided to<br>
&gt; &gt; split functions into atomic operations while thinking that it would<br>
&gt; &gt; actually improve the performance while on the contrary it did the<br>
&gt; &gt; opposit.<br>
&gt; &gt;<br>
&gt; &gt; I personaly suspect that I lose my cpu-cycles to the reactor<br>
&gt; &gt; scheduling the deferred-callbacks. Would that assumption make any<br>
&gt; &gt; sense?<br>
&gt; &gt; The part where I need these conversion functions is in marshalling/<br>
&gt; &gt; protocol reading and writing throughout the cloud platform, which<br>
&gt; &gt; implies that these functions will be called constantly so I need<br>
&gt; &gt; them to be superfast. I always though I had to split the entire<br>
&gt; &gt; marshalling process into small atomic (deferred-callback) functions<br>
&gt; &gt; to be efficient, but these figures tell me otherwise.<br>
&gt; &gt;<br>
&gt; &gt; I really hope someone can help me out here.<br>
&gt; &gt;<br>
&gt; &gt; Thanks in advance,<br>
&gt; &gt; Best regards,<br>
&gt; &gt; Dirk Moors<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; &lt;twistedbenchmark.py&gt;_______________________________________________<br>
&gt; &gt; Twisted-Python mailing list<br>
&gt; &gt; <a href="mailto:Twisted-Python@twistedmatrix.com">Twisted-Python@twistedmatrix.com</a><br>
&gt; &gt; <a href="http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python" target="_blank">http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python</a><br>
&gt;<br>
&gt; -------------- next part --------------<br>
&gt; An HTML attachment was scrubbed...<br>
&gt; URL:<br>
&gt; <a href="http://twistedmatrix.com/pipermail/twisted-python/attachments/20091013/e9ae2546/attachment.htm" target="_blank">http://twistedmatrix.com/pipermail/twisted-python/attachments/20091013/e9ae2546/attachment.htm</a><br>

&gt;<br>
&gt; ------------------------------<br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; Twisted-Python mailing list<br>
&gt; <a href="mailto:Twisted-Python@twistedmatrix.com">Twisted-Python@twistedmatrix.com</a><br>
&gt; <a href="http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python" target="_blank">http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python</a><br>
&gt;<br>
&gt;<br>
&gt; End of Twisted-Python Digest, Vol 67, Issue 22<br>
&gt; **********************************************<br>
&gt;<br>
-------------- next part --------------<br>
An HTML attachment was scrubbed...<br>
URL: <a href="http://twistedmatrix.com/pipermail/twisted-python/attachments/20091013/357ffe0c/attachment.htm" target="_blank">http://twistedmatrix.com/pipermail/twisted-python/attachments/20091013/357ffe0c/attachment.htm</a><br>

-------------- next part --------------<br>
A non-text attachment was scrubbed...<br>
Name: twistedbenchmark.py<br>
Type: application/octet-stream<br>
Size: 7269 bytes<br>
Desc: not available<br>
Url : <a href="http://twistedmatrix.com/pipermail/twisted-python/attachments/20091013/357ffe0c/attachment.obj" target="_blank">http://twistedmatrix.com/pipermail/twisted-python/attachments/20091013/357ffe0c/attachment.obj</a><br>

<br>
------------------------------<br>
<br>
_______________________________________________<br>
Twisted-Python mailing list<br>
<a href="mailto:Twisted-Python@twistedmatrix.com">Twisted-Python@twistedmatrix.com</a><br>
<a href="http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python" target="_blank">http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python</a><br>
<br>
<br>
End of Twisted-Python Digest, Vol 67, Issue 23<br>
**********************************************<br>
</blockquote></div><br></div>