ProgramingTip

Golang 메모리를 분석하는 방법?

bestdevel 2020. 12. 1. 19:12
반응형

Golang 메모리를 분석하는 방법?


런타임에 1.2GB의 메모리를 사용하는 golang 프로그램을 작성했습니다.

323.4MB go tool pprof http://10.10.58.118:8601/debug/pprof/heap에 불고기 한 카드가 생성됩니다.

  • 나머지 메모리 상태는 어떻습니까?
  • golang 운영 메모리를 설명하는 더 좋은 도구가 있습니까?

gcvis나는 이것을 사용하여 :

여기에 이미지 설명 입력

.. 및이 힙 양식 프로필 :

여기에 이미지 설명 입력

내 코드는 다음과 달라집니다. https://github.com/sharewind/push-server/blob/v3/broker


힙 프로필은 활성 메모리, 실행이 프로그램에서 사용 중이라고 생각하는 메모리를 보여줍니다 (예 : 가비지 수집기에 의해 수집되지 않음). GC 메모리를 수집가하면 프로필이 축소되지만 메모리는 시스템에 반환되지 않습니다 . 할당은 시스템에 추가 요청을하기 전에 이전에 수집 된 개체 풀의 메모리를 사용하려고합니다.

외부에서 이것은 프로그램의 메모리 사용이 증가하거나 수준을 유지한다는 것을 의미합니다. 외부 시스템이 프로그램의 "Resident Size"로 표시되는 것은 사용중인 go 값을 보유하든 수집 된 값을 보유하든 프로그램에 할당 된 RAM의 바이트 수입니다.

