文中全部的Proactor模式,均指模擬Proactor模式,而不是操做系統級別的Proactor網絡
先說下Erlang的check_io是作什麼用的。Erlang中的check_io實質是調用系統的epoll/select/kevent/poll對IO事件進行檢查。優化
那麼問題就產生了,Erlang的網絡模型不是Proactor模式嘛,它和scheduler有什麼關係?spa
爲了回答這個問題,咱們先說下Erlang的Proactor模式和常規的Proactor模式有什麼樣的差別。操作系統
Erlang所採用Proactor模式和常規的Proactor模式相比有兩大差別。第一大差別是,Erlang的Proactor模式並無專用的IO線程,而是複用scheduler的線程。第二大差別是,Erlang的Proactor模式並無在事件發生後馬上進行IO讀寫操做,而是將讀寫操做的事件放入和fd相關聯的Erlang驅動中了,由Erlang的驅動來完成真正的IO操做。這樣咱們就能很明顯的看出來,Erlang的scheduler既是IO線程又是業務線程。線程
好了,這又產生問題了,Erlang爲何選擇這樣作?那麼Erlang是如何讓scheduler線程平衡IO操做和業務處理的?隊列
Erlang這麼作我我的認爲有如下幾個緣由:進程
常規Proactor模式中,IO操做集中在IO線程上面,當其中一個Socket傳輸大塊數據的時候,會出現IO時效性下降。由於Erlang的網絡驅動自己是一個Port進程,而多個Port進程能夠分散到多個Erlang的schduler中,若是將事件和fd放入驅動的隊列當中,讓驅動來完成真正的IO操做,將讀寫IO的操做分散到多個線程上,會大大的提升IO的時效性。事件
做爲一個通用語言的虛擬機,Erlang不能假設某種業務場景針對Proactor模式進行優化。當出現業務並不複雜而IO吞吐又很高的狀況時,會出現業務線程大量空閒而IO線程滿載的場景,那麼這也是一種資源浪費,因此讓業務線程參與到部分IO操做上能夠提升IO吞吐的量級。資源
Erlang是如何讓scheduler線程平衡IO操做和業務處理的:虛擬機
Erlang的scheduler使用優先執行RunQueue中任務而後在進行IO檢查的策略。
Erlang的scheduler中有一個計數器,當RunQueue的任務執行到必定數量的時候,強制性的進行IO檢查,防止過分執行RunQueue而讓IO沒機會進行檢查。
多個scheduler共享一個pollset,當一個scheduler檢查IO的時候,其它scheduler盡最大力量執行RunQueue。這裏面經過使用原子性的置位操做,減小了多個scheduler去搶鎖引發的開銷。