Maison > développement back-end > Golang > Pourquoi la reconversion de « interface{} » en tranche entraîne-t-elle une allocation de tas supplémentaire ?

Pourquoi la reconversion de « interface{} » en tranche entraîne-t-elle une allocation de tas supplémentaire ?

PHPz
Libérer: 2024-02-12 22:15:09
avant
804 Les gens l'ont consulté

Pourquoi la reconversion de « interface{} » en tranche entraîne-t-elle une allocation de tas supplémentaire ?

En PHP, lors de la conversion du type "interface{}" en type slice, cela entraînera une allocation de tas supplémentaire. En effet, en PHP, une interface est un type de données abstrait et une tranche est un type de tableau dynamique. Lorsque nous convertissons un type d'interface en type slice, PHP doit allouer de l'espace mémoire supplémentaire au type slice afin de stocker les éléments de la tranche. Cette opération d'allocation de tas supplémentaire entraînera une surcharge de mémoire supplémentaire, ce qui peut entraîner des problèmes de performances pour certaines applications sensibles à la mémoire. Par conséquent, lors de la conversion de type, nous devons prêter attention à ce problème et essayer d'éviter une allocation de tas supplémentaire inutile.

Contenu des questions

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)
    }
}
Copier après la connexion

Ce benchmark donne le résultat suivant dans go1.19.5.

benchmarkpool
benchmarkpool-10        47578498            24.47 ns/op       24 b/op          1 allocs/op
Copier après la connexion

Les choses semblent différentes lors de l'utilisation de *[]byte :

func benchmarkpool(b *testing.b) {
    b.reportallocs()
    p := sync.pool{new: func() interface{} {
        bts := make([]byte, 1024)
        return &bts
    }}
    for i := 0; i < b.n; i++ {
        bts := p.get().(*[]byte)
        p.put(bts)
    }
}
Copier après la connexion
BenchmarkPool
BenchmarkPool-10        142008002            8.581 ns/op           0 B/op          0 allocs/op
Copier après la connexion

Il semble que la reconversion de interface{} en tranche entraîne des allocations de tas supplémentaires.

Pourquoi Go a-t-il besoin de cette allocation supplémentaire ? Quelles sont les considérations de conception derrière cela ?

Solution

Ce n'est pas any[]byte 的转换,而是 []byteany 的转换。 p.Put(bts) 将参数 bts 隐式转换为 any,然后再将其传递给 (*sync.Pool).Put qui provoque l'allocation. L'interface de GoGC 1.19 est implémentée sous la forme d'une paire de pointeurs, l'un pointant vers les métadonnées de type et l'autre vers l'objet réel. Dans ce cas, le deuxième pointeur est échappé vers le pool, provoquant l'allocation de l'objet slice. Cela s'applique non seulement aux types de tranches, mais également à tout autre type non pointeur.

Pour les pointeurs, tels que *[]byte,编译器会执行优化,将其值直接放入 iface 结构中,从而在转换为接口时删除 *[]byte, le compilateur effectue une optimisation en plaçant sa valeur directement dans la structure iface, supprimant ainsi l'allocation de l'instance

lors de la conversion en interface. Par conséquent, il est généralement recommandé de placer des pointeurs dans un pool plutôt que dans la structure elle-même. 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal