欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入理解Go語言對(duì)象池

 更新時(shí)間:2024年01月25日 10:25:56   作者:FunTester  
對(duì)象池是一種在編程中用于優(yōu)化資源管理的技術(shù),本文主要介紹了深入理解Go語言對(duì)象池,對(duì)象池通常通過sync.Pool包或自定義數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn),下面就來介紹一下

對(duì)象池是一種在編程中用于優(yōu)化資源管理的技術(shù)。它的基本思想是在應(yīng)用程序啟動(dòng)時(shí)預(yù)先創(chuàng)建一組對(duì)象,并在需要時(shí)重復(fù)使用這些對(duì)象,而不是頻繁地創(chuàng)建和銷毀。這種重用的機(jī)制有助于減少資源分配和回收的開銷,提高程序性能,特別在涉及大量短壽命對(duì)象的場(chǎng)景下效果顯著。

在Go語言中,對(duì)象池通常通過sync.Pool包或自定義數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)。該機(jī)制利用Go的垃圾回收策略,通過避免不必要的對(duì)象分配來減輕垃圾回收的負(fù)擔(dān)。對(duì)象的創(chuàng)建、重用和釋放是對(duì)象池的核心流程,其中創(chuàng)建發(fā)生在對(duì)象池為空且需要新對(duì)象時(shí),重用則是從對(duì)象池中獲取現(xiàn)有對(duì)象,而釋放則是將不再需要的對(duì)象放回對(duì)象池供其他地方使用。

對(duì)象池在高并發(fā)和高性能的Go應(yīng)用中具有廣泛應(yīng)用。例如,在網(wǎng)絡(luò)編程中,可以使用對(duì)象池來維護(hù)連接池,避免頻繁地創(chuàng)建和關(guān)閉連接;在數(shù)據(jù)庫訪問中,對(duì)象池可以用于管理數(shù)據(jù)庫連接,減少連接的創(chuàng)建和銷毀開銷。這些實(shí)際應(yīng)用場(chǎng)景充分展示了對(duì)象池在提升性能和資源利用率方面的價(jià)值。

之前在Java性能測(cè)試當(dāng)中也分享了通用池化框架 Apache common-pool2 以及對(duì)應(yīng)的實(shí)踐案例,今天分享一下Go語言在對(duì)象池實(shí)現(xiàn)上的應(yīng)用。

對(duì)象池的優(yōu)勢(shì)

這里不得不簡(jiǎn)單分享一下Go語言的垃圾回收。垃圾回收(Garbage Collection,GC)是一種自動(dòng)管理內(nèi)存的機(jī)制,用于檢測(cè)和釋放不再使用的內(nèi)存對(duì)象,以防止內(nèi)存泄漏。Go的垃圾回收機(jī)制采用了基于并發(fā)的標(biāo)記-清理算法,以及部分停頓的方式來進(jìn)行垃圾回收。

Go語言中,頻繁創(chuàng)建對(duì)象和回收對(duì)象會(huì)帶來兩個(gè)性能問題。

  • 頻繁分配和銷毀對(duì)象會(huì)造成更多的內(nèi)存碎片,處理這些碎片會(huì)增加額外資源開銷。
  • 頻繁分配和銷毀對(duì)象會(huì)導(dǎo)致更頻繁的停頓時(shí)間。
  • 頻繁分配和銷毀對(duì)象會(huì)帶來更多系統(tǒng)資源開銷。

為了解決這個(gè)問題,處理在優(yōu)化編碼質(zhì)量和調(diào)整GC參數(shù)之外,對(duì)象池技術(shù)是最重要的解決方案。以上三個(gè)問題均轉(zhuǎn)化為對(duì)象池技術(shù)的優(yōu)點(diǎn),

