如何提高吞吐量
快期末考試了,作為學霸的你(對记靡,就是你L父汀)忙的春光滿面。
一大波學妹來讓你輔導摸吠。
你把她們聚集到了大教室里空凸,對她們說:一個一個來。很快一個妹子過來了寸痢,但卻得等她翻書呀洲,找題,整理思路,甚至還要先照照鏡子問你她漂亮嗎道逗,最后才慢吞吞的開始問你題兵罢。你眼看著后面排著長隊的妹子在等著你,但你卻只能如此緩慢的一個一個親(禽)手(獸)輔導滓窍,效率真低卖词。一天才能接觸幾個?
這就是
單進程單線程阻塞模式
贰您。 如果遇到哪個妹子纏著你一天坏平,你就別想接觸其他妹子了。
改進一號
于是你想這么不行啊锦亦,妹子們需要你舶替。于是你學會了分身術,把自己分成N個杠园,同時給N個妹子服務顾瞪,于是把妹效率提高了N倍。當你還在高興的時候抛蚁,問題出來了陈醒。
教室就這么大,不可能把自己分身出太多瞧甩,否則一個教室全是自己的分身钉跷,妹子進不來,搞毛啊肚逸。 不行爷辙,一定要限制分身的數(shù)量。此時你內(nèi)心極度惆悵朦促,唉膝晾,難道把妹效率有個不可逾越的鴻溝嗎?
尼瑪务冕,人可以分身血当,但水杯只有一個啊。你的分身老是輪流站著你的水杯禀忆,你早已饑渴難耐臊旭,卻拿不到水杯。于是你規(guī)定箩退,誰拿了水杯巍扛,就在黑板上標記一下。用完了乏德,要及時把標記擦掉撤奸。這樣其他分身如果看到黑板有標記吠昭,那就等等,當發(fā)現(xiàn)黑板沒有標記的時候胧瓜,你們就去搶矢棚,誰先搶到,他就去做標記府喳,獨享水杯蒲肋。
但后來一些各種蛋疼原因,黑板上的標記沒有被清除钝满,于是你和你的分身們渴的實在沒法輔導兜粘,于是把妹效率降低很多。
這就是
多進程/線程模式
弯蚜。 目前Linux很多經(jīng)典的服務都是這種模型孔轴。但缺點也顯而易見:
多進程/線程的數(shù)量在 一臺機器 上數(shù)量是嚴重收限制的。
早期一些服務是動態(tài)創(chuàng)建/銷毀進程碎捺。在當時看起來很不錯路鹰。鏈接多了,就多來點進程給那些大爺們服務收厨。于是在大量鏈接的沖擊下晋柱,服務不停的創(chuàng)建新進程,最終導致系統(tǒng)資源枯竭诵叁,服務器失去響應雁竞。(現(xiàn)在的Linux會直接殺死占用內(nèi)存過多的程序,從而保證系統(tǒng)自身處于可響應狀態(tài))
線程雖然輕量一點拧额,但在Linux系統(tǒng)中碑诉,線程會占用8M棧空間势腮,對于要保持長鏈接的請求,也不可能弄多少線程出來漫仆。
來捎拯,讓我們和鎖一起愉快的玩耍 不說了,你們先玩盲厌,我走了
關于多線程還有
leader-follow
署照,Half-Sync/Half-Async
等模式。它們對多線程做了很多優(yōu)化吗浩,可以處理大量鏈接建芙。但我并不了解,所以這里也不做陳述懂扼。
改進二號
恩禁荸,你想著要改進右蒲,于是先不分身了。
你有了新辦法: 你首先請了你的死黨赶熟,他就站在教室里瑰妄。
然后你對妹子們說,誰準備好了要我來輔導映砖,就先給我說一下间坐,然后就準備著,等準備好了去給我兄弟說邑退。我知道了就會叫你竹宋。
有妹子來到你這兒報名,然后她們就下去準備問題了地技。你就把她們的名字記在一張紙上蜈七,當你空閑的時候,你就把紙給你兄弟說乓土,看看這上面誰準備好了宪潮,然后你兄弟告訴你誰好了,你就把那個妹子叫過來趣苏,搞定后狡相,再次把名單給你兄弟,不停的這個循環(huán)食磕。
但后來又發(fā)現(xiàn)問題了尽棕。
紙?zhí)。瑏韴竺拿米犹啾蚵祝涗洸幌隆?/p>
-
你在空閑的時候得把整張紙給你兄弟滔悉,你兄弟要依次看一邊名字,然后找出誰準備好了单绑。最后回官,還要把紙給你傳回去。
你兄弟要抱怨了搂橙,尼瑪老子不停的看這密密麻麻的名字歉提,好累啊。跟你傳紙的頻率比老子lu的頻率都高扒苔巨!
這是
基于事件的select
模式。(或者叫多路IO復用)
它的限制很多:
你需要把要監(jiān)聽的fd加入一個列表中废离,Linux系統(tǒng)默認列表大小只有1024
每次你都需要把這個fd列表傳遞給select調(diào)用侄泽。select調(diào)用再返回給你哪個fd上你感興趣的事件觸發(fā)了。也就是每次都需要從用戶態(tài)->內(nèi)核態(tài)->用戶態(tài)這樣拷貝一次蜻韭。系統(tǒng)消耗太大
改進三號
恩悼尾,select方式要不停的輪尋柿扣,限制多多,效率也沒高哪去诀豁。
于是你又改進了一下方式:
妹子還是到你這兒來報道窄刘,但你不用紙記錄她的名字,而是立即告訴你兄弟舷胜,誰誰誰報名了娩践,你留意下,她要是準備好了烹骨,你把她名字告訴我翻伺。
然后當你沒事干的時候,就可以睡睡覺什么的沮焕。只要等著你兄弟來叫你就行了吨岭。
這就是
epoll/kqueue/ICOP 事件回調(diào)
機制.
epoll 對應Linux
kqueue對應BSD
ICOP對應Windows不用 select 那樣的去輪尋,而是注冊fd和回調(diào)峦树,等待事件通知即可辣辫。
libevent
,libev
這些庫就是將系統(tǒng)提供的事件回調(diào)機制的封裝,供上層應用程序方便使用魁巩。
協(xié)程
當然急灭,除了上面那些,還有一種模型谷遂,被稱為協(xié)程葬馋。
特點如下:
- 由程序自己產(chǎn)生,管理肾扰,調(diào)度畴嘶,銷毀。和OS沒一點關系
- 在一個OS進程中集晚,可以產(chǎn)生百萬級別的協(xié)程窗悯。
- 基于協(xié)程的Actor模型不共享數(shù)據(jù),寫并發(fā)程序得心應手
目前支持協(xié)程的語言有
這里也得提一下 Scala偷拔,它也有Actor模型蒋院,而且akka庫也很強大。但應該不屬于協(xié)程范圍条摸。
Python 是通過 Gevent 庫來實現(xiàn)的協(xié)程悦污。
我在工作和自己的折騰中都用過Erlang和Gevent铸屉,從協(xié)程角度講钉蒲,它們都很好用。
- Erlang 在各個process之間發(fā)送消息彻坛,不共享顷啼。沒有鎖的煩惱
- Gevent可以讓你用同步的方式來寫異步程序
看起來協(xié)程好處多多踏枣,那么 它有什么缺點呢?
- 因為協(xié)程還是運行在一個OS進程中钙蒙,所以協(xié)程不能跑阻塞任務茵瀑,否則就要將整個OS進程阻塞住了。
后面再寫個文章具體講講我對Erlang和Gevent的看法