PHP では、「interface{}」タイプをスライスタイプに変換すると、追加のヒープ割り当てが発生します。これは、PHP ではインターフェイスが抽象データ型であり、スライスが動的配列型であるためです。インターフェイス型をスライス型に変換すると、PHP はスライスの要素を保存するためにスライス型に追加のメモリ領域を割り当てる必要があります。この追加のヒープ割り当て操作により追加のメモリ オーバーヘッドが発生し、メモリに依存する一部のアプリケーションでパフォーマンスの問題が発生する可能性があります。したがって、型変換を実行するときは、この問題に注意し、不必要な追加のヒープ割り当てを避けるように努める必要があります。
func benchmarkpool(b *testing.b) { b.reportallocs() p := sync.pool{new: func() interface{} { return make([]byte, 1024) }} for i := 0; i < b.n; i++ { bts := p.get().([]byte) p.put(bts) } }
このベンチマークでは、go1.19.5 で次の出力が得られます。
リーリー[]byte
:
interface{}
をスライスに変換し直すと、追加のヒープ割り当てが発生するようです。
なぜ go にはこのような追加の割り当てが必要なのでしょうか?この背後にある設計上の考慮事項は何ですか?
割り当ての原因は、any
から []byte
への変換ではなく、[]byte の変換です。
から any
への変換。 p.Put(bts)
パラメータ bts
を (*sync.Pool).Put
に渡す前に暗黙的に any
に変換します。 GoGC 1.19 のインターフェイスは、1 組のポインターとして実装され、1 つは型メタデータを指し、もう 1 つは実際のオブジェクトを指します。この場合、2 番目のポインターはプールにエスケープされ、スライス オブジェクトが割り当てられます。これはスライス型だけでなく、他の非ポインター型にも当てはまります。
*[]byte
などのポインターの場合、コンパイラはその値を iface
構造体に直接配置する最適化を実行するため、変換時に が削除されます。 *[]byte
インスタンスの割り当て。したがって、一般的には、構造体自体ではなくプールにポインターを入れることをお勧めします。
以上が「interface{}」をスライスに変換すると、余分なヒープ割り当てが発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。