Maison  >  Article  >  développement back-end  >  Cas pratiques de tests de performances à Golang

Cas pratiques de tests de performances à Golang

PHPz
PHPzoriginal
2023-08-07 09:53:131221parcourir

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来接收通道中的单词和出现次数,并汇总到countrrreee

Effectuez des tests de performances via la fonction 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 performances

Aprè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ées numWorkers 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!

Déclaration:
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