「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > Golang: 可観測性とプロファイリングにより、ほぼ検出不可能なスロットリングがどのように明らかにされたか

Golang: 可観測性とプロファイリングにより、ほぼ検出不可能なスロットリングがどのように明らかにされたか

2024 年 11 月 8 日に公開
ブラウズ:967

Go との個人プロジェクトで、Bovespa から金融資産に関する情報を取得します。
このシステムはゴルーチンによる同時実行性と並列性を最大限に活用し、8 秒ごとに資産情報 (ビジネス計算とともに) を更新します。
当初、エラーや警告は表示されませんでしたが、一部のゴルーチンの実行に他のゴルーチンよりも時間がかかっていることに気付きました。

より具体的には、p99 時間は 0.03 ms でしたが、ある時点では 0.9 ms まで増加しました。これにより、問題をさらに調査することになりました。

GOMAXPROCS 変数に基づいて作成されたセマフォ goroutine プールを使用していることがわかりました。
しかし、このアプローチには問題があることに気づきました。

GOMAXPROCS 変数を使用すると、コンテナーで使用可能なコアの数が正しく取得されません。コンテナーの使用可能なコアが VM の合計よりも少ない場合、VM の合計が考慮されます。たとえば、私の VM には利用可能なコアが 8 個ありますが、コンテナーには 4 個しかありませんでした。その結果、同時に実行する 8 つのゴルーチンが作成され、スロットリングが発生しました。

一晩かけて多くの調査を行った結果、コンテナ内にあるかどうかに関係なく、GOMAXPROCS 変数をより効率的に自動的に調整する Uber によって開発されたライブラリを発見しました。このソリューションは非常に安定していて効率的であることが証明されました: automaxprocs

Golang: Como a observabilidade e profiling revelaram um throttling quase indetectável ウーバーゴー / automaxproc

Linux コンテナーの CPU クォータと一致するように GOMAXPROCS を自動的に設定します。

automaxprocs Golang: Como a observabilidade e profiling revelaram um throttling quase indetectável Golang: Como a observabilidade e profiling revelaram um throttling quase indetectável Golang: Como a observabilidade e profiling revelaram um throttling quase indetectável

Linux コンテナーの CPU クォータと一致するように GOMAXPROCS を自動的に設定します。

インストール

go get -u go.uber.org/automaxprocs

クイックスタート

import _ "go.uber.org/automaxprocs"

func main() {
  // Your application logic here.
}
全画面モードにする 全画面モードを終了

パフォーマンス

Uber の内部ロード バランサーから測定されたデータ。 200% の CPU クォータ (つまり 2 コア) でロード バランサーを実行しました:

GOMAXPROCS RPS P50 (ミリ秒) P99.9 (ミリ秒)
1 28,893.18 1.46 19.70
2 (クォータと等しい) 44,715.07 0.84 26.38
3 44,212.93 0.66 30.07
4 41,071.15 0.57 42.94
8 33,111.69 0.43 64.32
デフォルト (24) 22,191.40 0.45 76.19

GOMAXPROCS が CPU クォータを超えて増加すると、P50 はわずかに減少しますが、P99 まで大幅に増加します。また、処理される合計 RPS も減少していることがわかります。

GOMAXPROCS が割り当てられた CPU クォータよりも高い場合、大幅なスロットルも発生しました:

$ cat /sys/fs/cgroup/cpu,cpuacct/system.slice/[...]/cpu.stat
nr_periods 42227334
nr_throttled 131923
throttled_time 88613212216618

GOMAXPROCS が CPU クォータに一致するように削減されると、CPU スロットルは発生しなくなりました。

GitHub で表示

このライブラリの使用を実装した後、問題は解決され、p99 時間は常に 0.02 ms のままになりました。この経験により、同時システムにおける可観測性とプロファイリングの重要性が強調されました。

以下は非常に単純な例ですが、パフォーマンスの違いを示しています。

Go のネイティブ テストと benckmak パッケージを使用して、2 つのファイルを作成しました:

benchmarking_with_enhancement_test.go:

package main

import (
    _ "go.uber.org/automaxprocs"
    "runtime"
    "sync"
    "testing"
)

// BenchmarkWithEnhancement Função com melhoria, para adicionar o indice do loop em um array de inteiro
func BenchmarkWithEnhancement(b *testing.B) {
    // Obtém o número de CPUs disponíveis
    numCPUs := runtime.NumCPU()
    // Define o máximo de CPUs para serem usadas pelo programa
    maxGoroutines := runtime.GOMAXPROCS(numCPUs)
    // Criação do semáforo
    semaphore := make(chan struct{}, maxGoroutines)

    var (
        // Espera para grupo de goroutines finalizar
        wg sync.WaitGroup
        // Propriade
        mu sync.Mutex
        // Lista para armazenar inteiros
        list []int
    )

    // Loop com mihão de indices
    for i := 0; i 



benchmarking_without_enhancement_test.go:

package main

import (
    "runtime"
    "sync"
    "testing"
)

// BenchmarkWithoutEnhancement Função sem a melhoria, para adicionar o indice do loop em um array de inteiro
func BenchmarkWithoutEnhancement(b *testing.B) {
    // Obtém o número de CPUs disponíveis
    numCPUs := runtime.NumCPU()
    // Define o máximo de CPUs para serem usadas pelo programa
    maxGoroutines := runtime.GOMAXPROCS(numCPUs)
    // Criação do semáforo
    semaphore := make(chan struct{}, maxGoroutines)

    var (
        // Espera para grupo de goroutines finalizar
        wg sync.WaitGroup
        // Propriade
        mu sync.Mutex
        // Lista para armazenar inteiros
        list []int
    )

    // Loop com mihão de indices
    for i := 0; i 



これらの違いは、Uber ライブラリのインポートを使用することです。

2 つの CPU が使用されると想定してベンチマークを実行した場合、結果は次のようになりました。

Golang: Como a observabilidade e profiling revelaram um throttling quase indetectável

ns/op: 特定の操作の実行にかかる時間の平均をナノ秒単位で提供します。

使用可能な CPU の合計は 8 コアであり、これが runtime.NumCPU() プロパティによって返されたものであることに注意してください。ただし、ベンチマークの実行時と同様に、使用する CPU は 2 つだけであると定義し、automaxprocs を使用しないファイルでは、一度に実行できるゴルーチンの制限が 8 つであり、最も効率的なのは 2 つであると定義しました。この方法では、割り当てを少なくすることで実行がより効率的になります。

したがって、アプリケーションの可観測性とプロファイリングの重要性は明らかです。

リリースステートメント この記事は次の場所に転載されています: https://dev.to/mggcmatheus/golang-como-a-observabilidade-e-profiling-revelaram-um-throttling-quase-indetectavel-1h5p?1 侵害がある場合は、study_golang にご連絡ください。 @163.com 削除
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3