이 두 숫자가 종종 상당히 다른 이유는 다음과 가변적입니다.

  1. GC 수집 메모리는 프로그램의 외부보기에 영향을주지 않습니다.
  2. 메모리 조각화
  3. GC는 사용중인 메모리가 이전 GC 이후 사용중인 메모리를 두 배로 늘릴 때만 실행됩니다 (기본적으로 http://golang.org/pkg/runtime/#pkg-overview 참조 ).

Go가 메모리를 인식하는 방식을 정확하게 분석하여 사용할 수 있습니다. ReadMemStats 호출 : http://golang.org/pkg/runtime/#ReadMemStats

또는에서 브라우저를 통해 약력 링 데이터에 액세스 할 수있는 경우 웹 기반 약력 링을 사용 http://10.10.58.118:8601/debug/pprof/하고 있으므로 힙 링크를 클릭하면 작동에 실행됩니다. MemStats 구조가 출력 된 힙 약력의 실행보기가 표시됩니다. 바닥.

runtime.MemStats 문서 ( http://golang.org/pkg/runtime/#MemStats )에는 모든 필드에 대한 설명이 토론이 토론에서 흥미로운 내용은 다음과 있습니다.

  • HeapAlloc : 내부적으로 약력 러가 제공하는 것 (활성 힙 메모리)
  • Alloc : HeapAlloc과 유사하지만 모두 관리되는 메모리에 대해
  • Sys : OS에서 요청한 총 메모리 양 (주소 공간)

Go가 시스템에 요청하는 것과 OS가 제공하는 것이 항상 같지 않기 때문에 Sys와 OS가보고하는 내용 사이에는 여전히 불일치가있을 것입니다. 또한 CGO / syscall (예 : malloc / mmap)


@Cookie of Nine의 답변에 추가로 간단히 말해서 --alloc_space옵션을 시도 할 수 있습니다 .

go tool pprof--inuse_space기본적으로 사용 합니다. 결과는 실제의 하위 집합이 할당 된 메모리를 샘플링합니다.
으로 --alloc_spacepprof는 프로그램 시작 이후 할당 된 모든 메모리 를 반환합니다 .


Go 애플리케이션의 주거용 메모리 증가에 대해 항상 혼란 스러웠고 마침내 Go 생태계에 존재하는 약력 링 도구를 배워야했습니다. 런타임은 runtime.Memstats 구조 내에서 많은 메트릭을 제공 하지만 메모리 증가의 원인을 찾는 데 도움이 될 수있는 메트릭 을 이해하기 어려울 수 있으므로 몇 가지 추가 도구가 필요합니다.

프로파일 링 환경

에서 애플리케이션 https://github.com/tevjef/go-runtime-metrics사용 하십시오 . 예를 들어 다음과 같이 입력 할 수 있습니다 main.

import(
    metrics "github.com/tevjef/go-runtime-metrics"
)
func main() {
    //...
    metrics.DefaultConfig.CollectionInterval = time.Second
    if err := metrics.RunCollector(metrics.DefaultConfig); err != nil {
        // handle error
    }
}

실행 InfluxDBGrafana내부 Docker용기 :

docker run --name influxdb -d -p 8086:8086 influxdb
docker run -d -p 9090:3000/tcp --link influxdb --name=grafana grafana/grafana:4.1.0

GrafanaInfluxDB Grafana(Grafana 메인 페이지-> 상단 모서리 상단-> 데이터 소스-> 새 데이터 소스 추가) 상호 작용을 설정합니다 .

여기에 이미지 설명 입력

https://grafana.com 에서 대시 보드 # 3242 가져 오기 (Grafana 메인 페이지-> 왼쪽 상단 모서리-> 대시 보드-> 가져 오기 오기) :

여기에 이미지 설명 입력

마지막으로 애플리케이션을 시작합니다. 가동을 contenerized로 전송합니다 Influxdb. 응용 프로그램을 합리적인 부하 (제 경우에는 몇 시간 동안 5RPS로 매우 작음)에 놓으십시오.

메모리 소비 분석

  1. Sys(의 동의어 RSS) curve는 curve와 매우 유사합니다 HeapSys. 동적 메모리 할당이 전체 메모리 증가의 주요 구성이 이루어졌습니다. 스택 변수는 사용하는 소량의 메모리는 일정에 따라 무시할 수 있습니다.
  2. 꼭 양의 고 루틴은 고 루틴 / 스택 변수가 없음을 보장합니다.
  3. 할당 된 개체의 총 양은 프로세스 수명 동안 동일하게 유지됩니다 (변동을 고려할 필요가 없음).
  4. 가장 놀라운 사실 은 같은 속도로 성장하는 반면 항상 0입니다. 분명히 말하는 것이냐 테스트의 조건 하에서 메모리를 OS 에 전혀 반환하지 않습니다 .HeapIdleSysHeapReleased
HeapIdle minus HeapReleased estimates the amount of memory    
that could be returned to the OS, but is being retained by
the runtime so it can grow the heap without requesting more
memory from the OS.

여기에 이미지 설명 입력여기에 이미지 설명 입력

메모리 소비 문제를 조사하려는 사람들에게는 사소한 오류 (예 : 고 루틴 한 오류)를 생략하기 위해 설명 단계를 따르는 것이 좋습니다.

명시 적으로 메모리 해제

다음을 명시 적으로 호출하여 메모리 소비를 크게 수 있습니다. 흥미 롭습니다 debug.FreeOSMemory().

// in the top-level package
func init() {
   go func() {
       t := time.Tick(time.Second)
       for {
           <-t
           debug.FreeOSMemory()
       }
   }()
}

비교

실제로 접근 방식은 기본 조건에 비해 35 %의 메모리를 절약했습니다.


또한 StackImpact 를 사용할 수 있습니다.이 프로필은 상당한이고 수준으로 트리거 된 메모리 할당 프로필을 자동으로 기록하고 보드에보고합니다.이 프로필은 기록 및 비교 가능한 형식으로 제공됩니다. 자세한 내용은이 블로그 게시물을 참조하십시오 . Go 애플리케이션의 메모리 누수 감지

여기에 이미지 설명 입력

면책 조항 : 저는 StackImpact에서 일합니다

참고 URL : https://stackoverflow.com/questions/24863164/how-to-analyze-golang-memory

반응형