<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Dirk,<div><br></div><div>I hope you are using 'twisted.trial.unittest' instead of standard Python's 'unittest'... Right? In case this is not so - update your test script to use Twisted's unittest module.<br><div apple-content-edited="true"> <span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; "><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; "><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><br class="Apple-interchange-newline"><br></div><div>Kind regards,</div><div><br></div><div>Valeriy Pogrebitskiy</div><div><a href="mailto:vpogrebi@verizon.net">vpogrebi@verizon.net</a></div><div><br></div></div></span><br class="Apple-interchange-newline"></span><br class="Apple-interchange-newline"> </div><br><div><div>On Oct 13, 2009, at 10:18 AM, Dirk Moors wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div class="gmail_quote"><div>Hello Valeriy,</div><div><br></div><div>I tried the thing you suggested, and I attached the (updated) code.</div><div>Unfortunatly, the new code was even slower, producing the following results:</div> <div><br></div><div><div>*** Starting Asynchronous Benchmarks. (Using Twisted, with "deferred-decorator")</div><div>&nbsp;&nbsp;-&gt; Asynchronous Benchmark (1 runs) Completed in 56.0279998779 seconds.</div><div>&nbsp;&nbsp;-&gt; Asynchronous Benchmark (10 runs) Completed in 56.0130000114 seconds.</div> <div>&nbsp;&nbsp;-&gt; Asynchronous Benchmark (100 runs) Completed in 56.010999918 seconds.</div><div>&nbsp;&nbsp;-&gt; Asynchronous Benchmark (1000 runs) Completed in 56.0410001278 seconds.</div><div>&nbsp;&nbsp;-&gt; Asynchronous Benchmark (10000 runs) Completed in 56.3069999218 seconds.</div> <div>&nbsp;&nbsp;-&gt; Asynchronous Benchmark (100000 runs) Completed in 58.8910000324 seconds.</div><div>*** Asynchronous Benchmarks Completed in 59.4659998417 seconds.</div><div><br></div><div>I suspect that this would me more inefficient because with the deferToThread function in place, every single operation will be executed in its own thread, which means:</div> <div>(1 x 2) + (10 x 2) + (100 x 2) + (1000 x 2) + (10000 x 2) + (100000 x 2) threads....which is...a lot.</div><div><br></div><div>Maybe the problem lies in the way I test the code? I understand that using the asynchronous testcode this way (generating the deferreds using a FOR-loop), a lot of deferreds are generated before the reactor starts calling the deferred-callbacks.....would there be another, better way to test the code?&nbsp;</div> <div>The reason I need to now which one is faster (async vs sync functions) is because I need to decide on whetehr or not I should re-evaluate the code I just recently finished building.</div><div><br></div><div>Any other ideas maybe?</div> <div><br></div><div>Thanks in advance,</div><div>Dirk&nbsp;</div><div><br></div><div><br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">________________________________________________________________________________________________________________________________________________________<br> Message: 3<br> Date: Tue, 13 Oct 2009 09:41:19 -0400<br> From: Valeriy Pogrebitskiy &lt;<a href="mailto:vpogrebi@verizon.net">vpogrebi@verizon.net</a>&gt;<br> Subject: Re: [Twisted-Python] Twisted Python vs. "Blocking" Python:<br> &nbsp; &nbsp; &nbsp; &nbsp;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: &lt;<a href="mailto:EDB2B354-B25D-4A98-AC9D-B9745CA6C3AB@verizon.net">EDB2B354-B25D-4A98-AC9D-B9745CA6C3AB@verizon.net</a>&gt;<br> Content-Type: text/plain; charset="us-ascii"<br> <br> Dirk,<br> <br> Using deferred directly in your bin2intAsync() may be somewhat less<br> efficient than some other way described in Recipe 439358: [Twisted]<br> &nbsp;From blocking functions to deferred functions<br> <br> recipe (<a href="http://code.activestate.com/recipes/439358/" target="_blank">http://code.activestate.com/recipes/439358/</a>)<br> <br> You would get same effect (asynchronous execution) - but potentially<br> more efficiently - by just decorating your synchronous methods as:<br> <br> from twisted.internet.threads import deferToThread<br> deferred = deferToThread.__get__<br> ....<br> @deferred<br> def int2binAsync(anInteger):<br> &nbsp; &nbsp; #Packs an integer, result is 4 bytes<br> &nbsp; &nbsp; return struct.pack("i", anInteger)<br> <br> @deferred<br> def bin2intAsync(aBin):<br> &nbsp; &nbsp; #Unpacks a bytestring into an integer<br> &nbsp; &nbsp; return struct.unpack("i", aBin)[0]<br> <br> <br> <br> <br> Kind regards,<br> <br> Valeriy Pogrebitskiy<br> <a href="mailto:vpogrebi@verizon.net">vpogrebi@verizon.net</a><br> <br> <br> <br> <br> On Oct 13, 2009, at 9:18 AM, Dirk Moors wrote:<br> <br> &gt; Hello Everyone!<br> &gt;<br> &gt; My name is Dirk Moors, and since 4 years now, I've been involved in<br> &gt; developing a cloud computing platform, using Python as the<br> &gt; programming language. A year ago I discovered Twisted Python, and it<br> &gt; got me very interested, upto the point where I made the decision to<br> &gt; convert our platform (in progress) to a Twisted platform. One year<br> &gt; later I'm still very enthousiastic about the overal performance and<br> &gt; stability, but last week I encountered something I did't expect;<br> &gt;<br> &gt; It appeared that it was less efficient to run small "atomic"<br> &gt; operations in different deferred-callbacks, when compared to running<br> &gt; these "atomic" operations together in "blocking" mode. Am I doing<br> &gt; something wrong here?<br> &gt;<br> &gt; To prove the problem to myself, I created the following example<br> &gt; (Full source- and test code is attached):<br> &gt; ---------------------------------------------------------------------------------------------------------------------------------------------------------------------<br> &gt; import struct<br> &gt;<br> &gt; def int2binAsync(anInteger):<br> &gt; &nbsp; &nbsp; def packStruct(i):<br> &gt; &nbsp; &nbsp; &nbsp; &nbsp; #Packs an integer, result is 4 bytes<br> &gt; &nbsp; &nbsp; &nbsp; &nbsp; return struct.pack("i", i)<br> &gt;<br> &gt; &nbsp; &nbsp; d = defer.Deferred()<br> &gt; &nbsp; &nbsp; d.addCallback(packStruct)<br> &gt;<br> &gt; &nbsp; &nbsp; reactor.callLater(0,<br> &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d.callback,<br> &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; anInteger)<br> &gt;<br> &gt; &nbsp; &nbsp; return d<br> &gt;<br> &gt; def bin2intAsync(aBin):<br> &gt; &nbsp; &nbsp; def unpackStruct(p):<br> &gt; &nbsp; &nbsp; &nbsp; &nbsp; #Unpacks a bytestring into an integer<br> &gt; &nbsp; &nbsp; &nbsp; &nbsp; return struct.unpack("i", p)[0]<br> &gt;<br> &gt; &nbsp; &nbsp; d = defer.Deferred()<br> &gt; &nbsp; &nbsp; d.addCallback(unpackStruct)<br> &gt;<br> &gt; &nbsp; &nbsp; reactor.callLater(0,<br> &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d.callback,<br> &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; aBin)<br> &gt; &nbsp; &nbsp; return d<br> &gt;<br> &gt; def int2binSync(anInteger):<br> &gt; &nbsp; &nbsp; #Packs an integer, result is 4 bytes<br> &gt; &nbsp; &nbsp; return struct.pack("i", anInteger)<br> &gt;<br> &gt; def bin2intSync(aBin):<br> &gt; &nbsp; &nbsp; #Unpacks a bytestring into an integer<br> &gt; &nbsp; &nbsp; return struct.unpack("i", aBin)[0]<br> &gt;<br> &gt; ---------------------------------------------------------------------------------------------------------------------------------------------------------------------<br> &gt;<br> &gt; While running the testcode I got the following results:<br> &gt;<br> &gt; (1 run = converting an integer to a byte string, converting that<br> &gt; byte string back to an integer, and finally checking whether that<br> &gt; last integer is the same as the input integer.)<br> &gt;<br> &gt; *** Starting Synchronous Benchmarks. (No Twisted =&gt; "blocking" code)<br> &gt; &nbsp; -&gt; Synchronous Benchmark (1 runs) Completed in 0.0 seconds.<br> &gt; &nbsp; -&gt; Synchronous Benchmark (10 runs) Completed in 0.0 seconds.<br> &gt; &nbsp; -&gt; Synchronous Benchmark (100 runs) Completed in 0.0 seconds.<br> &gt; &nbsp; -&gt; Synchronous Benchmark (1000 runs) Completed in 0.00399994850159<br> &gt; seconds.<br> &gt; &nbsp; -&gt; Synchronous Benchmark (10000 runs) Completed in 0.0369999408722<br> &gt; seconds.<br> &gt; &nbsp; -&gt; Synchronous Benchmark (100000 runs) Completed in 0.362999916077<br> &gt; seconds.<br> &gt; *** Synchronous Benchmarks Completed in 0.406000137329 seconds.<br> &gt;<br> &gt; *** Starting Asynchronous Benchmarks . (Twisted =&gt; "non-blocking"<br> &gt; code)<br> &gt; &nbsp; -&gt; Asynchronous Benchmark (1 runs) Completed in 34.5090000629<br> &gt; seconds.<br> &gt; &nbsp; -&gt; Asynchronous Benchmark (10 runs) Completed in 34.5099999905<br> &gt; seconds.<br> &gt; &nbsp; -&gt; Asynchronous Benchmark (100 runs) Completed in 34.5130000114<br> &gt; seconds.<br> &gt; &nbsp; -&gt; Asynchronous Benchmark (1000 runs) Completed in 34.5859999657<br> &gt; seconds.<br> &gt; &nbsp; -&gt; Asynchronous Benchmark (10000 runs) Completed in 35.2829999924<br> &gt; seconds.<br> &gt; &nbsp; -&gt; Asynchronous Benchmark (100000 runs) Completed in 41.492000103<br> &gt; seconds.<br> &gt; *** Asynchronous Benchmarks Completed in 42.1460001469 seconds.<br> &gt;<br> &gt; Am I really seeing factor 100x??<br> &gt;<br> &gt; I really hope that I made a huge reasoning error here but I just<br> &gt; can't find it. If my results are correct then I really need to go<br> &gt; and check my entire cloud platform for the places where I decided to<br> &gt; split functions into atomic operations while thinking that it would<br> &gt; actually improve the performance while on the contrary it did the<br> &gt; opposit.<br> &gt;<br> &gt; I personaly suspect that I lose my cpu-cycles to the reactor<br> &gt; scheduling the deferred-callbacks. Would that assumption make any<br> &gt; sense?<br> &gt; The part where I need these conversion functions is in marshalling/<br> &gt; protocol reading and writing throughout the cloud platform, which<br> &gt; implies that these functions will be called constantly so I need<br> &gt; them to be superfast. I always though I had to split the entire<br> &gt; marshalling process into small atomic (deferred-callback) functions<br> &gt; to be efficient, but these figures tell me otherwise.<br> &gt;<br> &gt; I really hope someone can help me out here.<br> &gt;<br> &gt; Thanks in advance,<br> &gt; Best regards,<br> &gt; Dirk Moors<br> &gt;<br> &gt;<br> &gt;<br> &gt;<br> &gt;<br> &gt;<br> &gt;<br> &gt;<br> &gt;<br> &gt;<br> &gt;<br> &gt;<br> &gt;<br> &gt; &lt;twistedbenchmark.py&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> <br> -------------- next part --------------<br> An HTML attachment was scrubbed...<br> URL: <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> <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 22<br> **********************************************<br> </blockquote></div><br> <span>&lt;twistedbenchmark.py&gt;</span>_______________________________________________<br>Twisted-Python mailing list<br><a href="mailto:Twisted-Python@twistedmatrix.com">Twisted-Python@twistedmatrix.com</a><br>http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python<br></blockquote></div><br></div></body></html>