Heim > Backend-Entwicklung > Golang > Das Go-Programm ist zu groß. Können wir eine verzögerte Initialisierung verwenden?

Das Go-Programm ist zu groß. Können wir eine verzögerte Initialisierung verwenden?

Freigeben: 2023-08-04 17:23:53
nach vorne
838 Leute haben es durchsucht


Während sich das Unternehmen weiterentwickelt, sind die meisten von ihnen am Anfang große Einheiten, und die Transformation erfolgt langsam. Ein Lager wird länger als zehn Jahre genutzt, und die Größe des Lagers ist im Grunde ein Prozess der kontinuierlichen Steigerung.

Eine der Auswirkungen ist, dass die Größe der gepackten Anwendung immer größer wird und ich nicht weiß, wo sie verwendet wird ... Der Vorschlag, der heute besprochen wird „Vorschlag: Sprache: Lazy-Init-Importe nach möglicherweise Import ohne Nebenwirkungen [1]“ hängt damit zusammen.

Vorschlag

Hintergrund

Beobachten wir einen sehr einfachen Go-Code und studieren ihn. Der folgende Code:

package main

import _ "crypto/x509"

func main() {}
Nach dem Login kopieren

Dieses Go-Programm hat nur 3 Codezeilen und sieht nach nichts aus. Ist das tatsächlich der Fall?

Wir können den folgenden Befehl ausführen, um den Initialisierungsprozess zu sehen:

$ go build --ldflags=--dumpdep main.go 2>&1 | grep inittask
Nach dem Login kopieren

Ausgabeergebnis:

runtime.main -> runtime..inittask
runtime.main -> main..inittask
main..inittask -> crypto/x509..inittask
crypto/x509..inittask -> bytes..inittask
crypto/x509..inittask -> crypto/sha256..inittask
crypto/x509..inittask -> encoding/pem..inittask
crypto/x509..inittask -> errors..inittask
crypto/x509..inittask -> sync..inittask
crypto/x509..inittask -> crypto/aes..inittask
crypto/x509..inittask -> crypto/cipher..inittask
crypto/x509..inittask -> crypto/des..inittask
...
context..inittask -> context.init.0
vendor/golang.org/x/net/dns/dnsmessage..inittask -> vendor/golang.org/x/net/dns/dnsmessage.init
vendor/golang.org/x/net/route..inittask -> vendor/golang.org/x/net/route.init
vendor/golang.org/x/net/route..inittask -> vendor/golang.org/x/net/route.init.0
...
Nach dem Login kopieren

Dieses Programm initialisiert tatsächlich viele Softwarepakete (Standardbibliotheken, Pakete von Drittanbietern usw.). Dadurch ändert sich die Paketgröße von standardmäßig 1,3 MB auf 2,3 MB.

Ab einem gewissen Ausmaß glaubt jeder, dass diese Auswirkungen sehr teuer sind. Denn Sie sehen, dass das Go-Programm mit nur 3 Zeilen nichts Wesentliches bewirkt.

Programme, die empfindlich auf die Startleistung reagieren, werden mit der Zeit auch in einen Teufelskreis geraten und der Start wird langsamer als normal sein.

Lösung

Wir werden uns die Lösung zusammen mit einem weiteren Vorschlag ansehen „Vorschlag: Spezifikation: Go 2: Manuelle Kontrolle über die Initialisierung importierter Pakete zulassen[2]“.

Die Kernidee besteht darin, eine verzögerte Initialisierung (Lazy Init) einzuführen, die in der Branche auch häufig als Lazy Loading bezeichnet wird. Das heißt, der eigentliche Import erfolgt bei Bedarf und die Initialisierung ist abgeschlossen, wenn das Paket nicht eingeführt wird.

Optimierungsrichtung: Hauptsächlich Hinzufügen verzögerter Initialisierungsdeklarationen nach dem Importieren des Paketpfads, wie z. B. die unten erwähnten Annotationen go:lazyinit oder go:deferred. Warten Sie, bis das Programm tatsächlich verwendet wird, bevor Sie es offiziell initialisieren.

1、go:lazyinit 的例子:

package main

import (
      "crypto/x509" // go:lazyinit
      "fmt"
)

func main() {...}
Nach dem Login kopieren

2、go:deferred 的例子:

package main

import (
    _ "github.com/eddycjy/core" // go:deferred
    _ "github.com/eddycjy/util" // go:deferred
)

func main() {
    if os.Args[1] != "util" {
        // 现在要使用这个包,开始初始化
        core, err := runtime.InitDeferredImport("github.com/some/module/core")
        ...
    }
    ...
}
Nach dem Login kopieren

以此来实现,可以大大提高启动性能。

讨论

实际上在大多数的社区讨论中,对这个提案是又爱又恨。因为它似乎又有合理的诉求,但细思似乎又会发现完全不对劲。

这个提案的背景和解决方案,是治标不治本的。因为根本原因是:许多库滥用了 init 函数,让许多不必要的东西都初始化了。

Das Go-Programm ist zu groß. Können wir eine verzögerte Initialisierung verwenden?

Go 核心开发团队认为让库作者去修复这些库,而不是让 Go 来 “解决” 这些问题。如果支持惰性初始化,也会为这些低质量库的作者提供继续这样做的借口。

似曾相识的感觉

在写这篇文章时,我想起了 Go 的依赖管理(Go modules),其有一个设计是基于语义化版本的规范。

如下图

Das Go-Programm ist zu groß. Können wir eine verzögerte Initialisierung verwenden?

版本格式为 “主版本号.次版本号.修订号”,版本号的递增规则如下:

  • 主版本号:当你做了不兼容的 API 修改。
  • 次版本号:当你做了向下兼容的功能性新增。
  • 修订号:当你做了向下兼容的问题修正。

Go modules 的原意是软件库都遵守这个规范,因此内部会有最小版本选择的逻辑。

也就是一个模块往往依赖着许多其它许许多多的模块,并且不同的模块在依赖时很有可能会出现依赖同一个模块的不同版本,Go 会把版本清单都整理出来,最终得到一个构建清单。

如下图:

Das Go-Programm ist zu groß. Können wir eine verzögerte Initialisierung verwenden?

Sie werden feststellen, dass die endgültige Abhängigkeitsversion wahrscheinlich nicht mit den Erwartungen übereinstimmt, was zu vielen Geschäftsproblemen führt. Das klassischste Problem ist das Kompatibilitätsproblem mit mehreren Versionen von grpc-go, protoc-go usw., unter dem viele Menschen leiden.

Das Design des Go-Teams in diesem Bereich ist relativ ideal und Cao Da hat es auch als eine der sieben Todsünden der Go-Module eingestuft. Die Init-Funktion des Softwarepakets hat viele Probleme mit der zufälligen Initialisierung, was auch ein wenig bekannt ist.

Zusammenfassung

Die Lösung (der Vorschlag) für dieses Problem wird noch diskutiert. Offensichtlich hofft das Go-Team, dass die Autoren der Softwarebibliothek ihren eigenen Code einschränken und nicht zufällig initialisieren können.

Wie wäre es Ihrer Meinung nach mit der Einführung einer verzögerten Initialisierung? Willkommen, um Nachrichten zu hinterlassen und im Kommentarbereich zu diskutieren.

Das obige ist der detaillierte Inhalt vonDas Go-Programm ist zu groß. Können wir eine verzögerte Initialisierung verwenden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:Golang菜鸟
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