読者です 読者をやめる 読者になる 読者になる

Go言語入門 / golang入門 sync.Poolの使い方

プログラミング Go言語 / golang Go言語入門 / golang 入門

f:id:nasust:20161122141513p:plain The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/) CC3.0

こんにちはnasustです。
今回はsync.Poolの使い方を解説します。

Go言語で高速化する為には、なるべくメモリのアロケーションを発生させない様にします。 Go言語では、オブジェクトのメモリプールの機能が用意されています。

sync.Poolはスレッドセーフなメモリプールです。sync.Poolを使用する事によって高速化することができます。

使い方は簡単で、sync.Pool構造体を生成する時のNewフィールドにオブジェクト生成の関数を指定します。必要時にNewの関数が呼ばれます。

あるスレッドで、Getメソッドを呼び、もしプールに無かったらNewの関数でオブジェクトを生成します。そしてGetでオブジェクトを取得します。もしプールにオブジェクトが在れば、そのオブジェクトを返します。使い終わったらPutメソッドでプールに戻します。

これの繰り返しでオブジェクトをリサイクルすることでメモリのアロケーションを最小限にして高速化することができます。

スレッドセーフですので、スレッド間でメモリプールする事ができます。

WEB APIなどでhttpサーバを実装した時の高速化する場合に使用すると非常に効果的です。

サンプルプログラム

package main

import (
    "fmt"
    "runtime"
    "sync"
    "time"
)

type Hoge struct {
    name  string
    value int
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())

    pool := sync.Pool{
        New: func() interface{} {
            return &Hoge{
                name:  "hoge",
                value: 0,
            }
        },
    }
    wg := &sync.WaitGroup{}

    poolFunc := func() {
        hoge := pool.Get().(*Hoge)
        if hoge.value == 0 {
            fmt.Println("New")
        } else {
            fmt.Println("Cache")
        }
        hoge.value += 1
        pool.Put(hoge)
        time.Sleep(1 * time.Microsecond)
        wg.Done()
    }

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go poolFunc()
    }

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go poolFunc()
    }

    wg.Wait()
    fmt.Println("End")
}

結果

New
New
Cache
Cache
Cache
Cache
New
Cache
Cache
Cache
Cache
Cache
Cache
Cache
Cache
Cache
Cache
Cache
Cache
Cache
END

Go言語 / golang 入門 目次に戻る

広告を非表示にする