메모리 누수를 찾는 방법에 대한 몇 가지 기사가 있습니다.
그러나 하나를 만드는 것은 어떻습니까?
Ruby에서 메모리 누수가 어떻게 보이는지 알 수 있도록 흥미로운 연습이 될 것이라고 생각합니다.
몇 가지 예를 살펴보겠습니다.
간단한 누출
배열에 새 개체를 추가하기만 하면 메모리 누수가 발생할 수 있습니다.
좋아요 :
a = []
b = {}
loop {
sleep(1)
10_000.times { a << "abc" }
puts GC.stat(b)[:heap_live_slots]
}
이것은 매초 10k 문자열을 생성하고 개체 수를 인쇄합니다:
285051 295052 305053 315054 325055 335056 345057 355058
GC가 이러한 문자열을 수집할 수 없으므로 포함하는 배열(a ).
a인 경우 GC가 이러한 모든 "abc"를 수집할 수 있는 범위를 벗어납니다. 문자열. a를 설정하여 위의 예에서 이를 테스트할 수 있습니다. nil로 설정한 다음 GC.start 실행 .
여기에서 라이브 예제를 찾을 수 있습니다. run을 클릭하기만 하면 됩니다. 결과를 확인하세요.
C 확장자 누출
Ruby에서 객체를 생성할 때 GC는 사용 중인 메모리 양을 추적하지만 C 확장을 사용할 때 Ruby는 어떤 일이 발생하는지 제어할 수 없습니다.
다음과 같이 C 확장을 만드는 경우:
#include <ruby.h>
#include "extconf.h"
void *ptr;
void Init_extension()
{
allocate_memory();
}
void allocate_memory() {
for(int i = 0; i < 10000; i++) {
ptr = malloc(1000);
}
}
allocate_memory() 함수는 malloc를 사용하기 때문에 메모리 누수가 발생합니다. &free라고 부르지 않습니다. 그 기억을 해제합니다.
여기에서 볼 수 있듯이:
`ps -o rss -p #{$$}`.lines.last
# "49036"
require './extension'
`ps -o rss -p #{$$}`.lines.last
# "89512"
이러한 종류의 누수는 힙 덤프나 GC.stat에 표시되지 않습니다. 하지만 메모리 사용량이 증가하는 것을 볼 수 있습니다.
요약
이제 메모리 누수가 어떻게 생겼는지 알았습니다. 이 문제가 발생하면 더 빨리 찾는 데 도움이 될 것입니다. Btw Ruby 2.4.1에는 알려진 메모리 누수가 있으므로 이 특정 버전을 사용하는 경우 업그레이드하는 것이 좋습니다.
질문, 피드백 또는 흥미로운 메모리 누수 디버깅 스토리가 있습니까? 아래에 댓글을 남겨주세요 🙂
읽어주셔서 감사합니다!