Table des matières
Plusieurs situations où Golang peut facilement entraîner des fuites de mémoire
1.1 L'utilisation de time.After()
1.2 time.NewTicker ressources ne sont pas libérés à tempslors de l'utilisation de time.NewTicker Vous devez appeler manuellement la méthode Stop() pour libérer les ressources, sinon cela provoquera une fuite de mémoire permanente" >1.2 time.NewTicker ressources ne sont pas libérés à tempslors de l'utilisation de time.NewTicker Vous devez appeler manuellement la méthode Stop() pour libérer les ressources, sinon cela provoquera une fuite de mémoire permanente
2. select, s'il y a un cas qui n'est pas entièrement couvert et qu'il n'y a pas de branche par défaut pour le traitement, cela finira par entraîner des fuites de mémoire" >2. select, s'il y a un cas qui n'est pas entièrement couvert et qu'il n'y a pas de branche par défaut pour le traitement, cela finira par entraîner des fuites de mémoire
" >4. Fuite de mémoire causée par goroutine
4.1 Demander trop de goroutines
Par exemple, dans une boucle for Trop de goroutines ne sont pas libérées à temps, provoquant des fuites de mémoire
4.2 Blocage de Goroutine
La connexion d'E/S ne définit pas de délai d'attente, ce qui oblige la goroutine à attendre et le code continuera à se bloquer. " >4.2.1 Problème d'E/SLa connexion d'E/S ne définit pas de délai d'attente, ce qui oblige la goroutine à attendre et le code continuera à se bloquer.
4.2.2 Le verrou mutex n'est pas libéré
5. par slice" >5. par slice
Maison développement back-end Golang Quelles sont les causes des fuites de mémoire Golang ?

Quelles sont les causes des fuites de mémoire Golang ?

Jan 10, 2023 pm 05:45 PM
golang go语言 内存泄漏

Les raisons de la fuite sont : 1. L'utilisation de time.After(). Chaque fois.After(duration x) générera NewTimer() Avant l'expiration de la durée x, la minuterie nouvellement créée ne sera pas GC. , GC; 2. Les ressources time.NewTicker ne sont pas libérées à temps ; 3. blocage de sélection ; 4. blocage de canal ; 5. application d'un trop grand nombre de goroutines, blocage de goroutines ;

Quelles sont les causes des fuites de mémoire Golang ?

L'environnement d'exploitation de ce tutoriel : système Windows 7, GO version 1.18, ordinateur Dell G3.

Plusieurs situations où Golang peut facilement entraîner des fuites de mémoire

1. Utilisation inappropriée des minuteries

1.1 L'utilisation de time.After()

L'heure par défaut.After() a de la mémoire Le problème est divulgué car NewTimer() sera généré à chaque fois.After(duration

Au fil du temps, surtout si la durée Veuillez vérifier la différence par vous-même ou lire mes articles précédents https://blog.csdn.net/weixin_38299404/article/details/119352884

for true {
	select {
	case <-time.After(time.Minute * 3):
    // do something
  default:
		time.Sleep(time.Duration(1) * time.Second)
	}
}
Copier après la connexion

1.2 time.NewTicker ressources ne sont pas libérés à tempslors de l'utilisation de time.NewTicker Vous devez appeler manuellement la méthode Stop() pour libérer les ressources, sinon cela provoquera une fuite de mémoire permanente

timer := time.NewTicker(time.Duration(2) * time.Second)
defer timer.Stop()
for true {
	select {
	case <-timer.C:
		// do something
	default:
		time.Sleep(time.Duration(1) * time.Second)
	}
}
Copier après la connexion

2. select, s'il y a un cas qui n'est pas entièrement couvert et qu'il n'y a pas de branche par défaut pour le traitement, cela finira par entraîner des fuites de mémoire

2.1 Causer le blocage de goroutine

timer := time.NewTicker(time.Duration(2) * time.Second)
// defer timer.Stop()
for true {
	select {
	case <-timer.C:
		// do something
	default:
		time.Sleep(time.Duration(1) * time.Second)
	}
}
Copier après la connexion
La situation ci-dessus bloquera la consommation de ch3 et provoquer des fuites de mémoire

2.2 L'inactivité de la boucle provoque une surtension du processeur

func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)
    ch3 := make(chan int)
    go Getdata("https://www.baidu.com",ch1)
    go Getdata("https://www.baidu.com",ch2)
    go Getdata("https://www.baidu.com",ch3)
    select{
        case v:=<- ch1:
            fmt.Println(v)
        case v:=<- ch2:
            fmt.Println(v)
    }
}
Copier après la connexion
Ci-dessus Une fois que la condition de la boucle for atteint la valeur par défaut, la boucle deviendra inactive et finira par faire monter en flèche le processeur

3.

Le blocage des canaux est principalement divisé en deux situations : le blocage en écriture et le blocage en lecture

canal vide
func main() {
	fmt.Println("main start")
	msgList := make(chan int, 100)
	go func() {
		for {
			select {
			case <-msgList:
			default:
 
			}
		}
	}()
	
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)
	s := <-c
	
	fmt.Println("main exit.get signal:", s)
}
Copier après la connexion
Blocage en écriture

Le blocage du canal sans tampon est généralement l'opération d'écriture est bloquée car il n'y a pas de lecture

func channelTest() {
  	//声明未初始化的channel读写都会阻塞
    var c chan int
  	//向channel中写数据
    go func() {
        c <- 1
        fmt.Println("g1 send succeed")
        time.Sleep(1 * time.Second)
    }()
  	//从channel中读数据
    go func() {
        <-c
        fmt.Println("g2 receive succeed")
        time.Sleep(1 * time.Second)
    }()
    time.Sleep(10 * time.Second)
}
Copier après la connexion

    Le canal tamponné est bloqué car le tampon est plein, l'opération d'écriture est bloquée
  • func channelTest() {
        var c = make(chan int)
      	//10个协程向channel中写数据
        for i := 0; i < 10; i++ {
            go func() {
                <- c
                fmt.Println("g1 receive succeed")
                time.Sleep(1 * time.Second)
            }()
        }
      	//1个协程丛channel读数据
        go func() {
            c <- 1
            fmt.Println("g2 send succeed")
            time.Sleep(1 * time.Second)
        }()
      	//会有写的9个协程阻塞得不到释放
        time.Sleep(10 * time.Second)
    }
    Copier après la connexion
Blocage de la lecture

    J'attends avec impatience la lecture des données du canal, le résultat est qu'il n'y a pas de goroutine pour écrire des données
  • func channelTest() {
        var c = make(chan int, 8)
      	//10个协程向channel中写数据
        for i := 0; i < 10; i++ {
            go func() {
                <- c
                fmt.Println("g1 receive succeed")
                time.Sleep(1 * time.Second)
            }()
        }
      	//1个协程丛channel读数据
        go func() {
            c <- 1
            fmt.Println("g2 send succeed")
            time.Sleep(1 * time.Second)
        }()
      	//会有写的几个协程阻塞写不进去
        time.Sleep(10 * time.Second)
    }
    Copier après la connexion

4. Fuite de mémoire causée par goroutine

4.1 Demander trop de goroutines

Par exemple, dans une boucle for Trop de goroutines ne sont pas libérées à temps, provoquant des fuites de mémoire

4.2 Blocage de Goroutine

4.2.1 Problème d'E/SLa connexion d'E/S ne définit pas de délai d'attente, ce qui oblige la goroutine à attendre et le code continuera à se bloquer.

4.2.2 Le verrou mutex n'est pas libéré

goroutine ne peut pas obtenir la ressource de verrouillage, ce qui provoque le blocage de la goroutine
func channelTest() {
   var c = make(chan int)
  //1个协程向channel中写数据
  go func() {
    <- c
    fmt.Println("g1 receive succeed")
    time.Sleep(1 * time.Second)
  }()
  //10个协程丛channel读数据
  for i := 0; i < 10; i++ {
    go func() {
        c <- 1
        fmt.Println("g2 send succeed")
        time.Sleep(1 * time.Second)
    }()
  }
  //会有读的9个协程阻塞得不到释放
  time.Sleep(10 * time.Second)
}
Copier après la connexion
4.2.3 Deadlock

Lorsque le programme se bloque, d'autres goroutines le feront bloque également
//协程拿到锁未释放,其他协程获取锁会阻塞
func mutexTest() {
    mutex := sync.Mutex{}
    for i := 0; i < 10; i++ {
        go func() {
            mutex.Lock()
            fmt.Printf("%d goroutine get mutex", i)
      			//模拟实际开发中的操作耗时
            time.Sleep(100 * time.Millisecond)
        }()
    }
    time.Sleep(10 * time.Second)
}
Copier après la connexion
4.2.4 Utilisation inappropriée du groupe d'attente

La différence entre le nombre d'ajout, terminé et d'attente du groupe d'attente entraînera une attente constante
5. par slice

Lorsque deux tranches sont partagées, dont l'une est une variable globale, l'autre ne peut pas être GC

