版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、轉(zhuǎn)自:1 .刖日偶然看至UErlangvs.Stacklesspython:afirstbenchmark,對Erlang和StacklessPython的并發(fā)處理性能進(jìn)展了實驗比較,根本結(jié)論認(rèn)為二者有比較相近的性能。我看完產(chǎn)生的問題是,StacklessPython與Python的其他并發(fā)實現(xiàn)機(jī)制性能又會有多大區(qū)別呢,比方線程和進(jìn)程。因此我采用與這篇文章一樣的方法來對StacklessPython、普通Python的thread模塊、普通Python的threading模塊、普通Python的processing模塊這四種并發(fā)實現(xiàn)方案進(jìn)展了性能實驗,并將實驗過程和根本結(jié)果記錄在這里。后來看到
2、了基于greenlet實現(xiàn)的高性能網(wǎng)絡(luò)框架Eventlet,因此更新了實驗方案,將greenlet也參加了比較,雖然greenlet并非是一種真正意義上的并發(fā)處理,而是在單個線程下對程序塊進(jìn)展切換輪流執(zhí)行。(EditSectionJ)2 .實驗方案實驗方案與Erlangvs.Stacklesspython:afirstbenchmark是一樣的,用每種|方案分別給出如下問題的實現(xiàn),記錄完成整個處理過程的總時間來作為評判性能的根據(jù):1 .由n個節(jié)點組成一個環(huán)狀網(wǎng)絡(luò),在上面?zhèn)魉凸瞞個消息。2 .將每個消息共m個,逐個發(fā)送給1號節(jié)點。3 .第1到n-1號節(jié)點在接收到消息后,都轉(zhuǎn)發(fā)給下一號節(jié)點。4 .
3、第n號節(jié)點每次收到消息后,不再繼續(xù)轉(zhuǎn)發(fā)。5 .當(dāng)m個消息都從1號逐個到達(dá)第n號節(jié)點時,認(rèn)為全部處理完畢。(EditSectionJ)硬件平臺MacbookPro3,1上的Vmware虛擬機(jī)中,注意這里給虛擬機(jī)只啟用了cpu的單個核心:?原始Cpu:Core2Duo,2.4GHz,2核心,4MBL2緩存,總線速度800MHz?分配給虛擬機(jī)的內(nèi)存:796M單個CPU,還能比較并發(fā)嗎?(EditSectionJ)軟件平臺Vmware下的Debianetch:?原始Python:Debian發(fā)行版自帶?Stackless3.1b3060516?processing-0.52-py2.4-linux-i
4、686.egg?原始Python下的greenlet實現(xiàn):(EditSectionJ)3 .實驗過程及結(jié)果各方案的實現(xiàn)代碼見后文。實驗時使用time指令記錄每次運行的總時間,選用的都是不做任何輸出的no_io實現(xiàn)Python的print指令還是挺耗資源的,假設(shè)不注釋掉十有八九得影響測試結(jié)果,每次執(zhí)行時設(shè)定n=300,m=10000Erlangvs.Stacklesspython:afirstbenchmark文章中認(rèn)為n可以設(shè)置為300,m那么可以取10000到90000之間的數(shù)值分別進(jìn)展測試。(EditSectionJ)StacklessPython的實驗結(jié)果realusersys即使將m擴(kuò)
5、大到30000,實驗結(jié)果仍然很突出:realusersys(EditSectionJ)使用thread模塊的實驗結(jié)果realusersys(EditSectionJ)使用threading模塊配合Queue模塊的實驗結(jié)果不太穩(wěn)定,有時候這樣:realusersys也有時這樣:realusersys(EditSectionJ)使用processing模塊配合Queue模塊的實驗結(jié)果realusersys(EditSectionJ)greenlet模塊的實驗結(jié)果realusersys(EditSectionJ)eventlet模塊的實驗結(jié)果注意!eventlet的這個實驗結(jié)果是后來增補的,硬件平臺
6、沒變,但是是直接在OSX自帶Python2.5環(huán)境下執(zhí)行出來的,同時系統(tǒng)中還有Firefox等很多程序也在爭奪系統(tǒng)資源。因此只能作為大致參考,不能與其他幾組數(shù)據(jù)作直接比照。其中eventlet的版本是(EditSectionJ)4 .結(jié)論與分析(EditSectionJ)StacklessPython毫無疑問,StacklessPython幾乎有匪夷所思的并發(fā)性能,比其他方案快上幾十倍,而且借助StacklessPython提供的channel機(jī)制,實現(xiàn)也相當(dāng)簡單。也許這個結(jié)果向我們部分提醒了沈仙人基于StacklessPython實現(xiàn)的Eurasia3可以提供相當(dāng)于c語言效果的恐懼并發(fā)性能的
7、原因。(EditSectionJ)Python線程從道理上來講,thread模塊似乎應(yīng)該和threading提供根本一樣的性能,畢竟threading只是對thread的一種封裝嘛,后臺機(jī)制應(yīng)該是一致的?;蛟Sthreading由于本身類實例維護(hù)方面的開銷,應(yīng)該會比直接用thread慢一點。從實驗結(jié)果來看,二者性能也確實差不多。只是不大明白為何threading方案的測試結(jié)果不是很穩(wěn)定,即使對其他方案的測試運行屢次,誤差也不會像threading這么飄。從代碼實現(xiàn)體驗來說,用threading配合Queue比直接用thread實在是輕松太多了,并且出錯的時機(jī)也要少很多。(EditSectionJ
8、)Python進(jìn)程processing模塊給出的進(jìn)程方案大致比thread線程要慢一倍,并且這是在我特意調(diào)整虛擬機(jī)給它預(yù)備了足夠空閑內(nèi)存、防止使用交換分區(qū)的情況下獲得的特意分給虛擬機(jī)700多M內(nèi)存就是為了這個。而其他方案僅僅占用數(shù)M內(nèi)存,完全無需特意調(diào)大可用內(nèi)存總量。當(dāng)然,假設(shè)給虛擬機(jī)多啟用幾個核心的話,processing也許會占上點廉價,畢竟目前thread模塊是不能有效利用多cpu資源的經(jīng)實驗,StacklessPython在開啟雙核的情況下表現(xiàn)的性能和單核是一樣的,說明也是不能有效利用多cpu。因此一種比較合理的做法是根據(jù)cpu的數(shù)量,啟用少量幾個進(jìn)程,而在進(jìn)程內(nèi)部再開啟線程進(jìn)展實際業(yè)
9、務(wù)處理,這也是目前Python社區(qū)推薦的有效利用多cpu資源的方法。好在processing配合其自身提供的Queue模塊,編程體驗還是比較輕松的。(EditSectionJ)greenlet超輕M級方案基于greenlet的實現(xiàn)那么性能僅次于StacklessPython,大致比StacklessPython慢一倍,比其他方案快接近一個數(shù)量級。其實greenlet不是一種真正的并發(fā)機(jī)制,而是在同一線程內(nèi),在不同函數(shù)的執(zhí)行代碼塊之間切換,施行你運行一會、我運行一會,并且在進(jìn)展切換時必須指定何時切換以及切換到哪。greenlet的接口是比較簡單易用的,但是使用greenlet時的考慮方式與其他并
10、發(fā)方案存在一定區(qū)別。線程/進(jìn)程模型在大邏輯上通常從并發(fā)角度開始考慮,把可以并行處理的并且值得并行處理的任務(wù)別離出來,在不同的線程/進(jìn)程下運行,然后考慮別離過程可能造成哪些互斥、沖突問題,將互斥的資源加鎖保護(hù)來保證并發(fā)處理的正確性。greenlet那么是要求從防止阻塞的角度來進(jìn)展開發(fā),當(dāng)出現(xiàn)阻塞時,就顯式切換到另一段沒有被阻塞的代碼段執(zhí)行,直到原先的阻塞狀況消失以后,再人工切換回原來的代碼段繼續(xù)處理。因此,greenlet本質(zhì)是一種合理安排了的用行,實驗中g(shù)reenlet方案可以得到比較好的性能表現(xiàn),主要也是因為通過合理的代碼執(zhí)行流程切換,完全防止了死鎖和阻塞等情況執(zhí)行帶屏幕輸出的我們會看到腳本
11、總是一個一個地處理消息,把一個消息在環(huán)上從頭傳到尾之后,再開始處理下一個消息。因為greenlet本質(zhì)是串行,因此在沒有進(jìn)展顯式切換時,代碼的其他部分是無法被執(zhí)行到的,假設(shè)要防止代碼長時間占用運算資源造成程序假死,那么還是要將greenlet與線程/進(jìn)程機(jī)制結(jié)合使用每個線程、進(jìn)程下都可以建立多個greenlet,但是跨線程/進(jìn)程時greenlet之間無法切換或通訊。Stackless那么比較特別,對很多資源從底層進(jìn)展了并發(fā)改造,并且提供了channel等更適宜并發(fā)的通訊機(jī)制實現(xiàn),使得資源互斥沖突的可能性大大減小,并發(fā)性能自然得以進(jìn)步。粗糙來講,greenlet是阻塞了我就先干點兒別的,但是程序
12、員得明確告訴greenlet能先干點兒啥以及什么時候回來;Stackless那么是東西我已經(jīng)改造好了,你只要用我的東西,并發(fā)沖突就不用操心,只管放心大膽地并發(fā)好了。greenlet應(yīng)該是學(xué)習(xí)了Stackless的上下文切換機(jī)制,但是對底層資源沒有進(jìn)展適宜并發(fā)的改造。并且實際上greenlet也沒有必要改造底層資源的并發(fā)性,因為它本質(zhì)是串行的單線程,不與其他并發(fā)模型混合使用的話是無法造成對資源的并發(fā)訪問的。(EditSectionJ)greenlet封裝后的eventlet方案eventlet是基于greenlet實現(xiàn)的面向網(wǎng)絡(luò)應(yīng)用的并發(fā)處理框架,提供線程池、隊列等與其他Python線程、進(jìn)程模
13、型非常相似的api,并且提供了對Python發(fā)行版自帶庫及其他模塊的超輕量并發(fā)適應(yīng)性調(diào)整方法,比直接使用greenlet要方便得多。并且這個解決方案源自著名虛擬現(xiàn)實游戲第二人生,可以說是久經(jīng)考驗的新興并發(fā)處理模型。其根本原理是調(diào)整Python的socket調(diào)用,當(dāng)發(fā)生阻塞時那么切換到其他greenlet執(zhí)行,這樣來保證資源的有效利用。需要注意的是:?eventlet提供的函數(shù)只能對Python代碼中的socket調(diào)用進(jìn)展處理,而不能對模塊的C語言部分的socket調(diào)用進(jìn)展修改。對后者這類模塊,仍然需要把調(diào)用模塊的代碼封裝在Python標(biāo)準(zhǔn)線程調(diào)用中,之后利用eventlet提供的適配器實現(xiàn)ev
14、entlet與標(biāo)準(zhǔn)線程之間的協(xié)作。?再有,雖然eventlet把api封裝成了非常類似標(biāo)準(zhǔn)線程庫的形式,但兩者的實際并發(fā)執(zhí)行流程仍然有明顯區(qū)別。在沒有出現(xiàn)I/O阻塞時,除非顯式聲明,否那么當(dāng)前正在執(zhí)行的eventlet永遠(yuǎn)不會把cpu交給其他的eventlet,而標(biāo)準(zhǔn)線程那么是無論是否出現(xiàn)阻塞,總是由所有線程一起爭奪運行資源。所有eventlet對I/O阻塞無關(guān)的大運算量耗時操作根本沒有什么幫助。在性能測試結(jié)果方面,eventlet消耗的運行時間大致是greenlet方案的3到5倍,而Python標(biāo)準(zhǔn)線程模型的thread方式消耗的運行時間大致是eventlet測試代碼的8到10倍。其中前者可
15、能是因為我們在eventlet的測試代碼中,使用隊列機(jī)制來完成所有的消息傳遞,而隊列上的訪問互斥保護(hù)可能額外消耗了一些運算資源??傮w而言,eventlet模型的并發(fā)性能雖然比StacklessPython和直接使用greenlet有一定差距,但仍然比標(biāo)準(zhǔn)線程模型有大約一個數(shù)量級的優(yōu)勢,這也就不奇怪近期很多強調(diào)并發(fā)性能的網(wǎng)絡(luò)效勞器實現(xiàn)采取eventlet、線程、進(jìn)程三者組合使用的實現(xiàn)方案。(EditSectionJ)5 .實驗代碼實驗代碼下載:?版本3下載:增加了eventlet方案的實驗代碼。?版本2下載:增加了greenlet方案的實驗代碼。?版本1下載:包括StacklessPython、
16、thread、threading、processing四種方案的實驗代碼。為方便閱讀,將實驗中用到的幾個腳本的代碼粘貼如下,其中StacklessPython方案的代碼實現(xiàn)直接取自Erlangvs.Stacklesspython:afirstbenchmark:(EditSectionJ)1. #!/Library/Frameworks/2. #encoding:utf-83. importsys4. importstacklessasSL5.6. defrun_benchmark(n,m):7. stackless3.1b3here(N=%d,M=%d)!n"%(n,m)8. fi
17、rstP=cin=()9. forsinxrange(1,n):10. seqn=s11. cout=()12. #print("*>s=%d"%(seqn,)13. t=(loop)(seqn,cin,cout)14. cin=cout15. else:16. seqn=s+117. #print("$>s=%d"%(seqn,)18. t=(mloop)(seqn,cin)19. forrinxrange(m-1,-1,-1):20. #print("+sendingMsg#%d"%r)21. (r)22. ()23.
18、 defloop(s,cin,cout):24. whileTrue:25. r=()26. (r)27. ifr>0:28. #print(":Proc:<%s>,Seq#:%s,Msg#:%s."(pid(),s,r)29. pass30. else:31. #print("*Proc:<%s>,Seq#:%s,Msg#:terminate!"%(pid(),s)32. break33. defmloop(s,cin):34. whileTrue:35. r=()36. ifr>0:37. #print("
19、;>Proc:<%s>,Seq#:%s,Msg#:%s."(pid(),s,r)38. pass39. else:40. #print("Proc:<%s>,Seq#:%s,ringterminated."%(pid(),s)41. break42.43. defpid():returnrepr().split()-12:-144.45. if_name_='_main_'46. run_benchmark(int(sys.argv1),int(sys.argv2)GetCode(EditSectionJ)1. #!/
20、Library/Frameworks/2. #encoding:utf-83. importsys,time4. importthread5.6. SLEEP_TIME=7.8. defrun_benchmark(n,m):9. stackless3.1b3here(N=%d,M=%d)!n"%(n,m)10. locks=thread.allocate_lock()foriinxrange(n)11. firstP=cin=12. cin_lock_id=013. forsinxrange(1,n):14. seqn=s15. cout=16. cout_lock_id=s17.
21、#print("*>s=%d"%(seqn,)18. thread.start_new_thread(loop,(seqn,locks,cin,cin_lock_id,cout,cout_lock_id)19. cin=cout20. cin_lock_id=cout_lock_id21. else:22. seqn=s+123. #print("$>s=%d"%(seqn,)24. thread.start_new_thread(mloop,(seqn,locks,cin,cin_lock_id)25. forrinxrange(m-1,-
22、1,-1):5.66.#print("+sendingMsg#%d"%r)lock=locks0()(r)()time.sleep(SLEEP_TIME)try:whileTrue:time.sleep(SLEEP_TIME)except:passdefloop(s,locks,cin,cin_lock_id,cout,cout_lock_i
23、d):whileTrue:lock=lockscin_lock_id()一一iflen(cin)>0:r=cin.pop(0)()else:()time.sleep(SLEEP_TIME)continuelock=lockscout_lock_id()一一(r)()ifr>0:# print(":Proc:<%s>,Seq#:%s,Msg#:%s."%(pid(),s,r)passelse:# print("*Proc:<%s>,Seq#:%s,Msg#:terminate!"%(pid(),s)breakdefmlo
24、op(s,locks,cin,cin_lock_id):whileTrue:lock=lockscin_lock_id()一一iflen(cin)>0:r=cin.pop(0)()else:()67. time.sleep(SLEEP_TIME)68. continue69. ifr>0:70. #print(">Proc:<%s>,Seq#:%s,Msg#:%s."%(pid(),s,r)71. pass72. else:73. #print("Proc:<%s>,Seq#:%s,ringterminated."
25、;%(pid(),s)74. break75. errupt_main()76.77. defpid():returnthread.get_ident()78.79. if_name_='_main_'80. run_benchmark(int(sys.argv1),int(sys.argv2)GetCode(EditSectionJ)1. #!/Library/Frameworks/2. #encoding:utf-83. importsys4. importthreading,Queue5.6. defrun_benchmark(n,m):7. stac
26、kless3.1b3here(N=%d,M=%d)!n"%(n,m)8. firstP=cin=Queue.Queue()9. forsinxrange(1,n):10. seqn=s11. cout=Queue.Queue()12. #print("*>s=%d"%(seqn,)13. t=Loop(seqn,cin,cout)14. (False)15. ()16. cin=cout17. else:18. seqn=s+119. #print("$>s=%d"%(seqn,)20. t=MLoop(seqn,cin)21. (
27、False)7.()forrinxrange(m-1,-1,-1):#print("+sendingMsg#%d"%r)(r)classLoop(threading.Thread):def_init_(self,s,cin,cout):threading.Thread._init_(self)self.cin=cinself.cout=coutself.s=sdefrun(self):whileTrue:r=self()self(r)ifr>0:#print(":Pr
28、oc:<%s>,Seq#:%s,Msg#:%s."%(pid(),r)38. pass39. else:%s, Msg#:40. #print("*Proc:<%s>,Seq#:terminate!"%(pid(),)41. break1.classMLoop(threading.Thread):def_init_(self,s,cin):threading.Thread._init_(self)self.cin=cinself.s=sdefrun(self):whileTrue:r=
29、self()ifr>0:#print(">Proc:<%s>,Seq#:%s,Msg#:%s."%(pid(),r)52. pass53. else:54. #print("Proc:<%s>,Seq#:%s,ringterminated."%(pid(),)55. break56.57. defpid():returnthreading.currentThread()58.59. if_name_='_main_':60. run_benchmark(int(sys.argv1),int(sys.ar
30、gv2)(EditSectionJ)1.#!/Library/Frameworks/..8.29.30.#encoding:utf-8importsysimportprocessing,Queuedefrun_benchmark(n,m):stackless3.1b3here(N=%d,M=%d)!n"%(n,m)firstP=cin=processing.forsinxrange(1,n):seqn=scout=processing.Queue(
31、)Queue()#print("*>s=%d"%(seqn,)p=(target=loop,args=seqn,cin,cout)()cin=coutelse:seqn=s+#print("$>s=%d"%(seqn,)p=(target=mloop,args=seqn,cin)()forrinxrange(m-1,-1,-1):#print("+sendingMsg#%d"%r)(r)GetCode()defloop(s,cin,cout):whiler=()(r)ifTrue:r>0:#print(":
32、Proc:<%s>,Seq#:%s,4.Msg#:%s."%(pid(),s,r)passelse:#print("*Proc:<%s>,Seq#:%s,Msg#:terminate!"%(pid(),s)break35.defmloop(s,cin):36.whileTrue:37. r=()38. ifr>0:39. #print(">Proc:<%s>,Seq#:%s,Msg#:%s."(pid(),s,r)40. pass41. else:42. #print(&quo
33、t;Proc:<%s>,Seq#:%s,ringterminated."%(pid(),s)43. break44.45. defpid():return()46.47. if_name_='_main_'48. run_benchmark(int(sys.argv1),int(sys.argv2)GetCode(EditSectionJ)1. #!/Library/Frameworks/2. #encoding:utf-83. importsys4. fromimportgreenlet5.6. defrun_benchmark(n,m):7. stac
34、kless3.1b3here(N=%d,M=%d)!n"%(n,m)8. glets=()9. forsinxrange(1,n):10. seqn=s11. (greenlet(loop)12. #print("*>s=%d"%(seqn,)13. else:14. seqn=s+115. (greenlet(mloop)16. #print("$>s=%d"%(seqn,)17. glets-1.switch(seqn,glets)18. forrinxrange(m-1,-1,-1):19. #print("+sen
35、dingMsg#%d"%r)20. glets1.switch(r)21. defloop(s,glets):22. previous=gletss-123. next=gletss+124.if s> 1:25.r=(s-1, glets)26.else :27.r=()28.whileTrue :29.ifr > 0:30.# print(":Proc:(pid("loop", s), s,r)31.pass32.else :<%s>, Seq#: %s, Msg#: %s.33. #print("*Proc:<
36、;%s>,Seq#:%s,Msg#:terminate!"%(pid("loop",s),s)34. break35. (r)36. r=()37. (r)38. defmloop(s,glets):1Proc: <%s>, Seq#: %s, Msg#: %s.39. previous=gletss-40. r=(s-1,glets)41. whileTrue:42. ifr>0:43. #print(">(pid("mloop",s),s,r)44. pass45. else46. #print("Proc:<%s>,Seq#:%s,ringterminated."%(pid("mloop",s),s)47. brea
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度房地產(chǎn)職業(yè)經(jīng)理人人才培養(yǎng)與合同3篇
- 2024版建筑工程聯(lián)合承包合同樣本版B版
- 二零二五年度城市更新綠化工程合同2篇
- 2024版建筑工程施工總承包協(xié)議精簡模板版B版
- 2025版?zhèn)€人網(wǎng)絡(luò)安全防護(hù)借款合同
- 2024年銷售員勞動合同模板與團(tuán)隊建設(shè)3篇
- 二零二五年度婚禮婚戒定制與銷售合同3篇
- 二零二五年度房地產(chǎn)合同建筑工程竣工驗收標(biāo)準(zhǔn)3篇
- 家庭教育指導(dǎo)在商業(yè)環(huán)境中的應(yīng)用
- 2024藥品集中招標(biāo)采購服務(wù)合同范本3篇
- taft波完整版可編輯
- 2023-2024學(xué)年浙江省富陽市小學(xué)數(shù)學(xué)五年級上冊期末通關(guān)試題
- TTAF 092-2022 移動終端融合快速充電測試方法
- GB/T 9410-2008移動通信天線通用技術(shù)規(guī)范
- GB/T 5343.2-2007可轉(zhuǎn)位車刀及刀夾第2部分:可轉(zhuǎn)位車刀型式尺寸和技術(shù)條件
- GB/T 32285-2015熱軋H型鋼樁
- GB/T 13772.2-1992機(jī)織物中紗線抗滑移性測定方法模擬縫合法
- SVG運行與維護(hù)課件
- 企業(yè)大學(xué)商學(xué)院建設(shè)方案
- 部編人教版 六年級下冊道德與法治課堂作業(yè)(含答案)
- 幼兒園大班數(shù)學(xué):《長頸鹿的水果店》 課件
評論
0/150
提交評論