亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Golang > 正文

7分鐘讀懂Go的臨時對象池pool以及其應用場景

2020-04-01 18:51:19
字體:
來源:轉載
供稿:網友

臨時對象池 pool 是啥?

sync.Pool 給了一大段注釋來說明 pool 是啥,我們看看這段都說了些什么。

臨時對象池是一些可以分別存儲和取出的臨時對象。

池中的對象會在沒有任何通知的情況下被移出(釋放或者重新取出使用)。如果 pool 中持有某個對象的唯一引用,則該對象很可能會被回收。

Pool 在多 goroutine 使用環境中是安全的。

Pool 是用來緩存已經申請了的 目前未使用的 接下來可能會使用的 內存,以此緩解 GC 壓力。使用它可以方便高效的構建線程安全的 free list(一種用于動態內存申請的數據結構)。然而,它并不適合所有場景的 free list。

在同一 package 中獨立運行的多個獨立線程之間靜默共享一組臨時元素才是 pool 的合理使用場景。Pool 提供在多個獨立 client 之間共享臨時元素的機制。

在 fmt 包中有一個使用 Pool 的例子,它維護了一個動態大小的輸出 buffer。

另外,一些短生命周期的對象不適合使用 pool 來維護,這種情況下使用 pool 不劃算。這是應該使用它們自己的 free list(這里可能指的是 go 內存模型中用于緩存 <32k小對象的 free list) 更高效。

Pool 一旦使用,不能被復制。

Pool 結構體的定義為:

