「interface{}」をスライスに変換すると、余分なヒープ割り当てが発生するのはなぜですか?

PHPz
リリース: 2024-02-12 22:15:09
転載
761 人が閲覧しました

「interface{}」をスライスに変換すると、余分なヒープ割り当てが発生するのはなぜですか?

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 サイトの他の関連記事を参照してください。

関連ラベル:
ソース:stackoverflow.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!