Maison  >  Article  >  développement back-end  >  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
PHPzavant
2024-02-12 22:15:09782parcourir

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)
    }
}

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

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)
    }
}
BenchmarkPool
BenchmarkPool-10        142008002            8.581 ns/op           0 B/op          0 allocs/op

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer