成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

go語(yǔ)言設(shè)計(jì)模式對(duì)象池 go的設(shè)計(jì)模式

golang sync.pool對(duì)象復(fù)用 并發(fā)原理 緩存池

在go http每一次go serve(l)都會(huì)構(gòu)建Request數(shù)據(jù)結(jié)構(gòu)。在大量數(shù)據(jù)請(qǐng)求或高并發(fā)的場(chǎng)景中,頻繁創(chuàng)建銷毀對(duì)象,會(huì)導(dǎo)致GC壓力。解決辦法之一就是使用對(duì)象復(fù)用技術(shù)。在http協(xié)議層之下,使用對(duì)象復(fù)用技術(shù)創(chuàng)建Request數(shù)據(jù)結(jié)構(gòu)。在http協(xié)議層之上,可以使用對(duì)象復(fù)用技術(shù)創(chuàng)建(w,*r,ctx)數(shù)據(jù)結(jié)構(gòu)。這樣即可以回快TCP層讀包之后的解析速度,也可也加快請(qǐng)求處理的速度。

創(chuàng)新互聯(lián)是由多位在大型網(wǎng)絡(luò)公司、廣告設(shè)計(jì)公司的優(yōu)秀設(shè)計(jì)人員和策劃人員組成的一個(gè)具有豐富經(jīng)驗(yàn)的團(tuán)隊(duì),其中包括網(wǎng)站策劃、網(wǎng)頁(yè)美工、網(wǎng)站程序員、網(wǎng)頁(yè)設(shè)計(jì)師、平面廣告設(shè)計(jì)師、網(wǎng)絡(luò)營(yíng)銷人員及形象策劃。承接:網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、網(wǎng)站改版、網(wǎng)頁(yè)設(shè)計(jì)制作、網(wǎng)站建設(shè)與維護(hù)、網(wǎng)絡(luò)推廣、數(shù)據(jù)庫(kù)開發(fā),以高性價(jià)比制作企業(yè)網(wǎng)站、行業(yè)門戶平臺(tái)等全方位的服務(wù)。

先上一個(gè)測(cè)試:

結(jié)論是這樣的:

貌似使用池化,性能弱爆了???這似乎與net/http使用sync.pool池化Request來(lái)優(yōu)化性能的選擇相違背。這同時(shí)也說(shuō)明了一個(gè)問(wèn)題,好的東西,如果濫用反而造成了性能成倍的下降。在看過(guò)pool原理之后,結(jié)合實(shí)例,將給出正確的使用方法,并給出預(yù)期的效果。

sync.Pool是一個(gè) 協(xié)程安全 的 臨時(shí)對(duì)象池 。數(shù)據(jù)結(jié)構(gòu)如下:

local 成員的真實(shí)類型是一個(gè) poolLocal 數(shù)組,localSize 是數(shù)組長(zhǎng)度。這涉及到Pool實(shí)現(xiàn),pool為每個(gè)P分配了一個(gè)對(duì)象,P數(shù)量設(shè)置為runtime.GOMAXPROCS(0)。在并發(fā)讀寫時(shí),goroutine綁定的P有對(duì)象,先用自己的,沒(méi)有去偷其它P的。go語(yǔ)言將數(shù)據(jù)分散在了各個(gè)真正運(yùn)行的P中,降低了鎖競(jìng)爭(zhēng),提高了并發(fā)能力。

不要習(xí)慣性地誤認(rèn)為New是一個(gè)關(guān)鍵字,這里的New是Pool的一個(gè)字段,也是一個(gè)閉包名稱。其API:

如果不指定New字段,對(duì)象池為空時(shí)會(huì)返回nil,而不是一個(gè)新構(gòu)建的對(duì)象。Get()到的對(duì)象是隨機(jī)的。

原生sync.Pool的問(wèn)題是,Pool中的對(duì)象會(huì)被GC清理掉,這使得sync.Pool只適合做簡(jiǎn)單地對(duì)象池,不適合作連接池。

pool創(chuàng)建時(shí)不能指定大小,沒(méi)有數(shù)量限制。pool中對(duì)象會(huì)被GC清掉,只存在于兩次GC之間。實(shí)現(xiàn)是pool的init方法注冊(cè)了一個(gè)poolCleanup()函數(shù),這個(gè)方法在GC之前執(zhí)行,清空pool中的所有緩存對(duì)象。

為使多協(xié)程使用同一個(gè)POOL。最基本的想法就是每個(gè)協(xié)程,加鎖去操作共享的POOL,這顯然是低效的。而進(jìn)一步改進(jìn),類似于ConcurrentHashMap(JDK7)的分Segment,提高其并發(fā)性可以一定程度性緩解。