在高性能編程實(shí)踐中,對(duì)象池技術(shù)是一項(xiàng)不可或缺的戰(zhàn)略,它不僅能顯著提升系統(tǒng)性能,降低資源開銷,還有助于優(yōu)化內(nèi)存利用率。通過巧妙地重用已經(jīng)存在的對(duì)象,對(duì)象池有效地規(guī)避了頻繁的對(duì)象創(chuàng)建和銷毀過程,減輕了系統(tǒng)負(fù)擔(dān)。這對(duì)于面臨資源稀缺、要求高度響應(yīng)性的應(yīng)用環(huán)境尤為重要。

在高并發(fā)場(chǎng)景下,對(duì)象池更是發(fā)揮了巨大的作用。并發(fā)環(huán)境中,多個(gè)線程或協(xié)程可以從對(duì)象池中獲取對(duì)象,實(shí)現(xiàn)了資源的共享與協(xié)同,有效提高了程序的并發(fā)性能。同時(shí),對(duì)象池還有助于避免由于頻繁的資源分配導(dǎo)致的內(nèi)存碎片問題,優(yōu)化了內(nèi)存空間的使用,使系統(tǒng)更為穩(wěn)定。

在一個(gè)長時(shí)間運(yùn)行的高性能應(yīng)用中,對(duì)象池的靈活性也是其優(yōu)勢(shì)之一。通過動(dòng)態(tài)調(diào)整對(duì)象池的大小,可以根據(jù)實(shí)際需求進(jìn)行優(yōu)化,確保在不同負(fù)載下仍然能夠保持高效的性能表現(xiàn)。綜合而言,對(duì)象池技術(shù)的采用在高性能編程中不僅是一項(xiàng)優(yōu)秀的實(shí)踐,更是為了應(yīng)對(duì)復(fù)雜、高并發(fā)應(yīng)用場(chǎng)景的必備利器。

sync.Pool實(shí)現(xiàn)對(duì)象池

首先,Go語言自帶了 sync.Pool 實(shí)現(xiàn)。sync.Pool 是 Go 語言標(biāo)準(zhǔn)庫中的一個(gè)對(duì)象池實(shí)現(xiàn),用于提高對(duì)象的重用性,減少對(duì)象的創(chuàng)建和垃圾回收的開銷。sync.Pool 在并發(fā)環(huán)境中特別有用,它能夠顯著提升程序性能。

以下是 sync.Pool 的主要特點(diǎn)和使用方式:

  • 對(duì)象池的創(chuàng)建: 通過 sync.Pool,你可以創(chuàng)建一個(gè)對(duì)象池,用于存儲(chǔ)和管理特定類型的對(duì)象。對(duì)象池中的對(duì)象在被取出后可以被重用,而不是每次都重新創(chuàng)建。
  • Get 和 Put 操作: 使用 sync.Pool 的 Get 方法可以從對(duì)象池中獲取一個(gè)對(duì)象,而 Put 方法則用于將對(duì)象放回對(duì)象池。這兩個(gè)操作是并發(fā)安全的,可以被多個(gè) goroutine 同時(shí)使用。
  • 對(duì)象的生命周期: sync.Pool 并不保證對(duì)象會(huì)一直存在,對(duì)象可能會(huì)在任意時(shí)刻被垃圾回收。因此,不能假設(shè)對(duì)象在調(diào)用 Get 后一直有效,需要重新初始化。
  • 適用于短生命周期對(duì)象: sync.Pool 特別適用于管理短生命周期的對(duì)象,例如臨時(shí)對(duì)象、緩存對(duì)象等。對(duì)于長時(shí)間生存的對(duì)象,sync.Pool 的優(yōu)勢(shì)可能會(huì)減弱。

下面是我用 sync.Pool 創(chuàng)建對(duì)象池的演示Demo:

package pool  
  
import (  
    "funtester/ftool"  
    "log"    "sync"    "testing")  
  
// PooledObject  
// @Description: 對(duì)象池對(duì)象  
type PooledObject struct {  
    Name    string  
    Age     int  
    Address string  
}  
  
