Table des matières
1. Aperçu de la gestion de la mémoire du langage GO
2. Mécanisme de collecte des ordures et cycle de collecte de mémoire
3. Observer le comportement GC par Gogctrace
3.1 Observer les journaux GC sous des retards courts
3.2 Observez le journal GC sous des retards longs
4. Grande stratégie de gestion des variables de mémoire et malentendus communs
4.1 La signification de l'attribution nulle
4.2 Raisons pour que la mémoire ne soit pas retournée au système d'exploitation immédiatement
4.3 Suggestions pour éviter l'OOM
5. Résumé
Maison développement back-end Golang Analyse approfondie de la gestion de la mémoire du langage GO: comprendre la collecte des ordures et les mécanismes de retour de la mémoire

Analyse approfondie de la gestion de la mémoire du langage GO: comprendre la collecte des ordures et les mécanismes de retour de la mémoire

Sep 30, 2025 am 08:38 AM

Analyse approfondie de la gestion de la mémoire du langage GO: comprendre la collecte des ordures et les mécanismes de retour de la mémoire

Cet article explore le mécanisme de gestion de la mémoire du langage GO en profondeur, en particulier son collecteur de déchets basé sur la marque et le sweep. Nous analyserons la façon dont le GO Runtime déclenche périodiquement GC via Sysmon Goroutine, et introduire l'impact de paramètres clés tels que ForceGCPeriod et Scanvegelimit sur le recyclage de la mémoire. Grâce à la variable GOGCTRACE Environment, les lecteurs apprendront à observer les activités GC, à comprendre le retard dans la mémoire de retour au système d'exploitation à partir de GO Runtime et à maîtriser la pratique professionnelle de la gestion de grandes variables de mémoire, d'éviter les malentendus de gestion de la mémoire communes.

1. Aperçu de la gestion de la mémoire du langage GO

Le langage GO a un mécanisme de gestion automatique intégré de la mémoire, à savoir la collecte des ordures (GC). Contrairement aux langages tels que C / C qui nécessitent une gestion manuelle de la mémoire, les programmeurs GO n'ont généralement pas besoin d'allouer explicitement et de libre mémoire. GO'S GARBAGE Collector utilise l'algorithme Mark-and-Sweep . Le principe de base est: Marquez d'abord tous les objets accessibles (c'est-à-dire toujours utilisés par le programme), puis effacez (recycler) la mémoire occupée par tous les objets non marqués.

Il convient de noter que le GC de Go n'est pas déterministe. Cela signifie que vous ne pouvez pas contrôler exactement quand le GC s'exécute, et vous ne pouvez pas garantir que la mémoire sera retournée au système d'exploitation immédiatement après son recyclage. Le GO Runtime déclenchera GC, le cas échéant, selon sa propre stratégie. Par conséquent, lorsqu'un programme s'exécute, même si certains grands objets ne sont plus référencés, la mémoire qu'il consomme peut ne pas sembler immédiatement être réduite au niveau du système d'exploitation.

2. Mécanisme de collecte des ordures et cycle de collecte de mémoire

Il y a un goroutine appelé Sysmon à l'intérieur du GO Runtime. Il fonctionne en continu tout au long de la vie du programme et est responsable de l'exécution d'une série de tâches d'arrière-plan, y compris des vérifications périodiques et du déclenchement de la collection d'ordures. Sysmon gère GC et le retour de la mémoire avec plusieurs paramètres clés:

  • ForcegcPeriod : Il s'agit d'une variable interne qui définit l'intervalle maximal admissible entre deux collections de déchets forcés. Si aucun GC ne se produit pendant cette période, Sysmon le forcera à tirer une fois. Dans GO 1.0.3, cette valeur est d'environ 2 minutes. Cela signifie que même si l'utilisation de la mémoire du tas n'atteint pas le seuil de déclenchement GC, GC sera appliqué de temps en temps.
  • Scavengelimit : Ce paramètre détermine l'heure maximale où GO Runtime conservera une page de mémoire gratuite (SPAN) avant de retourner la mémoire au système d'exploitation. Les pages de mémoire sont l'unité de base de la gestion de la mémoire GO, et une portée peut contenir plusieurs objets. Lorsque tous les objets d'une portée sont recyclés et que la portée est inactive pendant plus de 5 minutes (environ 5 minutes en GO 1.0.3), GO envisagera seulement de le retourner au système d'exploitation.