注意到pool中的對(duì)象是無(wú)差異性的,加鎖或者分段加鎖都不是較好的做法。go的做法是為每一個(gè)綁定協(xié)程的P都分配一個(gè)子池。每個(gè)子池又分為私有池和共享列表。共享列表是分別存放在各個(gè)P之上的共享區(qū)域,而不是各個(gè)P共享的一塊內(nèi)存。協(xié)程拿自己P里的子池對(duì)象不需要加鎖,拿共享列表中的就需要加鎖了。

Get對(duì)象過(guò)程:

Put過(guò)程:

如何解決Get最壞情況遍歷所有P才獲取得對(duì)象呢:

方法1止前sync.pool并沒(méi)有這樣的設(shè)置。方法2由于goroutine被分配到哪個(gè)P由調(diào)度器調(diào)度不可控,無(wú)法確保其平衡。

由于不可控的GC導(dǎo)致生命周期過(guò)短,且池大小不可控,因而不適合作連接池。僅適用于增加對(duì)象重用機(jī)率,減少GC負(fù)擔(dān)。2

執(zhí)行結(jié)果:

單線程情況下,遍歷其它無(wú)元素的P,長(zhǎng)時(shí)間加鎖性能低下。啟用協(xié)程改善。

結(jié)果:

測(cè)試場(chǎng)景在goroutines遠(yuǎn)大于GOMAXPROCS情況下,與非池化性能差異巨大。

測(cè)試結(jié)果

可以看到同樣使用*sync.pool,較大池大小的命中率較高,性能遠(yuǎn)高于空池。

結(jié)論:pool在一定的使用條件下提高并發(fā)性能,條件1是協(xié)程數(shù)遠(yuǎn)大于GOMAXPROCS,條件2是池中對(duì)象遠(yuǎn)大于GOMAXPROCS。歸結(jié)成一個(gè)原因就是使對(duì)象在各個(gè)P中均勻分布。

池pool和緩存cache的區(qū)別。池的意思是,池內(nèi)對(duì)象是可以互換的,不關(guān)心具體值,甚至不需要區(qū)分是新建的還是從池中拿出的。緩存指的是KV映射,緩存里的值互不相同,清除機(jī)制更為復(fù)雜。緩存清除算法如LRU、LIRS緩存算法。

池空間回收的幾種方式。一些是GC前回收,一些是基于時(shí)鐘或弱引用回收。最終確定在GC時(shí)回收Pool內(nèi)對(duì)象,即不回避GC。用java的GC解釋弱引用。GC的四種引用:強(qiáng)引用、弱引用、軟引用、虛引用。虛引用即沒(méi)有引用,弱引用GC但有空間則保留,軟引用GC即清除。ThreadLocal的值為弱引用的例子。

regexp 包為了保證并發(fā)時(shí)使用同一個(gè)正則,而維護(hù)了一組狀態(tài)機(jī)。

fmt包做字串拼接,從sync.pool拿[]byte對(duì)象。避免頻繁構(gòu)建再GC效率高很多。

golang sync.Pool的用法及實(shí)現(xiàn)

正如sycn.Pool的名字所示,這是go中實(shí)現(xiàn)的一個(gè)對(duì)象池,為什么要有這個(gè)池呢?首先go是自帶垃圾回收機(jī)制(也就是通常所說(shuō)的gc)。gc會(huì)帶來(lái)運(yùn)行時(shí)的開銷,對(duì)于高頻的內(nèi)存申請(qǐng)與釋放,如果將不用的對(duì)象存放在一個(gè)池子中,用的時(shí)候從池子中取出一個(gè)對(duì)象,用完了再還回去,這樣就能減輕gc的壓力。

對(duì)于池這個(gè)概念,之前可能聽說(shuō)過(guò)連接池。能否用sync.Pool實(shí)現(xiàn)一個(gè)連接池呢?答案是不能的。因?yàn)閷?duì)于sync.Pool而言,我們無(wú)法保證每次放回去再取出來(lái)的對(duì)象是與之前一致的,對(duì)象的內(nèi)存存在著唄銷毀的可能。因此,這個(gè)sync.Pool的存在僅僅是為了減緩gc的壓力而生的。

定義sync.Pool的時(shí)候只需要設(shè)置一個(gè)New成員,它是一個(gè)函數(shù),類型為func() interface{},當(dāng)池子中沒(méi)有空閑的對(duì)象時(shí)就會(huì)調(diào)用New函數(shù)生成一個(gè)。由于pool中對(duì)象的數(shù)量不可控,因此并沒(méi)有傳遞任何與對(duì)象數(shù)量有關(guān)的參數(shù)。

然后,調(diào)用調(diào)用Get函數(shù)就可以取出一個(gè)對(duì)象,調(diào)用Put函數(shù)就可以將對(duì)象歸還到池子中。

