Maison > Article > développement back-end > Cas pratiques de tests de performances à Golang
Cas pratiques de tests de performances dans Golang
Avec la large application de Golang dans l'industrie Internet, la demande d'optimisation des performances du code est devenue de plus en plus importante. Les tests de performances sont devenus un moyen important d’évaluer les performances du code. Cet article utilisera un cas pratique pour présenter comment effectuer des tests de performances dans Golang et optimiser les goulots d'étranglement des performances.
Contexte du cas
Supposons que nous ayons l'obligation de compter les occurrences de tous les mots dans un fichier. Ceci peut être réalisé grâce au code suivant :
func countWords(filename string) (map[string]int, error) { file, err := os.Open(filename) if err != nil { return nil, err } defer file.Close() scanner := bufio.NewScanner(file) scanner.Split(bufio.ScanWords) count := make(map[string]int) for scanner.Scan() { word := scanner.Text() count[word]++ } if err := scanner.Err(); err != nil { return nil, err } return count, nil }
Test de performances
Pour le code ci-dessus, nous pouvons utiliser le package test
intégré de Golang pour effectuer des tests de performances. La fonction de test spécifique est la suivante : testing
包来进行性能测试。具体的测试函数如下:
func BenchmarkCountWords(b *testing.B) { for i := 0; i < b.N; i++ { _, err := countWords("/path/to/file.txt") if err != nil { b.Errorf("unexpected error: %v", err) } } }
通过BenchmarkCountWords
函数来进行性能测试,b.N
表示测试的次数。在每次测试中,我们均调用countWords
函数,并判断是否有错误发生。如果有错误发生,则使用b.Errorf
来报错。
优化性能瓶颈
经过性能测试,我们发现在大文件的情况下,代码的执行时间较长。原因是我们采用了逐行扫描的方式来读取文件,并且使用了字符串拼接的方式来统计单词的出现次数。这种实现方式在大文件下性能较低。
针对这个性能瓶颈,我们可以采用并发的方式来进行优化。具体的实现如下:
func countWords(filename string) (map[string]int, error) { file, err := os.Open(filename) if err != nil { return nil, err } defer file.Close() count := make(map[string]int) type result struct { word string count int } wordCh := make(chan result) done := make(chan struct{}) go func() { for r := range wordCh { count[r.word] += r.count } done <- struct{}{} }() scanner := bufio.NewScanner(file) scanner.Split(bufio.ScanWords) const numWorkers = 5 var workersWg sync.WaitGroup workersWg.Add(numWorkers) for i := 0; i < numWorkers; i++ { go func() { defer workersWg.Done() for scanner.Scan() { word := scanner.Text() wordCh <- result{word: word, count: 1} } }() } go func() { workersWg.Wait() close(wordCh) }() if err := scanner.Err(); err != nil { return nil, err } <-done return count, nil }
在优化后的代码中,我们创建了numWorkers
个并发的Goroutine来读取文件,并将单词和出现次数发送到wordCh
的通道中。同时,我们创建了一个新的Goroutine来接收通道中的单词和出现次数,并汇总到count
rrreee
BenchmarkCountWords
, et b.N
représente le nombre de tests. Dans chaque test, nous appelons la fonction countWords
et déterminons si une erreur se produit. Si une erreur se produit, utilisez b.Errorf
pour signaler l'erreur. Optimiser les goulots d'étranglement des performancesAprès des tests de performances, nous avons constaté que dans le cas de fichiers volumineux, le temps d'exécution du code est plus long. La raison en est que nous utilisons l'analyse ligne par ligne pour lire le fichier et utilisons la concaténation de chaînes pour compter le nombre d'occurrences de mots. Cette implémentation a des performances inférieures avec des fichiers volumineux. Pour résoudre ce goulot d'étranglement des performances, nous pouvons utiliser la concurrence pour optimiser. L'implémentation spécifique est la suivante : rrreee
Dans le code optimisé, nous avons créé des Goroutines simultanéesnumWorkers
pour lire le fichier et envoyer les mots et le nombre d'occurrences à wordCh
dans la chaîne. En même temps, nous avons créé une nouvelle Goroutine pour recevoir les mots et les heures d'occurrence dans le canal et les résumer dans la carte de count
. Grâce à cette méthode de concurrence, l’efficacité d’exécution du code est améliorée. 🎜🎜Test de performances à nouveau🎜🎜Après l'optimisation de la concurrence, nous avons effectué à nouveau des tests de performances et avons constaté que dans le cas de fichiers volumineux, le temps d'exécution du code était considérablement réduit. Les performances ont été considérablement améliorées. 🎜🎜Résumé🎜🎜Les tests de performances dans Golang sont un moyen important d'évaluer les performances du code. Grâce aux cas pratiques de cet article, nous avons appris comment effectuer des tests de performances dans Golang et optimiser les goulots d'étranglement des performances. J'espère que cela pourra être utile à tout le monde dans l'optimisation des performances de Golang. 🎜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!