天天看點

從兩個簡單例子窺視協程的驚人性能(Python)

    我們用普通同步方式掃描10個端口,用協程(異步)方式掃描1000個端口,對比時間。

1、同步方式代碼

<code>#encoding=utf-8</code>

<code>#author: walker</code>

<code>#date: 2014-07-16</code>

<code>#function: 使用同步方式掃描10個端口</code>

<code>import</code> <code>time, socket, sys</code>

<code>def</code> <code>task(addr):</code>

<code>    </code><code>sock </code><code>=</code> <code>socket.socket(socket.AF_INET, socket.SOCK_STREAM)</code>

<code>    </code><code>sock.settimeout(</code><code>100</code><code>)</code>

<code>    </code><code>try</code><code>:</code>

<code>        </code><code>sock.connect(addr)</code>

<code>        </code><code>print</code><code>(</code><code>'Port '</code> <code>+</code> <code>str</code><code>(</code><code>str</code><code>(addr[</code><code>1</code><code>])) </code><code>+</code> <code>' is  open'</code><code>)</code>

<code>    </code><code>except</code><code>:</code>

<code>        </code><code>pass</code>

<code>    </code><code>finally</code><code>:</code>

<code>        </code><code>sock.close()</code>

<code>#掃描10個端口</code>

<code>def</code> <code>synchronous():</code>

<code>    </code><code>for</code> <code>i </code><code>in</code> <code>range</code><code>(</code><code>0</code><code>, </code><code>10</code><code>):</code>

<code>        </code><code>task((</code><code>'127.0.0.1'</code><code>, i))</code>

<code>        </code> 

<code>t0 </code><code>=</code> <code>time.time()</code>

<code>synchronous()</code>

<code>t1 </code><code>=</code> <code>time.time()</code>

<code>print</code><code>(</code><code>'time: {}s'</code><code>.</code><code>format</code><code>(t1 </code><code>-</code> <code>t0))</code>

2、協程(異步)方式代碼

<code>#function: 使用協程(異步)方式掃描1000個端口</code>

<code>import</code> <code>gevent.monkey</code>

<code>gevent.monkey.patch_socket()</code>

<code>import</code> <code>gevent, socket, sys, time</code>

<code>#掃描1000個端口</code>

<code>def</code> <code>asynchronous():</code>

<code>    </code><code>threads </code><code>=</code> <code>[]</code>

<code>    </code><code>for</code> <code>i </code><code>in</code> <code>range</code><code>(</code><code>0</code><code>, </code><code>1000</code><code>):</code>

<code>        </code><code>threads.append(gevent.spawn(task, (</code><code>'127.0.0.1'</code><code>, i)))</code>

<code>    </code><code>gevent.joinall(threads)</code>

<code>asynchronous()</code>

用同步方式掃描10個端口需要9s,而用協程掃描1000個端口僅需2s!從代碼複雜性來看,asynchronous函數僅比synchronous函數多一行。也就是說協程以同步方式的代碼複雜度實作了異步程式的性能!

Windows下使用gevent,建議安裝二進制版本,先裝greenlet,再裝gevent:

<a href="http://www.lfd.uci.edu/~gohlke/pythonlibs/#greenlet" target="_blank">http://www.lfd.uci.edu/~gohlke/pythonlibs/#greenlet</a>

<a href="http://www.lfd.uci.edu/~gohlke/pythonlibs/#gevent" target="_blank">http://www.lfd.uci.edu/~gohlke/pythonlibs/#gevent</a>

相關閱讀:

本文轉自walker snapshot部落格51CTO部落格,原文連結http://blog.51cto.com/walkerqt/1439034如需轉載請自行聯系原作者

RQSLT