Heim > Backend-Entwicklung > Golang > Warum führt die Rückkonvertierung von „interface{}' in ein Slice zu einer zusätzlichen Heap-Zuweisung?

Warum führt die Rückkonvertierung von „interface{}' in ein Slice zu einer zusätzlichen Heap-Zuweisung?

PHPz
Freigeben: 2024-02-12 22:15:09
nach vorne
788 Leute haben es durchsucht

Warum führt die Rückkonvertierung von „interface{} in ein Slice zu einer zusätzlichen Heap-Zuweisung?

In PHP führt die Konvertierung des Typs „interface{}“ in den Slice-Typ zu einer zusätzlichen Heap-Zuweisung. Dies liegt daran, dass in PHP eine Schnittstelle ein abstrakter Datentyp und ein Slice ein dynamischer Array-Typ ist. Wenn wir einen Schnittstellentyp in einen Slice-Typ konvertieren, muss PHP dem Slice-Typ zusätzlichen Speicherplatz zuweisen, um die Elemente des Slice zu speichern. Dieser zusätzliche Heap-Zuweisungsvorgang verursacht zusätzlichen Speicheraufwand, was bei einigen speicherempfindlichen Anwendungen zu Leistungsproblemen führen kann. Daher sollten wir bei der Typkonvertierung auf dieses Problem achten und versuchen, unnötige zusätzliche Heap-Zuweisungen zu vermeiden.

Frageninhalt

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)
    }
}
Nach dem Login kopieren

Dieser Benchmark liefert in go1.19.5 die folgende Ausgabe.

benchmarkpool
benchmarkpool-10        47578498            24.47 ns/op       24 b/op          1 allocs/op
Nach dem Login kopieren

Anders sieht es bei der Verwendung von *[]byte:

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

Es scheint, dass die Konvertierung interface{} zurück in einen Slice zu zusätzlichen Heap-Zuweisungen führt.

Warum benötigt go diese zusätzliche Zuweisung? Welche Designüberlegungen stecken dahinter?

Lösung

Es ist nicht any[]byte 的转换,而是 []byteany 的转换。 p.Put(bts) 将参数 bts 隐式转换为 any,然后再将其传递给 (*sync.Pool).Put, das die Zuordnung verursacht. Die Schnittstelle in GoGC 1.19 ist als Zeigerpaar implementiert, von denen einer auf die Typmetadaten und einer auf das eigentliche Objekt zeigt. In diesem Fall wird der zweite Zeiger in den Pool maskiert, wodurch das Slice-Objekt zugewiesen wird. Dies gilt nicht nur für Slice-Typen, sondern auch für alle anderen Nicht-Zeiger-Typen.

Für Zeiger wie *[]byte,编译器会执行优化,将其值直接放入 iface 结构中,从而在转换为接口时删除 *[]byte führt der Compiler eine Optimierung durch, indem er seinen Wert direkt in die iface-Struktur einfügt, wodurch die Zuordnung der

-Instanz bei der Konvertierung in eine Schnittstelle entfernt wird. Daher wird im Allgemeinen empfohlen, Zeiger in einen Pool und nicht in die Struktur selbst zu setzen. 🎜

Das obige ist der detaillierte Inhalt vonWarum führt die Rückkonvertierung von „interface{}' in ein Slice zu einer zusätzlichen Heap-Zuweisung?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage