Optimisation des performances des applications Go : conseils et exemples

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction

Go (Golang) est un langage compilé et statiquement typé créé par Google pour développer des applications serveur hautes performances. Cependant, même avec un langage aussi efficace, on peut rencontrer des goulots d'étranglement qui réduisent la vitesse et consomment des ressources inutiles. Dans cet article, nous examinerons les méthodes clés d'optimisation des performances des applications Go : du profilage à la gestion de la mémoire et de la concurrence. Vous apprendrez à identifier les problèmes, à les corriger et à écrire un code qui fonctionne rapidement et de manière stable.

1. Profilage : trouver les goulots d'étranglement

Avant d'optimiser, il faut comprendre ce qui ralentit exactement l'application. Go dispose d'un outil intégré pour cela — pprof. Il permet de collecter des profils CPU, mémoire, goroutines et verrous.

Comment lancer le profilage

Ajoutez l'import net/http/pprof dans le code et lancez un serveur HTTP :

package main

import (
	"log"
	"net/http"
	_ "net/http/pprof"
)

func main() {
	go func() {
		log.Println(http.ListenAndServe("localhost:6060", nil))
	}()
	// votre code principal
	select {}
}

Exécutez ensuite la commande dans le terminal :

go tool pprof -http=:8080 http://localhost:6060/debug/pprof/profile?seconds=30

Cela ouvrira une interface web où sont clairement affichés les points chauds (hotspots) — les fonctions qui consomment le plus de CPU. Analysez-les et optimisez-les en priorité.

Benchmarking pour des mesures précises

Pour des tests isolés, utilisez testing.B. Créez un fichier example_test.go :

package main

import "testing"

func BenchmarkMyFunction(b *testing.B) {
	for i := 0; i < b.N; i++ {
		MyFunction()
	}
}

Lancez le benchmark :

go test -bench=. -benchmem

Le flag -benchmem affichera le nombre d'allocations mémoire par opération — c'est un indicateur clé pour l'optimisation.

2. Gestion de la mémoire : moins d'allocations = plus de vitesse

Le ramasse-miettes (GC) de Go est efficace, mais des allocations fréquentes ralentissent le travail. L'optimisation de la mémoire est l'un des moyens les plus efficaces d'accélérer une application.

Allocation préalable des slices

Si vous connaissez la taille du slice à l'avance, allouez-le via make en spécifiant la capacité :

// Mauvais : append réalloue constamment la mémoire
var data []int
for i := 0; i < 100000; i++ {
	data = append(data, i)
}

// Bon : allocation préalable
data := make([]int, 0, 100000)
for i := 0; i < 100000; i++ {
	data = append(data, i)
}

La différence de vitesse peut être de 2 à 3 fois, et le nombre d'allocations est réduit à 1.

Utilisation de sync.Pool pour les objets temporaires

Si vous créez et détruisez souvent des objets (par exemple, des buffers), utilisez un pool :

var bufPool = sync.Pool{
	New: func() interface{} {
		return new(bytes.Buffer)
	},
}

func process() {
	buf := bufPool.Get().(*bytes.Buffer)
	defer bufPool.Put(buf)
	buf.Reset()
	// travail avec le buffer
}

Cela réduit la charge sur le GC et accélère l'exécution dans les boucles.

Évitez les fuites de goroutines

Chaque goroutine occupe au moins 2-4 Ko de pile. Si elles sont des milliers, la mémoire augmente. Utilisez toujours context.WithCancel pour terminer les goroutines :

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

go func() {
	for {
		select {
		case <-ctx.Done():
			return
		default:
			// travail
		}
	}
}()

3. Concurrence : utilisation efficace des goroutines et des canaux

Go est réputé pour ses goroutines légères, mais une mauvaise utilisation peut dégrader les performances.

Taille correcte du pool de goroutines

Ne lancez pas une goroutine pour chaque tâche sans limite. Utilisez le pattern worker pool :



                
                

Blogs

Book Recommendations