Le GO Runtime organise la mémoire en blocs appelés "Span". Une durée se compose d'une série de pages de mémoire continue. Lorsque le programme n'utilise plus tous les objets dans une période, la portée sera marquée comme inactive. Mais il n'est pas immédiatement renvoyé au système d'exploitation, mais est conservé par le GO Runtime pendant une période (contrôlée par Scavengelimit) afin que les allocations de mémoire ultérieures puissent réutiliser ces mémoire allouées mais libres, réduisant ainsi les frais généraux de demandes fréquentes et de retour de la mémoire au système d'exploitation.

3. Observer le comportement GC par Gogctrace

Go fournit un puissant outil de débogage. En définissant la variable d'environnement GOGCTRACE = 1, vous pouvez publier des journaux GC détaillés lorsque le programme est en cours d'exécution, nous aidant à comprendre l'état de santé de GC.

Considérez l'exemple de code suivant qui simule le scénario d'allocation et de "libération" de grands blocs de mémoire:

 package principal

importer (
    "FMT"
    "temps"
)

func main () {
    fmt.println ("Obtenir de la mémoire (première fois)")
    tmp: = make ([] uint32, 100000000) // 400 Mo
    pour kk: = range tmp {
        tmp [kk] = 0
    }
    Time.Sleep (5 * time.second) // Breft Delay FMT.println ("Retour Memory (première fois)")
    tmp = make ([] uint32, 1) // réaffecter de petits tableaux pour faire en sorte que de grands tableaux remplissent les conditions GC tmp = nil // réglées sur nil, et ne se réfèrent pas explicitement à un grand tableau de temps.
    tmp = make ([] uint32, 10000000) // allocation grand tableau à nouveau pour kk: = range tmp {
        tmp [kk] = 0
    }
    Time.Sleep (5 * time.second) // Retour court fmt.println ("Mémoire de retour (deuxième fois)")
    tmp = make ([] uint32, 1)
    tmp = nil
    Time.Sleep (5 * time.second)

    fmt.println ("programme terminé")
}

3.1 Observer les journaux GC sous des retards courts

Exécutez le code ci-dessus sous le retard court par défaut (5 secondes) et définissez GOGCTRACE = 1:

 Gogctrace = 1 allez exécuter votre_program.go

Vous pouvez voir des sorties similaires à celles suivantes (les valeurs spécifiques varieront en fonction de la version GO et de l'environnement système):

 GC1 (1): 0 0 0 ms 0 -> 0 Mo 172 -> 137 (173-36) Objets 0 transfert
Obtenir de la mémoire (première fois)
GC2 (1): 0 0 0 MS 381 -> 381 MB 203 -> 202 (248-46) Objets 0 HANDOFF
mémoire de retour (première fois)
Obtenir de la mémoire (deuxième fois)
mémoire de retour (deuxième fois)
Programme terminé

Comme on peut le voir dans le journal, le GC est tiré (GC2) après la première allocation de grande mémoire, mais la taille du tas rapportée (381 Mo -> 381 Mo) ne change pas de manière significative. Après la mémoire renvoyée, aucun signe de mémoire n'est retourné au système d'exploitation n'a été observé immédiatement. En effet, TMP = NIL rend simplement le grand tableau recyclable, que GC peut avoir marqué comme recyclable, mais en raison du temps de retard court, la Forcegcperiod et Scavengelimit, la mémoire n'a pas été retournée au système d'exploitation. L'utilisation de la mémoire observée au niveau du système d'exploitation peut toujours être élevée, et même "double" dans la deuxième allocation, ce qui peut être dû au fait que le temps d'exécution GO choisit d'étendre le tas au lieu de réutiliser immédiatement la mémoire qui était auparavant marquée comme inactive mais n'est pas encore retournée au système d'exploitation lors de l'allocation de nouveaux grands souvenirs.

3.2 Observez le journal GC sous des retards longs

Pour observer les effets de la ForcegcCeriod et Scangelimit, nous avons changé le temps.

 package principal

importer (
    "FMT"
    "temps"
)

func main () {
    fmt.println ("Obtenir de la mémoire (première fois)")
    tmp: = make ([] uint32, 100000000) // 400 Mo
    pour kk: = range tmp {
        tmp [kk] = 0
    }
    Time.Sleep (3 * time.Minute) // étendre le retard fmt.println ("Retour Memory (première fois)")
    tmp = make ([] uint32, 1)
    tmp = nil
    Time.Sleep (3 * time.Minute) // étendre le retard fmt.println ("Getting Memory (deuxième fois)")
    tmp = make ([] uint32, 10000000) // allocation grand tableau à nouveau pour kk: = range tmp {
        tmp [kk] = 0
    }
    Time.Sleep (3 * Time.Minute)

    fmt.println ("retour de mémoire (deuxième fois)")
    tmp = make ([] uint32, 1)
    tmp = nil
    Time.Sleep (3 * Time.Minute)

    fmt.println ("programme terminé")
}