Go語(yǔ)言設(shè)計(jì)與實(shí)現(xiàn)(上)

基本設(shè)計(jì)思路:

類型轉(zhuǎn)換、類型斷言、動(dòng)態(tài)派發(fā)。iface,eface。

反射對(duì)象具有的方法:

編譯優(yōu)化:

內(nèi)部實(shí)現(xiàn):

實(shí)現(xiàn) Context 接口有以下幾個(gè)類型(空實(shí)現(xiàn)就忽略了):

互斥鎖的控制邏輯:

設(shè)計(jì)思路:

(以上為寫被讀阻塞,下面是讀被寫阻塞)

總結(jié),讀寫鎖的設(shè)計(jì)還是非常巧妙的:

設(shè)計(jì)思路:

WaitGroup 有三個(gè)暴露的函數(shù):

部件:

設(shè)計(jì)思路:

結(jié)構(gòu):

Once 只暴露了一個(gè)方法:

實(shí)現(xiàn):

三個(gè)關(guān)鍵點(diǎn):

細(xì)節(jié):

讓多協(xié)程任務(wù)的開始執(zhí)行時(shí)間可控(按順序或歸一)。(Context 是控制結(jié)束時(shí)間)

設(shè)計(jì)思路: 通過(guò)一個(gè)鎖和內(nèi)置的 notifyList 隊(duì)列實(shí)現(xiàn),Wait() 會(huì)生成票據(jù),并將等待協(xié)程信息加入鏈表中,等待控制協(xié)程中發(fā)送信號(hào)通知一個(gè)(Signal())或所有(Boardcast())等待者(內(nèi)部實(shí)現(xiàn)是通過(guò)票據(jù)通知的)來(lái)控制協(xié)程解除阻塞。

暴露四個(gè)函數(shù):

實(shí)現(xiàn)細(xì)節(jié):

部件:

包: golang.org/x/sync/errgroup

作用:開啟 func() error 函數(shù)簽名的協(xié)程,在同 Group 下協(xié)程并發(fā)執(zhí)行過(guò)程并收集首次 err 錯(cuò)誤。通過(guò) Context 的傳入,還可以控制在首次 err 出現(xiàn)時(shí)就終止組內(nèi)各協(xié)程。

設(shè)計(jì)思路:

結(jié)構(gòu):

暴露的方法:

實(shí)現(xiàn)細(xì)節(jié):

注意問(wèn)題:

包: "golang.org/x/sync/semaphore"

作用:排隊(duì)借資源(如錢,有借有還)的一種場(chǎng)景。此包相當(dāng)于對(duì)底層信號(hào)量的一種暴露。

設(shè)計(jì)思路:有一定數(shù)量的資源 Weight,每一個(gè) waiter 攜帶一個(gè) channel 和要借的數(shù)量 n。通過(guò)隊(duì)列排隊(duì)執(zhí)行借貸。

結(jié)構(gòu):

暴露方法:

細(xì)節(jié):

部件:

細(xì)節(jié):

包: "golang.org/x/sync/singleflight"

作用:防擊穿。瞬時(shí)的相同請(qǐng)求只調(diào)用一次,response 被所有相同請(qǐng)求共享。

設(shè)計(jì)思路:按請(qǐng)求的 key 分組(一個(gè) *call 是一個(gè)組,用 map 映射存儲(chǔ)組),每個(gè)組只進(jìn)行一次訪問(wèn),組內(nèi)每個(gè)協(xié)程會(huì)獲得對(duì)應(yīng)結(jié)果的一個(gè)拷貝。

結(jié)構(gòu):

邏輯:

細(xì)節(jié):

部件:

如有錯(cuò)誤,請(qǐng)批評(píng)指正。

當(dāng)前題目:go語(yǔ)言設(shè)計(jì)模式對(duì)象池 go的設(shè)計(jì)模式
轉(zhuǎn)載注明:http://jinyejixie.com/article48/hephep.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內(nèi)鏈、網(wǎng)站策劃、網(wǎng)站排名、網(wǎng)頁(yè)設(shè)計(jì)公司虛擬主機(jī)、品牌網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)
内乡县| 静乐县| 昭苏县| 武威市| 富蕴县| 沁水县| 汪清县| 石楼县| 土默特左旗| 平原县| 开平市| 垦利县| 德惠市| 沁水县| 天峻县| 亳州市| 花莲市| 宜君县| 永宁县| 郓城县| 南和县| 古蔺县| 磐石市| 浦北县| 固原市| 资兴市| 兴文县| 普兰店市| 察雅县| 泰和县| 青神县| 山东| 诸暨市| 武陟县| 钟山县| 冕宁县| 金秀| 岗巴县| 绵竹市| 伊川县| 常宁市|