14
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Goで不必要にメモリアロケーションの回数を増やさない方法

Last updated at Posted at 2014-08-31

Goにはガベージコレクションがあるのでプログラマがメモリ管理を意識することは少ない。とはいえ無駄にメモリを割り当てまくるとそれだけメモリアロケータとガベージコレクタが走る回数が増えてプログラムが遅くなってしまう。効率の良いプログラムを書こうと思ったらある程度はどういうふうに値がメモリ上に確保されるのか意識することが必要だ。

メモリシステムへの負荷を下げるにはメモリの量だけではなく回数を減らすことが有効である。Goでは構造体のレイアウトは自分で制御できるし、interior pointer(オブジェクトの内部を指しているポインタ)を取得することもできるので、必要な値をまとめてメモリ上に確保することができる。具体的には次のように行う。

type encoder {
    buf     []byte
    scratch [80]byte
    // その他のフィールド ...
}

func newEncoder() *encoder {
    e := new(encoder)
    e.buf = scratch[:]
    return e
}

encoderという型がbufというフィールドを持っているのだけど、encoderは同時にscratchという80バイトのバッファのフィールドも持っている。new(encoder)は一発でスクラッチバッファを含むencoder全体をアロケートする。bufがだいたい常に80バイト以内に収まるのであれば、それ以上メモリを割り当てる必要はないから、アロケーションは1回だけで済む。encoderにscratchフィールドがなくて、別のnewの呼び出しでbufにメモリを割り当てていたとしたら、newの呼び出しは常に2回になるから、1回で済むのはずいぶんな節約だ。

アロケーションを少なくするというアイデアはいろいろなところで有効である。たとえば結果のスライスの長さをあらかじめ計算することができるなら、結果の長さがどうなるかをまず計算してからきっちり同じキャパシティを持ったスライスを割り当てて、そこに結果をappendしていくほうが、長さ0のスライスにappendしていくよりずっとよい。

14
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?