// NewObject  
//  
//  @Description: 創(chuàng)建對(duì)象  
//  @return *PooledObject  
func NewObject() *PooledObject {  
    log.Println("創(chuàng)建對(duì)象")  
    return &PooledObject{  
       Name:    "",  
       Age:     0,  
       Address: "",  
    }    
}  
  
// Reset  
//  
//  @Description: 重置對(duì)象  
//  @receiver m 對(duì)象  
func (m *PooledObject) Reset() {  
    m.Name = ""  
    m.Age = 0  
    m.Address = ""  
    log.Println("重置對(duì)象")  
}  
  
type ObjectPool struct {  
    ObjPool sync.Pool  
    Name    string  
}  
  
// NewPool  
//  
//  @Description: 創(chuàng)建對(duì)象池  
//  @param size 對(duì)象池大小  
//  @return *ObjectPool 對(duì)象類型  
func NewPool(size int) *ObjectPool {  
    return &ObjectPool{  
       Name:    "FunTester測(cè)試",  
       ObjPool: sync.Pool{New: func() interface{} { return NewObject() }},  
    }  
}  
  
// Get  
//  
//  @Description: 獲取對(duì)象  
//  @receiver p 對(duì)象池  
//  @return *PooledObject 對(duì)象  
func (p *ObjectPool) Get() *PooledObject {  
    return p.ObjPool.Get().(*PooledObject)  
}  
  
// Back  
//  
//  @Description: 回收對(duì)象  
//  @receiver p 對(duì)象池  
//  @param obj 回收的對(duì)象  
func (p *ObjectPool) Back(obj *PooledObject) {  
    obj.Reset()  
    p.ObjPool.Put(obj)  
}  
  
func TestPool1(t *testing.T) {  
    pool := NewPool(1)  
    get := pool.Get()  
    get.Name = "FunTester"  
    get.Age = 18  
    get.Address = "地球"  
    log.Printf("%T %s", get, ftool.ToString(get))  
    pool.Back(get)  
    get2 := pool.Get()  
    log.Printf("%T %s", get, ftool.ToString(get2))  
}

控制臺(tái)打?。?/p>

=== RUN   TestPool1
2024/01/19 23:05:17 創(chuàng)建對(duì)象
2024/01/19 23:05:17 *pool.PooledObject &{FunTester 18 地球}
2024/01/19 23:05:17 重置對(duì)象
2024/01/19 23:05:17 *pool.PooledObject &{ 0 }
--- PASS: TestPool1 (0.00s)
PASS

PS:這里不建議使用并發(fā)安全類來控制對(duì)象池?cái)?shù)量,因?yàn)樵谑褂眠^程中,對(duì)象池中的對(duì)象可能會(huì)被垃圾回收機(jī)制銷毀,會(huì)導(dǎo)致額外的未知問題。但是可以使用并發(fā)安全類進(jìn)行借出和歸還的計(jì)數(shù),從而實(shí)現(xiàn)對(duì)最大可借數(shù)量的限制,不過略微復(fù)雜,并不適用于性能測(cè)試中的場(chǎng)景。

chan實(shí)現(xiàn)對(duì)象池

我們還可以借助 chan 來實(shí)現(xiàn)對(duì)象池??梢园?chan 用來存儲(chǔ)對(duì)象,借和還都只是從 chan 中取出和放入對(duì)象。這樣做的好處如下幾點(diǎn):

  • 并發(fā)安全。由于 chan 操作是原子性的,所以整個(gè)的借還過程都是并發(fā)安全的。
  • 數(shù)量可控??梢酝ㄟ^設(shè)置 chan 的容量控制對(duì)象總量。
  • 阻塞處理。當(dāng)無足夠?qū)ο蠡蛘哌^多對(duì)象時(shí),可以阻塞以便進(jìn)行邏輯處理。
  • 可讀性好。使用 chan 實(shí)現(xiàn)對(duì)象池,代碼清晰易讀,便于維護(hù)。