Elle a été utilisée après l'ajout de la tranche et n'a pas été nettoyée.
func mutexTest() {
    m1, m2 := sync.Mutex{}, sync.RWMutex{}
  	//g1得到锁1去获取锁2
    go func() {
        m1.Lock()
        fmt.Println("g1 get m1")
        time.Sleep(1 * time.Second)
        m2.Lock()
        fmt.Println("g1 get m2")
    }()
    //g2得到锁2去获取锁1
    go func() {
        m2.Lock()
        fmt.Println("g2 get m2")
        time.Sleep(1 * time.Second)
        m1.Lock()
        fmt.Println("g2 get m1")
    }()
  	//其余协程获取锁都会失败
    go func() {
        m1.Lock()
        fmt.Println("g3 get m1")
    }()
    time.Sleep(10 * time.Second)
}
Copier après la connexion

6. Transfert de valeur des tableaux

Étant donné que les tableaux sont le type de données de base de Golang, chaque tableau occupe un espace mémoire différent et le cycle de vie n'interfère pas les uns avec les autres. fuite, mais en tant que tableau Lors du transfert des paramètres formels, suivez la copie de la valeur temporelle. Si la fonction est appelée par plusieurs goroutines et que le tableau est trop grand, cela entraînera une augmentation de l'utilisation de la mémoire.

var a []int
 
func test(b []int) {
        a = b[:3]
        return
}
Copier après la connexion
Par conséquent, les tranches ou les pointeurs sont généralement utilisés pour transférer de grands tableaux dans des scénarios de paramètres formels afin d'éviter une augmentation à court terme de l'utilisation de la 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

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.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Commandes de chat et comment les utiliser
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌

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)

Quel est le problème avec le fil de file d'attente dans GO's Crawler Colly? Quel est le problème avec le fil de file d'attente dans GO's Crawler Colly? Apr 02, 2025 pm 02:09 PM

Problème de threading de file d'attente dans Go Crawler Colly explore le problème de l'utilisation de la bibliothèque Crawler Crawler dans le langage Go, les développeurs rencontrent souvent des problèmes avec les threads et les files d'attente de demande. � ...

Quelles bibliothèques sont utilisées pour les opérations du numéro de point flottantes en Go? Quelles bibliothèques sont utilisées pour les opérations du numéro de point flottantes en Go? Apr 02, 2025 pm 02:06 PM

La bibliothèque utilisée pour le fonctionnement du numéro de point flottante dans le langage go présente comment s'assurer que la précision est ...

Que dois-je faire si les étiquettes de structure personnalisées à Goland ne sont pas affichées? Que dois-je faire si les étiquettes de structure personnalisées à Goland ne sont pas affichées? Apr 02, 2025 pm 05:09 PM

Que dois-je faire si les étiquettes de structure personnalisées à Goland ne sont pas affichées? Lorsque vous utilisez Goland pour le développement du langage GO, de nombreux développeurs rencontreront des balises de structure personnalisées ...

Dans Go, pourquoi les chaînes d'impression avec println et string () ont-elles des effets différents? Dans Go, pourquoi les chaînes d'impression avec println et string () ont-elles des effets différents? Apr 02, 2025 pm 02:03 PM

La différence entre l'impression de chaîne dans le langage go: la différence dans l'effet de l'utilisation de fonctions println et string () est en Go ...

Quelles bibliothèques de GO sont développées par de grandes entreprises ou fournies par des projets open source bien connus? Quelles bibliothèques de GO sont développées par de grandes entreprises ou fournies par des projets open source bien connus? Apr 02, 2025 pm 04:12 PM

Quelles bibliothèques de GO sont développées par de grandes entreprises ou des projets open source bien connus? Lors de la programmation en Go, les développeurs rencontrent souvent des besoins communs, ...

Comment résoudre le problème de conversion de type user_id lors de l'utilisation du flux redis pour implémenter les files d'attente de messages dans le langage Go? Comment résoudre le problème de conversion de type user_id lors de l'utilisation du flux redis pour implémenter les files d'attente de messages dans le langage Go? Apr 02, 2025 pm 04:54 PM

Le problème de l'utilisation de Redessstream pour implémenter les files d'attente de messages dans le langage GO consiste à utiliser le langage GO et redis ...

Quelle est la différence entre la structure de définition des mots clés `var` et« type »dans le langage Go? Quelle est la différence entre la structure de définition des mots clés `var` et« type »dans le langage Go? Apr 02, 2025 pm 12:57 PM

Deux façons de définir les structures dans le langage GO: la différence entre les mots clés VAR et le type. Lorsque vous définissez des structures, GO Language voit souvent deux façons d'écrire différentes: d'abord ...

Comment s'assurer que la concurrence est sûre et efficace lors de la rédaction de journaux multi-processus? Comment s'assurer que la concurrence est sûre et efficace lors de la rédaction de journaux multi-processus? Apr 02, 2025 pm 03:51 PM

Gérez efficacement les problèmes de sécurité de la concurrence dans la rédaction de journaux multiproces. Plusieurs processus écrivent le même fichier journal en même temps. Comment s'assurer que la concurrence est sûre et efficace? C'est un ...

See all articles