Exécutez le code modifié et définissez GOGCTRACE = 1, et vous verrez un extrait de journal clé similaire à ce qui suit:

 mémoire de retour (première fois)
# ... Après un certain temps...
SCVG0: InUSE: 1, inactif: 1, sys: 3, libéré: 0, consommé: 3 (MB)
SCVG0: Inuse: 381, Idle: 0, SYS: 382, ​​libéré: 0, consommé: 382 (MB)
SCVG1: Inuse: 1, inactif: 1, sys: 3, libéré: 0, consommé: 3 (MB)
SCVG1: Inuse: 381, Idle: 0, SYS: 382, ​​libéré: 0, consommé: 382 (MB)
GC9 (1): 1 0 0 MS 1 -> 1 MB 4485 -> 2562 (26531-23969) Objets 0 HANDOFF
GC10 (1): 1 0 0 MS 1 -> 1 MB 2563 -> 2561 (26532-23971) Objets 0 HANDOFF
SCVG2: GC Forced // ForceGC (2 minutes) dépassé
SCVG2: InUSE: 1, inactif: 1, sys: 3, libéré: 0, consommé: 3 (MB)
GC3 (1): 0 0 0 MS 381 -> 381 MB 206 -> 206 (252-46) Objets 0 HANDOFF
SCVG2: GC Forced
SCVG2: Inuse: 381, Idle: 0, SYS: 382, ​​libéré: 0, consommé: 382 (MB)
Obtenir de la mémoire (deuxième fois)