下面是我的實(shí)現(xiàn)Demo:

package pool  
  
import (  
    "log"  
    "reflect"    "testing")
  
type ObjectPool2 struct {  
    objects chan *PooledObject  
    Name    string  
}  
  
// NewPool  
//  
//  @Description: 創(chuàng)建對(duì)象池  
//  @param size 對(duì)象池大小  
//  @return *ObjectPool 對(duì)象類型  
func NewPool2(size int) *ObjectPool2 {  
    return &ObjectPool2{  
       objects: make(chan *PooledObject, size),  
       Name:    "FunTester測(cè)試",  
    }  
}  
  
// Get  
//  
//  @Description: 獲取對(duì)象  
//  @receiver p 對(duì)象池  
//  @return *PooledObject 對(duì)象  
func (p *ObjectPool2) Get2() *PooledObject {  
    select {  
    case obj := <-p.objects:  
       return obj  
    default:  
       log.Println("額外創(chuàng)建對(duì)象")  
       return NewObject()  
    }  
}  
  
// Back  
//  
//  @Description: 回收對(duì)象  
//  @receiver p 對(duì)象池  
//  @param obj 回收的對(duì)象  
func (p *ObjectPool2) Back(obj *PooledObject) {  
    obj.Reset()  
    select {  
    case p.objects <- obj:  
    default:  
       obj = nil  
       log.Println("丟棄對(duì)象")  
    }  
}  
  
func TestPool2(t *testing.T) {  
    pool := NewPool2(1)  
    get := pool.Get2()  
    object := pool.Get2()  
    log.Printf("%T", get)  
    log.Println(reflect.TypeOf(get))  
    pool.Back(get)  
    pool.Back(object)  
  
}

控制臺(tái)輸出:

=== RUN   TestPool2
2024/01/19 23:19:42 額外創(chuàng)建對(duì)象
2024/01/19 23:19:42 創(chuàng)建對(duì)象
2024/01/19 23:19:42 額外創(chuàng)建對(duì)象
2024/01/19 23:19:42 創(chuàng)建對(duì)象
2024/01/19 23:19:42 *pool.PooledObject
2024/01/19 23:19:42 *pool.PooledObject
2024/01/19 23:19:42 重置對(duì)象
2024/01/19 23:19:42 重置對(duì)象
2024/01/19 23:19:42 丟棄對(duì)象
--- PASS: TestPool2 (0.00s)
PASS

雖然chan實(shí)現(xiàn)對(duì)象池在某些場(chǎng)景下具有優(yōu)勢(shì),但在其他情況下可能不是最佳選擇。在一些性能要求較高的場(chǎng)景中,使用更為專業(yè)的對(duì)象池庫或者手動(dòng)管理對(duì)象池的方式可能更為靈活和高效。

第三方庫

在Go語言中,有一些第三方庫專門用于實(shí)現(xiàn)對(duì)象池,它們提供了更復(fù)雜、靈活、高效的對(duì)象池管理機(jī)制。以下是一些常用的第三方庫,用于實(shí)現(xiàn)對(duì)象池:

github.com/fatih/pool:

GitHub 地址:  fatih/pool
該庫提供了一個(gè)通用的對(duì)象池實(shí)現(xiàn),支持對(duì)任意對(duì)象的池化。它允許你自定義對(duì)象的創(chuàng)建、銷毀和驗(yàn)證邏輯,非常靈活。

github.com/panjf2000/ants/v2:

GitHub 地址:  panjf2000/ants
該庫是一個(gè)高性能的 goroutine 池,適用于需要并發(fā)執(zhí)行任務(wù)的場(chǎng)景。雖然主要關(guān)注 goroutine 池,但也可以用作通用的對(duì)象池。

github.com/jolestar/go-commons-pool:

GitHub 地址:  jolestar/go-commons-pool
該庫是一個(gè)通用的對(duì)象池實(shí)現(xiàn),支持池化各種類型的對(duì)象。它提供了豐富的配置選項(xiàng),允許你自定義對(duì)象創(chuàng)建、銷毀和驗(yàn)證的邏輯。

github.com/avast/retry-go:

GitHub 地址:  avast/retry-go
該庫提供了一個(gè)靈活的對(duì)象池實(shí)現(xiàn),支持對(duì)獲取和釋放對(duì)象的重試策略。適用于需要在獲取對(duì)象時(shí)進(jìn)行重試的情況。

這些庫提供了比標(biāo)準(zhǔn)庫的 sync.Pool 和 chan實(shí)現(xiàn) 更為復(fù)雜且靈活,可以根據(jù)具體需求進(jìn)行選擇。后面有機(jī)會(huì)我會(huì)選擇其中一兩種學(xué)習(xí)實(shí)踐,然后分享。

到此這篇關(guān)于深入理解Go語言對(duì)象池的文章就介紹到這了,更多相關(guān)Go語言對(duì)象池內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang文件操作之讀取與寫入方法全攻略

    Golang文件操作之讀取與寫入方法全攻略

    本文詳細(xì)介紹了在Go語言中進(jìn)行文件操作的方法,包括文件的創(chuàng)建、打開、讀取、寫入和關(guān)閉等,解析了使用os、bufio和io包進(jìn)行高效文件操作的技巧,并提供了錯(cuò)誤處理與性能優(yōu)化的建議,以幫助開發(fā)者有效管理文件資源并提升應(yīng)用性能,需要的朋友可以參考下
    2024-11-11
  • go slice不同初始化方式性能及數(shù)組比較詳解

    go slice不同初始化方式性能及數(shù)組比較詳解

    這篇文章主要為大家介紹了go slice不同初始化方式性能及數(shù)組比較示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • 淺析Go語言如何在select語句中實(shí)現(xiàn)優(yōu)先級(jí)

    淺析Go語言如何在select語句中實(shí)現(xiàn)優(yōu)先級(jí)

    這篇文章主要為大家詳細(xì)介紹了Go語言如何在select語句中實(shí)現(xiàn)優(yōu)先級(jí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-03-03
  • go字符串拼接方式及性能比拼小結(jié)

    go字符串拼接方式及性能比拼小結(jié)

    在golang中字符串的拼接方式有多種,本文將會(huì)介紹比較常用的幾種方式,并且對(duì)各種方式進(jìn)行壓測(cè),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • golang return省略用法說明

    golang return省略用法說明

    這篇文章主要介紹了golang return省略用法說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang?int函數(shù)使用實(shí)例全面教程

    Golang?int函數(shù)使用實(shí)例全面教程

    這篇文章主要為大家介紹了Golang?int函數(shù)使用實(shí)例全面教程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • 阿里云go開發(fā)環(huán)境搭建過程

    阿里云go開發(fā)環(huán)境搭建過程

    這篇文章主要介紹了阿里云go開發(fā)環(huán)境搭建過程,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • GO的range具體使用

    GO的range具體使用

    GO語言的for…range 能做什么呢?golang的for…range是go 身的語法,可以用來遍歷數(shù)據(jù)結(jié)構(gòu),本文就詳細(xì)的來介紹一下具體使用,感興趣的可以了解一下
    2021-10-10
  • Golang的md5 hash計(jì)算操作

    Golang的md5 hash計(jì)算操作

    這篇文章主要介紹了Golang的md5 hash計(jì)算操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go使用Protocol?Buffers在數(shù)據(jù)序列化的優(yōu)勢(shì)示例詳解

    Go使用Protocol?Buffers在數(shù)據(jù)序列化的優(yōu)勢(shì)示例詳解

    這篇文章主要為大家介紹了Go使用Protocol?Buffers在數(shù)據(jù)序列化的優(yōu)勢(shì)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11

最新評(píng)論