"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > Golang: 관찰 가능성과 프로파일링을 통해 거의 감지할 수 없는 제한을 밝혀낸 방법

Golang: 관찰 가능성과 프로파일링을 통해 거의 감지할 수 없는 제한을 밝혀낸 방법

2024-11-08에 게시됨
검색:552

Bovespa로부터 금융 자산에 대한 정보를 얻는 Go와의 개인 프로젝트에서.
시스템은 고루틴과의 동시성 및 병렬성을 집중적으로 사용하여 8초마다 자산 정보(비즈니스 계산과 함께)를 업데이트합니다.
처음에는 오류나 경고가 나타나지 않았지만 일부 고루틴이 다른 고루틴보다 실행하는 데 시간이 오래 걸리는 것을 발견했습니다.

좀 더 구체적으로 말하면, p99 시간은 0.03ms였지만 어떤 지점에서는 0.9ms로 증가했습니다. 이로 인해 문제를 더 자세히 조사하게 되었습니다.

GOMAXPROCS 변수를 기반으로 생성된 세마포어 고루틴 풀을 사용하고 있음을 발견했습니다.
그런데 이 접근 방식에 문제가 있다는 것을 깨달았습니다.

GOMAXPROCS 변수를 사용하면 컨테이너에서 사용 가능한 코어 수가 올바르게 캡처되지 않습니다. 컨테이너에 사용 가능한 코어 수가 VM의 전체 코어보다 적은 경우 VM의 전체 코어를 고려합니다. 예를 들어 내 VM에는 사용 가능한 코어가 8개 있지만 컨테이너에는 4개만 있었습니다. 이로 인해 동시에 실행되도록 8개의 고루틴이 생성되어 제한이 발생했습니다.

밤새 많은 조사 끝에 컨테이너에 있는지 여부에 관계없이 GOMAXPROCS 변수를 보다 효율적으로 자동 조정하는 Uber에서 개발한 라이브러리를 발견했습니다. 이 솔루션은 매우 안정적이고 효율적인 것으로 입증되었습니다. automaxprocs

Golang: Como a observabilidade e profiling revelaram um throttling quase indetectável 우버고 / 자동 최대 프로시저

Linux 컨테이너 CPU 할당량과 일치하도록 GOMAXPROCS를 자동으로 설정합니다.

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

Linux 컨테이너 CPU 할당량과 일치하도록 GOMAXPROCS를 자동으로 설정합니다.

설치

가서 -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.02ms로 계속 유지됩니다. 이 경험은 동시 시스템에서 관찰 가능성과 프로파일링의 중요성을 강조했습니다.

다음은 매우 간단한 예이지만 성능의 차이를 보여주는 예입니다.

Go의 기본 테스트 및 benckmak 패키지를 사용하여 두 개의 파일을 만들었습니다.

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 라이브러리 가져오기를 사용한다는 것입니다.

CPU 2개가 사용된다고 가정하고 벤치마크를 실행했을 때 결과는 다음과 같습니다.

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

ns/op: 특정 작업을 수행하는 데 걸리는 시간을 나노초 단위로 평균 제공합니다.

내 CPU에서 사용할 수 있는 총 코어는 8개이며, 이는 런타임.NumCPU() 속성이 반환한 것입니다. 하지만 벤치마크를 실행하면서 CPU 2개만 사용하도록 정의했고, automaxprocs를 사용하지 않은 파일은 한 번에 실행 제한을 8개 고루틴으로 정의했는데, 가장 효율적인 것은 2개로 정의했습니다. 이렇게 하면 더 적은 할당을 사용하여 실행이 더 효율적이 됩니다.

따라서 애플리케이션의 관찰 가능성과 프로파일링의 중요성은 분명합니다.

릴리스 선언문 이 기사는 https://dev.to/mggcmatheus/golang-como-a-observabilidade-e-profiling-revelaram-um-throttling-quase-inDetectavel-1h5p?1에서 복제됩니다.1 침해가 있는 경우에는 Study_golang에 문의하세요. @163.com 삭제
최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3