type Pool struct { noCopy noCopy local  unsafe.Pointer // 本地P緩存池指針 localSize uintptr  // 本地P緩存池大小 // 當池中沒有可能對象時 // 會調用 New 函數構造構造一個對象 New func() interface{}}

Pool 中有兩個定義的公共方法,分別是 Put - 向池中添加元素;Get - 從池中獲取元素,如果沒有,則調用 New 生成元素,如果 New 未設置,則返回 nil。

Get

Pool 會為每個 P 維護一個本地池,P 的本地池分為 私有池 private 和共享池 shared。私有池中的元素只能本地 P 使用,共享池中的元素可能會被其他 P 偷走,所以使用私有池 private 時不用加鎖,而使用共享池 shared 時需加鎖。

Get 會優先查找本地 private,再查找本地 shared,最后查找其他 P 的 shared,如果以上全部沒有可用元素,最后會調用 New 函數獲取新元素。

func (p *Pool) Get() interface{} { if race.Enabled {  race.Disable() } // 獲取本地 P 的 poolLocal 對象 l := p.pin()   // 先獲取 private 池中的對象(只有一個) x := l.private l.private = nil runtime_procUnpin() if x == nil {  // 查找本地 shared 池,  // 本地 shared 可能會被其他 P 訪問  // 需要加鎖  l.Lock()  last := len(l.shared) - 1  if last >= 0 {   x = l.shared[last]   l.shared = l.shared[:last]  }  l.Unlock()    // 查找其他 P 的 shared 池  if x == nil {   x = p.getSlow()  } } if race.Enabled {  race.Enable()  if x != nil {   race.Acquire(poolRaceAddr(x))  } } // 未找到可用元素,調用 New 生成 if x == nil && p.New != nil {  x = p.New() } return x}

getSlow,從其他 P 中的 shared 池中獲取可用元素:

func (p *Pool) getSlow() (x interface{}) { // See the comment in pin regarding ordering of the loads. size := atomic.LoadUintptr(&p.localSize) // load-acquire local := p.local       // load-consume // Try to steal one element from other procs. pid := runtime_procPin() runtime_procUnpin() for i := 0; i < int(size); i++ {  l := indexLocal(local, (pid+i+1)%int(size))  // 對應 pool 需加鎖  l.Lock()  last := len(l.shared) - 1  if last >= 0 {   x = l.shared[last]   l.shared = l.shared[:last]   l.Unlock()   break  }  l.Unlock() } return x}

Put

Put 優先把元素放在 private 池中;如果 private 不為空,則放在 shared 池中。有趣的是,在入池之前,該元素有 1/4 可能被丟掉。

func (p *Pool) Put(x interface{}) { if x == nil {  return } if race.Enabled {  if fastrand()%4 == 0 {   // 隨機把元素扔掉...   // Randomly drop x on floor.   return  }  race.ReleaseMerge(poolRaceAddr(x))  race.Disable() } l := p.pin() if l.private == nil {  l.private = x  x = nil } runtime_procUnpin() if x != nil {  // 共享池訪問,需要加鎖  l.Lock()  l.shared = append(l.shared, x)  l.Unlock() } if race.Enabled {  race.Enable() }}

poolCleanup

當世界暫停,垃圾回收將要開始時, poolCleanup 會被調用。該函數內不能分配內存且不能調用任何運行時函數。原因:
防止錯誤的保留整個 Pool

如果 GC 發生時,某個 goroutine 正在訪問 l.shared,整個 Pool 將會保留,下次執行時將會有雙倍內存

func poolCleanup() {  for i, p := range allPools {  allPools[i] = nil  for i := 0; i < int(p.localSize); i++ {   l := indexLocal(p.local, i)   l.private = nil   for j := range l.shared {   l.shared[j] = nil   }   l.shared = nil  }  p.local = nil  p.localSize = 0 } allPools = []*Pool{}}

案例1:gin 中的 Context pool

在 web 應用中,后臺在處理用戶的每條請求時都會為當前請求創建一個上下文環境 Context,用于存儲請求信息及相應信息等。Context 滿足長生命周期的特點,且用戶請求也是屬于并發環境,所以對于線程安全的 Pool 非常適合用來維護 Context 的臨時對象池。

Gin 在結構體 Engine 中定義了一個 pool:

type Engine struct { // ... 省略了其他字段 pool    sync.Pool}

初始化 engine 時定義了 pool 的 New 函數:

engine.pool.New = func() interface{} { return engine.allocateContext()}// allocateContextfunc (engine *Engine) allocateContext() *Context { // 構造新的上下文對象 return &Context{engine: engine}}

ServeHttp:

// 從 pool 中獲取,并轉化為 *Contextc := engine.pool.Get().(*Context)c.writermem.reset(w)c.Request = reqc.reset() // resetengine.handleHTTPRequest(c)// 再扔回 pool 中engine.pool.Put(c)

案例2:fmt 中的 printer pool

printer 也符合長生命周期的特點,同時也會可能會在多 goroutine 中使用,所以也適合使用 pool 來維護。

printer 與 它的臨時對象池

// pp 用來維護 printer 的狀態// 它通過 sync.Pool 來重用,避免申請內存type pp struct { //... 字段已省略}var ppFree = sync.Pool{ New: func() interface{} { return new(pp) },}

獲取與釋放:

func newPrinter() *pp { p := ppFree.Get().(*pp) p.panicking = false p.erroring = false p.fmt.init(&p.buf) return p}func (p *pp) free() { p.buf = p.buf[:0] p.arg = nil p.value = reflect.Value{} ppFree.Put(p)}

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产日韩欧美自拍| 日韩中文在线中文网三级| 欧美交受高潮1| 欧美做爰性生交视频| 国产成人aa精品一区在线播放| 日韩国产高清视频在线| 日韩视频免费看| 国产日韩在线精品av| 国产精品精品视频一区二区三区| 91久久精品美女高潮| 国产精品自拍网| 久久九九全国免费精品观看| 国产高清在线不卡| 亚洲成人久久久| 日韩中文字幕网址| 日韩av免费看| 97视频在线观看亚洲| 伊人久久久久久久久久久| 亚洲变态欧美另类捆绑| 欧美激情2020午夜免费观看| 国产91色在线播放| 日韩在线观看免费全集电视剧网站| 国产免费观看久久黄| 国产精品日韩久久久久| 日韩亚洲在线观看| 国产视频一区在线| 亚洲人成免费电影| 国产视频亚洲精品| 亚洲wwwav| 97涩涩爰在线观看亚洲| 欧美成人午夜剧场免费观看| 韩国v欧美v日本v亚洲| 久久精品一偷一偷国产| 国产精品视频26uuu| 国产精品欧美在线| 91免费在线视频| 精品国产拍在线观看| 久久人人爽人人爽人人片av高清| 日韩在线视频导航| 久久艳片www.17c.com| 在线成人中文字幕| 欧美日韩国产成人| 欧美成人sm免费视频| 精品国产乱码久久久久久婷婷| 中文字幕一区二区三区电影| 亚洲人成电影在线| 97超视频免费观看| 日韩视频免费观看| 欧美中文字幕视频在线观看| 日av在线播放中文不卡| 欧美野外猛男的大粗鳮| 成人免费直播live| 国产一区视频在线| 精品国产一区二区三区久久久狼| 亚洲精品国产精品乱码不99按摩| 欧美在线视频免费观看| 国产亚洲综合久久| 日本免费一区二区三区视频观看| 国产丝袜一区二区| 亚洲欧美日韩国产中文专区| 亚州av一区二区| 欧美一区二三区| 国外成人在线视频| 色哟哟网站入口亚洲精品| 日韩av电影中文字幕| 欧美日韩中国免费专区在线看| 色琪琪综合男人的天堂aⅴ视频| 俺去亚洲欧洲欧美日韩| 欧美一级淫片丝袜脚交| 日本精品va在线观看| 亚洲视频在线观看视频| 国产精品久久久久久久久久东京| 91成品人片a无限观看| 国产免费观看久久黄| 亚洲成人网在线观看| 久久伊人免费视频| 精品国产1区2区| 中文字幕精品网| 国产精选久久久久久| 久久最新资源网| 国产美女久久精品香蕉69| 国产精品9999| 91免费国产视频| 永久免费精品影视网站| 亚洲一区免费网站| 免费av在线一区| 日韩电影中文字幕在线观看| 国产精品露脸自拍| 黑人精品xxx一区一二区| www国产精品视频| 国产亚洲一区精品| 欧美大成色www永久网站婷| 欧美高清视频在线| 亚洲欧美日韩精品久久| 国产一区二区三区在线观看网站| 亚洲性生活视频| 97超碰国产精品女人人人爽| 国产一区二区黄| 色偷偷噜噜噜亚洲男人的天堂| 亚洲美腿欧美激情另类| 国产精品视频在线观看| 日本国产欧美一区二区三区| 狠狠久久五月精品中文字幕| 国内免费精品永久在线视频| 亚洲性生活视频| 久久躁日日躁aaaaxxxx| 午夜精品久久久久久久男人的天堂| 国产乱人伦真实精品视频| 91大神在线播放精品| 亚洲成人亚洲激情| www.99久久热国产日韩欧美.com| 日韩av最新在线| 日本高清+成人网在线观看| 成人妇女免费播放久久久| 国产成人福利夜色影视| 人人做人人澡人人爽欧美| 国产精品视频白浆免费视频| 国产精品免费看久久久香蕉| 久久久这里只有精品视频| 国产精品一二区| 欧美在线视频免费| 欧美丝袜美女中出在线| 久久久999精品免费| 欧美午夜丰满在线18影院| 久久久在线视频| 黑人巨大精品欧美一区二区一视频| 久久精品电影网| 久久久成人的性感天堂| 亚洲午夜av久久乱码| 精品久久久久久中文字幕| 在线播放国产一区二区三区| 亚洲精品永久免费精品| 国产精品视频播放| 日韩美女中文字幕| 欧美激情日韩图片| yellow中文字幕久久| 亚洲国产免费av| 欧美中文在线字幕| 欧美电影免费播放| 国产精品久久久久国产a级| 欧美成人手机在线| 国产精品国产三级国产aⅴ9色| 精品成人69xx.xyz| 国产在线观看精品| 久久久久久久久久国产| 美日韩丰满少妇在线观看| 中文一区二区视频| 欧美一区二区三区免费观看| 亚洲石原莉奈一区二区在线观看| 亚洲成人三级在线| 国产精品一区二区电影| 欧美精品在线免费观看| 精品亚洲一区二区三区在线观看| 国产成人精品久久二区二区91| 992tv成人免费视频| 亚洲欧美制服第一页| 欧美国产高跟鞋裸体秀xxxhd| 亚洲国产精品成人一区二区| 久久91精品国产| 日韩美女在线观看一区| 影音先锋欧美精品| 亚洲欧美国内爽妇网| 欧美高清性猛交| 亚洲成人久久久久|