Interprétation du journal:

  • Ligne de journal SCVG : Il s'agit de la sortie du piégeur de mémoire, indiquant que l'activité de la mémoire est retournée au système d'exploitation.
    • InUse: la mémoire (MB) est actuellement utilisée lorsque GO fonctionne.
    • INDLE: La mémoire (MB) qui a été allouée lorsque GO est en cours d'exécution mais qui est actuellement gratuite.
    • SYS: La mémoire totale (inutilisation inactive, MB) obtenue à partir du système d'exploitation lorsque GO s'exécute.
    • Sortie: La mémoire (MB) est retournée au système d'exploitation.
    • Consommé: la mémoire totale (MB) actuellement consommée lors de l'exécution.
  • SCVG2: GC forcé : Cela indique que le sysmon a forcé un GC en raison de forcer le délai d'expiration GC (2 minutes).
  • Après la mémoire renvoyée, si le retard est suffisamment long (plus que Scangelimit), vous verrez la valeur de l'augmentation du champ publié, indiquant que le temps d'exécution GO renvoie la portée de mémoire libre au système d'exploitation. Par exemple, lorsqu'un grand tableau est libéré, cette ligne (ou d'autres lignes similaires) peut montrer que la libération a une valeur non nulle, ou la valeur SYS baisse considérablement, ce qui signifie que GO a renvoyé la majeure partie de la mémoire libre dans le système d'exploitation lors de son exécution.

Grâce à ces journaux, nous pouvons confirmer que GC GC de GO recycle la mémoire et renvoie la mémoire au système d'exploitation après la satisfaction d'une condition spécifique (comme ScanVENGELIMIT Timeout). Pendant une courte période, GO Runtime a tendance à conserver la mémoire recyclée pour une utilisation ultérieure pour améliorer les performances.

4. Grande stratégie de gestion des variables de mémoire et malentendus communs

Comprendre le mécanisme GC de Go est crucial pour gérer efficacement les grandes variables de mémoire.

4.1 La signification de l'attribution nulle

Dans l'exemple de code, nous avons utilisé TMP = NIL pour les grandes tableaux "libres". Cela ne forçait pas à GC à fonctionner immédiatement, mais marque la zone de mémoire pointée par la variable TMP comme n'étant plus référencée. Une fois qu'il n'y a pas de référence active pointant vers cette zone de mémoire, le GC le reconnaît comme un objet recyclable la prochaine fois qu'il fonctionnera. Ceci est juste un candidat pour transformer l'objet en GC, plutôt que de relâcher immédiatement la mémoire.

4.2 Raisons pour que la mémoire ne soit pas retournée au système d'exploitation immédiatement

Le GO Runtime ne renvoie pas immédiatement la mémoire recyclée au système d'exploitation, et il y a plusieurs raisons principales:

  1. Optimisation des performances : la demande fréquemment pour la mémoire et le rendement du système d'exploitation apporteront des frais généraux d'appel du système. GO Runtime a tendance à conserver une partie de la mémoire libre afin que les allocations de mémoire ultérieures puissent être récupérées à partir de ces mémoire réservées plus rapidement, réduisant la fréquence des appels système.
  2. Mécanisme Scavengelimit : Comme mentionné précédemment, GO conservera la portée de la mémoire libre pendant une période de temps selon le paramètre ScanvenGelimit. Ce n'est que lorsque le temps d'inactivité dépasse cette limite sera considérée comme retournée au système d'exploitation.
  3. Différences de rapport du système d'exploitation : différents systèmes d'exploitation (même le même système d'exploitation sous différents outils) peuvent être statistiquement différents dans la "consommation de mémoire". Par exemple, certains outils peuvent signaler la taille de mémoire virtuelle du processus, qui peut contenir de la mémoire que le GO Runtime a demandé au système d'exploitation mais est gratuite en interne, ce qui fait apparaître que la mémoire n'est pas réduite. Sur certains systèmes (tels que le plan 9 et certaines versions de Windows), le niveau du système d'exploitation peut ne pas afficher immédiatement une baisse de l'utilisation de la mémoire même si le GO Runtime s'est libéré en interne.

4.3 Suggestions pour éviter l'OOM

Lors du traitement de grandes quantités de données ou de programmes GO à long terme, vous pouvez rencontrer une exception "hors mémoire". Voici quelques pratiques professionnelles pour gérer les grandes variables de mémoire:

  1. Comprendre le comportement de GC : tout d'abord, soyez clair que GC de GO est non déterministe et ne vous attendez pas à ce que la mémoire soit renvoyée immédiatement au système d'exploitation.
  2. Analyse de la mémoire avec PPROF : Lors de la rencontre des problèmes de mémoire, l'outil le plus efficace est l'analyseur de performance intégré de GO PPROF. Il peut vous aider à identifier les parties du programme allouant beaucoup de mémoire et s'il y a une fuite de mémoire (c'est-à-dire que la mémoire qui n'est plus utilisée est toujours en train de se déformer).
  3. Réduire les allocations inutiles : pour les grands objets qui sont fréquemment créés et détruits, envisagez d'utiliser un pool d'objets (sync.pool) ou pré-allocation de grands tampons de morceaux et multiplexage pour réduire la pression GC et la fragmentation de la mémoire.
  4. Données de streaming : pour les ensembles de données super-grandes, essayez d'éviter de charger toutes les données en mémoire à la fois. Utilisez le traitement en streaming ou en se couchant, seule une petite partie des données est traitée à la fois, et elle est publiée immédiatement après le traitement pour s'assurer que le GC a la possibilité de le recycler.
  5. Concevoir raisonnablement des structures de données : choisissez des structures de données avec une efficacité de mémoire élevée. Par exemple, [] l'octet est généralement plus d'économie de mémoire que la chaîne [], car ce dernier peut impliquer une surcharge d'en-tête de chaîne supplémentaire.
  6. Évitez les grandes variables mondiales : essayez d'éviter de déclarer de grandes variables à longue durée de vie dans la portée globale, ce qui empêchera GC de récupérer la mémoire qu'il fait référence. Si nécessaire, assurez-vous de définir sa référence à NIL lorsqu'il n'est plus utilisé et assurez-vous qu'il n'y a pas d'autres références.
  7. Surveillance et réglage : surveiller en continu l'utilisation de la mémoire des programmes GO dans un environnement de production. Bien que GO GC fonctionne généralement bien, dans certains scénarios de haute charge, il peut être nécessaire d'ajuster le pourcentage cible de GC par le biais de variables d'environnement GOGC, mais il n'est généralement pas recommandé de le modifier à leur niveau, sauf si vous êtes bien conscient de son impact.

5. Résumé

GO Language gère automatiquement la mémoire via son collecteur de déchets de nettoyage de balise efficace et son goroutine sysmon. Bien que cela simplifie considérablement le travail des développeurs, la compréhension de leurs mécanismes internes est cruciale pour rédiger des programmes GO haute performance et conviviaux. Le recyclage de la mémoire est un processus asynchrone et retardé. Le GO Runtime recyclera la mémoire en interne et le renverra au système d'exploitation à des moments appropriés en fonction de paramètres tels que ForceGCPeriod et Scangelimit. Gogctrace vous permet d'observer en profondeur les activités GC, et PPROF est un outil puissant pour diagnostiquer les problèmes de mémoire. Suivre de bonnes pratiques de gestion de la mémoire, comme la réduction de l'allocation inutile, le multiplexage des objets et les données de streaming, peut nous aider à utiliser plus efficacement les capacités de gestion de la mémoire de Go et à éviter les goulots d'étranglement potentiels de mémoire.

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

Outils d'IA chauds

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Stock Market GPT

Stock Market GPT

Recherche d'investissement basée sur l'IA pour des décisions plus intelligentes

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Quelle est la structure structure vide {} utilisée dans Golang Quelle est la structure structure vide {} utilisée dans Golang Sep 18, 2025 am 05:47 AM

Struct {} est une structure sans champ dans GO, qui occupe des octets zéro et est souvent utilisé dans des scénarios où les données ne sont pas nécessaires. Il est utilisé comme signal dans le canal, comme la synchronisation de la goroutine; 2. Utilisé comme collection de types de valeurs de cartes pour réaliser des vérifications de l'existence clé en mémoire efficace; 3. Récepteurs de méthode sans état définissables, adaptés aux fonctions d'injection de dépendance ou d'organisation. Ce type est largement utilisé pour exprimer le débit de contrôle et effacer les intentions.

Résoudre Go WebSocket ERROR: Gardez la connexion active Résoudre Go WebSocket ERROR: Gardez la connexion active Sep 16, 2025 pm 12:15 PM

Cet article vise à résoudre les erreurs EOF (de fin de fichier) rencontrées lors du développement de WebSocket à l'aide de Go. Cette erreur se produit généralement lorsque le serveur reçoit le message client et que la connexion est fermée de manière inattendue, ce qui entraîne la livraison normalement des messages suivants. Cet article analysera les causes du problème, fournira des exemples de code et fournira des solutions correspondantes pour aider les développeurs à créer des applications WebSocket stables et fiables.

Démarrez un éditeur externe dans le programme Go et attendez qu'il termine Démarrez un éditeur externe dans le programme Go et attendez qu'il termine Sep 16, 2025 pm 12:21 PM

Cet article décrit comment démarrer un éditeur externe (comme VIM ou Nano) dans un programme Go et attendre que l'utilisateur ferme l'éditeur avant que le programme ne continue d'exécuter. En définissant CMD.Stdin, Cmd.Stdout et Cmd.Stderr, l'éditeur peut interagir avec le terminal pour résoudre le problème de l'échec du démarrage. Dans le même temps, un exemple de code complet est affiché et des précautions sont fournies pour aider les développeurs à implémenter cette fonction en douceur.

Comment lisez-vous et écrivez-vous des fichiers dans Golang? Comment lisez-vous et écrivez-vous des fichiers dans Golang? Sep 21, 2025 am 01:59 AM

GoprovidessIMPLEAFEFFIENTSFILEHandlingusingheosandbufiopackages.toreAdasmallFileEentirely, useos.readfile, wholoadStheContenTiToMeMorySafelyandAutomAtical ManagesFileOperations.ForlARGEFILSORINCREM

Comment lire la configuration à partir de fichiers de Golang Comment lire la configuration à partir de fichiers de Golang Sep 18, 2025 am 05:26 AM

Utilisez le package Encoding / JSON de la bibliothèque standard pour lire le fichier de configuration JSON; 2. Utilisez la bibliothèque gopkg.in/yaml.v3 pour lire la configuration du format YAML; 3. Utilisez la bibliothèque OS.getenv ou Godotenv pour écraser la configuration du fichier; 4. Utilisez la bibliothèque Viper pour prendre en charge des fonctions avancées telles que la configuration multi-format, les variables d'environnement, le rechargement automatique; Il est nécessaire de définir la structure pour garantir la sécurité de type, gérer correctement les erreurs de fichiers et d'analyse, utiliser correctement les champs de mappage de balises de structure, éviter les chemins à code dur et recommander d'utiliser des variables d'environnement ou un stockage de configuration sûre dans l'environnement de production. Il peut commencer par JSON simple et migrer vers Viper lorsque les exigences sont complexes.

Que sont les middleware dans le contexte des serveurs Web Golang? Que sont les middleware dans le contexte des serveurs Web Golang? Sep 16, 2025 am 02:16 AM

Middlewareingowebserversafunction aterttercepthttprequestsboreetheyreachthehandler, permettre à la transformation de la transmission de la transmission; ils enworkbywrapinghandlerstoaddpre-andpost-processingLogicsuchy

GO Language CFB Mode Encryption: Résoudre Nil Pointer Exception de XorkeyStream GO Language CFB Mode Encryption: Résoudre Nil Pointer Exception de XorkeyStream Sep 16, 2025 pm 12:30 PM

Cet article vise à aider les développeurs à comprendre et à résoudre les exceptions de pointes nulles causées par la fonction XorkeyStream qui peut être rencontrée lors de l'utilisation du mode CFB (rétroaction de chiffre) du langage GO pour le cryptage AES. Assurez-vous que le processus de cryptage se déroule bien en analysant les causes courantes des erreurs et en fournissant les exemples de code corrects. L'accent est mis sur l'utilisation correcte des vecteurs d'initialisation (IV) et sur l'importance de comprendre la taille du bloc AES.

Comment compiler aller pour une architecture différente (bras) Comment compiler aller pour une architecture différente (bras) Sep 16, 2025 am 12:27 AM

Pour compiler le code GO pour l'architecture ARM, définissez simplement les variables d'environnement et utilisez la commande gobuild. 1. Définissez GoOS = Linux et Goarch = ARM (32 bits) ou ARM64 (64 bits) pour spécifier la plate-forme cible. 2. En éventuellement, définissez Goarm = 7 pour le bras 32 bits pour spécifier le jeu d'instructions ARMV7. 3. Si aucun CGO n'est requis, définissez CGO_ENABLED = 0 pour assurer la liaison statique. 4. Exécutez la commande telle que goos = linuxgoarch = arm64cgo_enabled = 0gobuild-omyapp-arm64 pour générer un fichier binaire. 5. Copiez le fichier binaire généré sur un périphérique ARM (tel que Rambre

See all articles