python 之 微堆疊 stackless python

https://www.cnblogs.com/lao454490095/p/4397261.html

stackless python從字面上理解就是沒有棧的python,怎麼做到沒有棧呢?基於堆棧的語言是怎麼實現的:

1、一般將函數的調用推進棧裏面,後入棧單元計算完之後,先入棧的才能夠完成

2、棧裏面的單元怎麼通信呢?今天剛好做完DDos攻擊的實驗,提醒我了這點:棧的單元通過入口地址和返回地址與它的前後單元通信。

3、棧的厚度有限制,貌似是1000多,就是說,迭代到1000多層就不能繼續進棧了,當然可以將層數認爲調高。大概原理就是這樣。


stackless python說,我不要棧!那麼不用棧是怎麼寫程序呢?

1、他用一種叫做tasklet的東西代替了堆棧裏面的單元

2、這些單元通過一種叫做channel的機制來通信

3、因爲不是基於堆棧,所以這些tasklet的數量你想要多少有多少,就像這裏,100000


tasklet又叫做微線程(microthread),所以說,是在python進程裏面的一個線程再分出來的“thread”。它被設計爲在各個tasklet之間的切換開銷遠遠小於系統的線程。

一個tasklet可以通過往另外一個tasklet的channel來發送信息,自己進入阻塞狀態,然後激活另一個tasklet


以斐波那契數列爲例:

往常,我們使用遞歸求斐波那契數列的時候。。。。。就不說了,大家都懂

如果換做stackless的版本呢?

堆棧沒了,我們有一個個的tasklet,這些tasklet裏面包含了一個channel,一個個的tasklet

通過將自己的channel傳給下一個tasklet,下一個channel通過將自己的處理結果發送到前一個tasklet的channel裏面實現通信。


其實如果用“微線程”的方式去理解tasklet,你可以認爲,它其實是有“堆棧”的,就像系統級別的線程一樣,但是這個堆棧僅僅是用於調用一個函數,或者說,將這個函數的調用放進一個tasklet裏面。


通過這種方式(其實我不知道自己說明白沒有。。),就形成了一條tasklet鏈,如果我們將他們想象成層疊的形狀,其實跟堆棧的形狀也是挺相似的,但是他們不叫堆棧,叫做tasklet,而且性能比堆棧的性能要好。記住這種工具的名字,它叫做stackless

python。


下面是計算斐波那契數列的代碼:

import stackless


dic = {}


def factorial(n):

if n == 1:

return 1

elif n == 2:

return 2

else:

return task(n-1) + task(n-2)



def task(n):

if str(n) in dic:

return dic[str(n)]

chann = stackless.channel()

stackless.tasklet(compute)(n,chann)

result = chann.receive()

dic[str(n)] = result

return result


def compute(n,chann):

return chann.send(factorial(n))



print factorial(100000)


然後用堆棧版本試了一下,先將python堆棧的層數上線改了100000,運行,大概1.3秒到1.5秒,其實stackless與堆棧相比沒有多大優勢。


堆棧版本代碼:

import sys

sys.setrecursionlimit(100000)


dic = {}


def factorial(n):

if n == 1:

return 1

elif n == 2:

return 2

elif str(n) in dic:

return dic[str(n)]

else:

a = factorial(n-1)

if str(n-1) not in dic:

dic[str(n-1)] = a

b = factorial(n-2)

if str(n-2) not in dic:

dic[str(n-2)] = a

return a + b



print factorial(99999)


這裏僅僅講到的是stackless的這麼一種用法,一般stackless的用途還是在替代系統線程這方面,用來做併發有c語言級別的性能

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章