一摄凡、問(wèn)題的思考
以前我們?cè)谧龆嗑€程開(kāi)發(fā)時(shí)续徽,經(jīng)常提到線程池的概念,那么為啥要有線程池的概念那亲澡?為啥在golang開(kāi)發(fā)時(shí)钦扭,很少有人提到協(xié)程池的概念?
二床绪、思路
? ? ? ?線程的創(chuàng)建客情、銷(xiāo)毀以及線程調(diào)度往往牽扯到資源內(nèi)核態(tài)與用戶態(tài)的切換,是比較消耗資源的癞己,如果我們?cè)谶M(jìn)行多線程編程時(shí)膀斋,代碼運(yùn)行中動(dòng)態(tài)創(chuàng)建線程資源,從高性能的考慮出發(fā)末秃,必然會(huì)影響服務(wù)整體的性能概页。因此籽御,線程池的存在很有必要练慕。而golang的協(xié)程是運(yùn)行在用戶態(tài)的,因此協(xié)程的調(diào)度技掏,不涉及內(nèi)核態(tài)铃将、用戶態(tài)的切換,這里可以看下GMP模型深入理解下哑梳。線程相比協(xié)程占用更多的資源劲阎,比如一個(gè)線程大約占用8M的內(nèi)存,而一個(gè)協(xié)程鸠真,則占用4K的內(nèi)存悯仙,既然協(xié)程這么輕小,在我們開(kāi)發(fā)時(shí)是否有必要做協(xié)程池設(shè)計(jì)思考吠卷?這里結(jié)合壓測(cè)數(shù)據(jù)以及一些想法發(fā)散下锡垄。
三、golang協(xié)程池模型
3.1 模型1-動(dòng)態(tài)創(chuàng)建協(xié)程消費(fèi)task
每收到一個(gè)task祭隔,創(chuàng)建一個(gè)協(xié)程處理該task货岭,壓測(cè)結(jié)果如下:
從bench壓測(cè)數(shù)據(jù)看,每次循環(huán)執(zhí)行的時(shí)間基本上為66us.
3.2 模型2-固定worker消費(fèi)task
具體模型可參考https://studygolang.com/articles/15477疾渴,劉丹冰分享的《Golang的協(xié)程池設(shè)計(jì)》千贯,具體模型如下:
就以4個(gè)worker協(xié)程消費(fèi)task為例(因?yàn)閴簻y(cè)的服務(wù)器為mac pro,四核)搞坝,我們壓測(cè)下搔谴,數(shù)據(jù)如下:
從bench壓測(cè)數(shù)據(jù)看,每次循環(huán)執(zhí)行的時(shí)間基本上為55us.
相比第一個(gè)模型從壓測(cè)數(shù)據(jù)看桩撮,每次循環(huán)節(jié)約了大約11us敦第。
總結(jié):
1慌核、如果程序并發(fā)創(chuàng)建協(xié)程數(shù)據(jù)量很大,每個(gè)協(xié)程處理任務(wù)的事件較長(zhǎng)申尼,需要維持協(xié)程池垮卓,畢竟服務(wù)器的資源是有上限的,到達(dá)一定數(shù)量之后师幕,會(huì)導(dǎo)致協(xié)程數(shù)過(guò)多而產(chǎn)生CPU負(fù)載較高的情況粟按。
2、從自己壓測(cè)數(shù)據(jù)看霹粥,創(chuàng)建協(xié)程的過(guò)程確實(shí)比較小的系統(tǒng)開(kāi)銷(xiāo)灭将,通過(guò)上述壓測(cè)數(shù)據(jù)來(lái)看也只有11us的差距。
討論:
是否有更加高效的高性能協(xié)程池模型后控?
增加一個(gè)dispatcher模塊庙曙,根據(jù)msg的ID做dispatcher分發(fā)到不同的協(xié)程channel中是否更加高效?用戶可自己實(shí)現(xiàn)dispatcher以及message的處理方式浩淘,具體模型如下:
具體代碼我已經(jīng)提到到git上:https://github.com/go-snail/pool.git
壓測(cè)數(shù)據(jù)如下: