Ruby 애플리케이션에 무슨 일이 일어나고 있는지 궁금하시다면…
멋진 GUI 도구가 없습니다. …
하지만 ObjectSpace 모듈이 있습니다!
객체 공간 애플리케이션의 현재 상태에 대한 정보를 제공합니다.
작동 원리를 알아보겠습니다.
객체 계산
ObjectSpace
사용 프로그램에서 현재 '살아 있는' 개체를 알 수 있습니다.
개체가 살아 있다는 것은 무엇을 의미합니까?
개체를 가리키는 참조가 있는 한 개체는 살아 있습니다. 참조는 변수나 상수와 같은 개체에 액세스하는 방법일 뿐입니다.
개체에 도달할 수 없으면 메모리에서 제거해도 안전하다는 의미입니다.
예 :
# The variable 'name' holds a reference to the string 'Dave'. name = 'Dave' # The 'name' variable now points to 'John'. # 'Dave' no longer has a reference pointing to it. name = 'John'
이제 ObjectSpace
의 예를 살펴보겠습니다. 실행 중:
require 'objspace' # This is valid Ruby syntax, but doesn't work on irb/pry ObjectSpace .each_object .inject(Hash.new 0) { |h,o| h[o.class] += 1; h } .sort_by { |k,v| -v } .take(10) .each { |klass, count| puts "#{count.to_s.ljust(10)} #{klass}" } # Copy & paste version (use this for irb/pry) ObjectSpace.each_object.inject(Hash.new 0) { |h,o| h[o.class] += 1; h }.sort_by { |k,v| -v }.take(10).each { |klass, count| puts "#{count.to_s.ljust(10)} #{klass}" }를 넣습니다.
그러면 상위 10개 클래스에 대한 개체 수가 포함된 테이블이 인쇄됩니다.
Count Class ------------------------- 5436 String 315 Class 251 Array 101 Encoding 69 Regexp 45 Hash 26 Module 25 Gem::Version 22 Gem::StubSpecification::StubLine 22 Gem::StubSpecification
메모리 누수가 의심되는 경우 매시간 이 데이터를 기록하고 항상 증가하지만 결코 감소하지 않는 일부 개체 수가 있는지 확인할 수 있습니다.
재미있는 물건
ObjectSpace
를 사용하는 경우 정보뿐만 아니라 실제 개체에 액세스할 수 있으므로 모든 문자열의 값을 인쇄하거나 모든 File
의 경로를 인쇄하는 것과 같은 재미있는 작업을 수행할 수 있습니다. 개체.
예 :
ObjectSpace .each_object(String) .sort_by { |s| s.size } .each { |s| p s }
이렇게 하면 크기별로 정렬된 모든 인메모리 문자열이 인쇄됩니다. 스스로 생성한 것이 아니라 Ruby 인터프리터에서 생성한 문자열이 많이 있음을 알 수 있습니다.
실용?
음, 이것은 주로 앱에 대한 통계를 디버깅하고 수집하기 위한 것입니다 🙂
객체 메모리 크기
또 다른 방법은 ObjectSpace.memsize_of
를 사용하는 것입니다. 특정 개체의 메모리 크기를 찾습니다.
예 :
o = "a" * 100 ObjectSpace.memsize_of(o)
한 가지 명심해야 할 점은 다음 문서의 경고입니다.
<블록 인용>"반품 크기가 불완전하다는 점에 유의하십시오. 이 정보는 힌트로만 다루어야 합니다.”
다른 유형의 개체로 이 방법을 시도하면 몇 가지 흥미로운 점을 발견할 것입니다 , Fixnum
과 같이 s는 항상 0을 반환합니다.
ObjectSpace.memsize_of(42) # 0
그 이유는 Ruby가 내부적으로 Fixnum
을 생성하지 않기 때문입니다. 개체에 대한 자세한 내용은 내가 Ruby의 숫자에 대해 쓴 게시물에서 확인할 수 있습니다.
또 다른 흥미로운 것은 문자열입니다:
ObjectSpace.memsize_of("A" * 22) # 40 ObjectSpace.memsize_of("A" * 23) # 40 ObjectSpace.memsize_of("A" * 24) # 65<블록 인용>
"A" * size
를 사용합니다. 입력하지 않고 더 긴 문자열을 만드는 방법으로 🙂
기다리다! 방금 무슨 일이 일어났나요?
글쎄, Ruby에는 24자보다 작은 문자열에 대한 최적화가 내장되어 있다는 것이 밝혀졌습니다. 그래서 그 이후에 메모리 사용이 급증합니다. Pat Shaughnessy의 이 게시물에서 더 자세히 볼 수 있습니다.
별칭 메서드를 찾는 방법
Ruby에 모든 aliased 메소드의 '마스터' 목록이 있다면 좋지 않을까요?
소원성취!
여기를 살펴보세요 :
class Module def aliased_methods instance_methods(false) .group_by { |m| instance_method(m) } .map(&:last) .keep_if { |symbols| symbols.length > 1 } end end
Stackoverflow 답변에서 이 코드를 얻었습니다. aliased_methods
를 정의합니다. Module
의 메소드 instance_methods
를 사용하는 클래스 클래스에 정의된 모든 인스턴스 메서드 목록을 가져오는 메서드입니다.
다소 혼란스럽게 들릴 수도 있지만, 이것은 메타프로그래밍입니다!
다음은 코드의 나머지 부분으로, 최소한 하나의 '살아있는' 객체가 있는 모든 클래스 이름의 배열을 만든 다음 aliased_methods
를 호출합니다. 모든 클래스에서 및 출력을 인쇄합니다.
objects = ObjectSpace.each_object.map(&:class).uniq objects.each do |klass| methods = "n#{klass}n#{'-'*20}n" klass.send(:aliased_methods).each do |m1, m2| methods << "#{m1.to_s.ljust(15)} #{m2}n" end puts methods end
출력은 다음과 같습니다. :
Array -------------------- inspect to_s [] slice length size find_index index collect map collect! map!
결론
ObjectSpace
로 할 수 있는 멋진 작업에 대해 즐겁게 배우셨기를 바랍니다. , 지금 가서 사용해 보고 흥미로운 점을 찾으면 알려주세요!
이 게시물을 모든 프로그래머 친구들과 공유하는 것을 잊지 마세요. 그들이 새로운 것을 배우는 데 도움이 되고 더 많은 독자를 확보하는 데 도움이 될 것입니다 🙂