
[ad_1]
Quand et comment utiliser le package d’exécution Go
Le feu vert Durée package et son sous-package déboguer sont très pratiques pour gérer les métriques, le débogage, la goroutine et le GC, ce qui peut également faciliter notre compréhension de l’implémentation de Go lui-même.
Cet article vise à répondre aux cinq « Comment faire » suivants avec quelques cas d’utilisation et des exemples de codes.
- Comment utiliser les variables d’environnement exposées par les packages d’exécution et d’exécution/de débogage
- Comment utiliser les métriques Go exposées par les packages d’exécution et d’exécution/de débogage
- Comment gérer les goroutines avec les packages d’exécution et d’exécution/de débogage
- Comment faire fonctionner GC avec des packages d’exécution et d’exécution/de débogage
- Comment déboguer avec les packages d’exécution et d’exécution/de débogage
Le package d’exécution fournit de nombreuses variables d’environnement intégrées que nous pouvons appeler lors du développement.
Les variables d’environnement les plus courantes sont GOARCH
,GOOS
,GOPATH
,GOROOT,
qui sont pour différentes implémentations basées sur différents systèmes d’exploitation sous-jacents, respectivement. La sortie suivante est la même que celle que nous obtenons en exécutant go env
en CLI.
fmt.Printf(“OS: %s, GOARCH: %s”, runtime.GOOS, runtime.GOARCH)
De plus, il existe des variables d’environnement liées au GC, au débogage et à la trace.
GOGC
définit le pourcentage cible initial de récupération de place et détermine s’il convient de déclencher GC en fonction de la proportion d’objets de récupération restants. Ladebug.SetGCPercent
la fonction modifie ce pourcentage lors de l’exécution et désactive complètement la récupération de place lorsqueGOGC=100. GOGC=off
par défaut.GODEBUG
contrôle les variables de débogage dans le runtime, consistant en un ensemble dename=val
des chaînes séparées par des virgules et des configurations de prise en charge telles queallocfreetrace=1, clobberfree=1
etc. Veuillez vous référer à ce liste pour plus d’informations.GORACE
est utilisé pour configurer le détecteur de course en ajoutant-race
signaler quandbuild
.GOMAXPROCS
limite le nombre de threads du système d’exploitation qui exécutent simultanément du code Go au niveau de l’utilisateur, mais pas le nombre de threads bloqués dans un appel système.GOTRACEBACK
contrôle la quantité de sortie lorsqu’un programme Go échoue en raison d’une exception non gérée ou d’une condition d’exécution inattendue. Par défaut, la trace de la pile de la goroutine actuelle sera imprimée lorsqu’une erreur se produit, en ignorant la fonction d’exécution interne et en sortant avecexit 2
.
Alors que les traces de pile pour toutes les goroutines sont imprimées lorsqu’une erreur se produit s’il n’y a pas de goroutine actuelle, ou si l’échec est interne à l’exécution, les valeurs de support, y comprisnone(0)
,all(1)
,system(2)
,single
,crash
parmi lesquelsall
etsystem
sont les plus couramment utilisés.all
consiste à ajouter des informations de trace de pile pour toutes les goroutines créées par l’utilisateur. Etsystem
est similaire mais ajoute des informations de trace de pile pour les fonctions d’exécution et affiche les goroutines créées à l’intérieur de l’exécution.
Goroutine est l’une des principales fonctionnalités de Go. Généralement, on utilise go func()
pour créer des goroutines mais se soucient moins de la planification et de l’exécution ultérieures tant que le résultat final est correct.
Cependant, en tant que développeurs Go de haut niveau, nous devons connaître la planification des goroutines, comme le modèle GMP, la taille de la pile que chaque goroutine peut utiliser, le nombre maximum de goroutines pouvant être exécutées en parallèle, etc. Celles-ci peuvent, pour dans une certaine mesure, être affecté par les méthodes des packages d’exécution.
runtime.GOMAXPROCS(n)
runtime.GOMAXPROCS(n)
définit le nombre maximum de goroutines exécutées en parallèle dans un processus (P
), qui est identique à NumCPU()
et 256 au maximum. Mais la modification de cette valeur déclenchera STW (Stop the World), nous devons donc éviter de l’appeler fréquemment. Cette méthode est principalement utilisée pour s’assurer GOMAXPROCS()
est inférieur aux pools de travailleurs lorsque le nombre de travailleurs (ou waitGroups
) dans le pool de nœuds de calcul est configurable.
runtime.Gosched
La goroutine qui appelle runtime.Gosched()
sera suspendu par runtime.Gosched()
réinitialiser commeRunnable
et mis dans la file d’attente G exécutable du planificateur. Il peut fonctionner en combinaison avec le pool de travailleurs exécutables pour surveiller le nombre de tâches en cours d’exécution et modifier la goroutine actuelle en Runnable
état à exécuter la prochaine fois une fois que le nombre de tâches dépasse la taille du pool de threads. Un exemple parfait est le suivant :
runtime.Goexit
runtime.Goexit()
termine l’exécution de la goroutine qui l’appelle immédiatement après avoir terminé l’exécution de la defer
déclaration dans cette goroutine, mais n’affecte pas les autres goroutines. Dans la gestion des erreurs, runtime.Goexit()
peut conserver l’exception dans la goroutine actuelle et s’assurer que l’ensemble du programme Go est dans un état régulier.
runtime.LockOSThread et runtime.UnlockOSThread
runtime.LockOSThread()
verrouille la goroutine l’appelle avec le M
qui le dirige, tandis queruntime.UnlockOSThread()
déverrouille la serrure. Gardez à l’esprit ce qui suit :
- Appel
runtime.LockOSThread()
plusieurs fois ne causeront aucun problème, mais le dernier appel sera enregistré. - L’appel de
runtime.UnlockOSThread()
ne sera pas affecté même si aucun appel deruntime.LockOSThread()
est fait.
L’utiliser avant d’appeler des programmes non Go, tels que le code C ou les services du système d’exploitation, permet à la goroutine associée de découvrir l’erreur lorsque le programme échoue. Dans le code de Postman, vous pouvez trouver de nombreux exemples lors de l’accès à un autre système d’exploitation. Par exemple:
runtime.LockOSThread()
defer runtime.UnlockOSThread()// Call unix functions(non-Go)
fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_DGRAM, 0)
if err != nil {
return false, -1, err
}
r, w := os.NewFile(uintptr(fds[0]), "sync host"), os.NewFile(uintptr(fds[1]), "sync child")
En outre, il existe également des méthodes dans le package runtime/debug qui peuvent affecter le fonctionnement des goroutines.
debug.SetMaxStack
debug.SetMaxStack()
limite la taille maximale de l’espace de pile qu’une seule goroutine peut demander.
debug.SetMaxThreads
debug.SetMaxThreads()
définit le nombre de threads du noyau (M
) utilisé à l’exécution. Cette méthode est généralement appelée avec les paramètres de taille de file d’attente et de pool de nœuds de calcul.
Il existe deux types de données dans les packages d’exécution et d’exécution/de débogage.
profiles
y comprisBlockProfile
,MemProfile
,GoroutineProfile
etc., toutes les encapsulations des informations de la pile actuelle peuvent être obtenues avec lepprof
outil et ne sont pas recommandés par les responsables de Go pour les appels directs dans le code.stats
, des données directement lisibles, qui sont très intuitives. Ils sont généralement utilisés pour l’analyse directe en ligne du programme en cours.
NumCPU, NumCgoCall, NumGoroutine
Les trois méthodes renvoient directement des données en temps réel. Mais à noter que runtime.NumGoroutine()
renverra le nombre de goroutines dans l’état spécifique après son appel. L’état spécifique signifie ici Grunnable\Gruning\Gsyscall\Gwaition,
dans lequel les goroutines sont considérées comme actives ou programmées.
ReadMemStats, ReadGCStats
ReadMemStats()
lit la mémoire actuelle, y compris le tas occupé, le tas libéré, la pile occupée, l’état du cache, le nombre de GC, l’heure du prochain GC, etc. Imprimez-le pour voir.
ReadGCStats()
se trouve dans le package de débogage, et une partie des données qu’il a fournies est dupliquée avec READMemStats
mais il se concentre entièrement sur GC, comme LastGc
, NumGc
, Pause
, PauseTotal
etc. Par exemple, GCStats est appliqué dans le code de Prometheus.
Nous pouvons également ajouter des API pour renvoyer ces données lors du développement des services du serveur Go afin de faciliter le débogage en ligne.
Go encapsule si bien GC que les programmes fonctionnent efficacement même si des milliers de goroutines s’exécutent simultanément, et l’intervention de l’utilisateur est à peine nécessaire. Mais le package d’exécution fournit certaines fonctions pour compenser les lacunes du GC par défaut.
runtime.GC
runtime.GC()
effectue un GC obligatoire en exécution, différent du GC non obligatoire déclenché par GOGC
configuration.
Habituellement, nous déclenchons GC manuellement avant le profilage, comme la façon dont nous le faisons dans Kubernetes. Voici le code :
func flushProfiling() error {
switch profileName {
case "none":
return nil
case "cpu":
pprof.StopCPUProfile()
case "heap":
runtime.GC()
fallthrough
...
}
runtime.SetFinalizer
SetFinalizer()
intercepte le GC d’objets spécifiques et ajoute des opérations de nettoyage supplémentaires avec Finalizer
comme le Finaliseur dans le package crypto de Go, appelle C pour effacer les objets.
runtime.KeepAlive
KeepAlive
marque son argument comme actuellement accessible. Cela garantit que l’objet n’est pas libéré et que son finaliseur n’est pas exécuté avant le point du programme oùKeepAlive
est appelé.
runtime.SetFinalizer(p, func(p *File) { syscall.Close(p.d) })
var buf [10]byte
n, err := syscall.Read(p.d, buf[:])
// Ensure p is not finalized until Read returns.
runtime.KeepAlive(p)
Certains objets lourds comme les descripteurs de fichiers et les files d’attente vides utilisent KeepAlive avant le déclenchement de GC, comme les fenêtres os.File
objet obtenu dans Kubernetes.
func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
bi := &FileBasicInfo{}
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
}
runtime.KeepAlive(f)
return bi, nil
}
Nous pouvons également obtenir l’impression d’exception et les informations de pile avec le package d’exécution une fois qu’une erreur se produit.
runtime.Caller
Caller()
reflète le numéro de ligne du fichier où se trouvent le chemin absolu et l’instruction d’un cadre de pile. skip
est le nombre de cadres de pile à monter avec 0
identifier le Caller
. Et pour imprimer toutes les informations de la pile, vous pouvez directement utiliser debug.PrintStack()
.
L’exemple ci-dessus utilise également leFuncForPC
fonction, qui est souvent utilisée pour
- obtenir le nom de la fonction,
.Name()
- obtenir la ligne de fichier de la fonction,
.FileLine()
Ces deux méthodes sont les plus couramment utilisées pour obtenir plus d’informations lors de la personnalisation du journal d’impression, telles que le rôle SetV
fonction joue dans le klog
forfait.
Trace
Le package d’exécution prend également en charge l’impression trace
informations, en utilisant leStartTrace()
et StopTrace()
méthodes pour démarrer et terminer la trace, etReadTrace()
pour lire les informations.
Go lui-même utilise ces fonctions pour trace les activités d’exécution.
Cet article résume la plupart des méthodes du package d’exécution, parmi lesquelles la goroutine et les méthodes liées aux métriques sont très utiles dans le développement d’outils Go. Ils offrent des fonctionnalités telles que la gestion de l’utilisation de la mémoire de Go à un niveau supérieur, la surveillance des performances et la protection de la santé du programme. Et ceux liés au débogage aident à créer la prise en charge par défaut des invites d’erreur inattendues, ce qui peut considérablement accélérer la localisation de nos bogues.
Merci d’avoir lu!
[ad_2]
Télécharger ici