메모리 누수를 찾는 방법에 대한 몇 가지 기사가 있습니다.
그러나 하나를 만드는 것은 어떻습니까?
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에는 알려진 메모리 누수가 있으므로 이 특정 버전을 사용하는 경우 업그레이드하는 것이 좋습니다.
질문, 피드백 또는 흥미로운 메모리 누수 디버깅 스토리가 있습니까? 아래에 댓글을 남겨주세요 🙂
읽어주셔서 감사합니다!