Ruby 메서드의 시간 측정 및 벤치 마크


89

Ruby에서 메서드와 해당 메서드의 개별 문에 걸리는 시간을 어떻게 측정 할 수 있습니까? 아래 방법을 보면 방법에 걸린 총 시간과 데이터베이스 액세스 및 redis 액세스에 걸린 시간을 측정하고 싶습니다. 모든 문 앞에 Benchmark.measure를 작성하고 싶지 않습니다. 루비 인터프리터가이 작업을 수행 할 수있는 방법을 제공합니까?

def foo
# code to access database
# code to access redis. 
end

new Date()루비가 가지고있는 자바 스크립트 와 비슷한 것이 있지만 정확한 구문이 기억 나지 않습니다. 하지만 당신이 목록 괜찮은 구글을 주어야한다
레이건

1
@Phani 정답을 선택해주세요. 8 년이 지나면 여기에 확실한 답이 있다고 생각합니다. 감사.
Joshua Pinter

답변:


114

Time개체를 사용할 수 있습니다 . ( 타임 문서 )

예를 들면

start = Time.now
# code to time
finish = Time.now

diff = finish - start

diff 부동 소수점 숫자로 초 단위입니다.

편집 : end예약되어 있습니다.


13
사소한 수정일뿐입니다. end예약되어 있으므로 다른 변수 이름을 사용하십시오.
Jason Kim

4
Time.now시스템 시계 조정의 영향을 받으므로 Process.clock_gettime(Process::CLOCK_MONOTONIC)대신 사용하는 것이 좋습니다. 그러나 대략적인 계산의 경우 이것은 중요하지 않습니다. blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way
Patrick Brinich-Langlois

104

가장 간단한 방법 :

require 'benchmark'

def foo
 time = Benchmark.measure {
  code to test
 }
 puts time.real #or save it to logs
end

샘플 출력 :

2.2.3 :001 > foo
  5.230000   0.020000   5.250000 (  5.274806)

값은 CPU 시간, 시스템 시간, 총 및 실제 경과 시간입니다.

출처 : 루비 문서 .


40
당신은 또한 할 수 Benchmark.realtime { block }방금 실시간하려면
jmccure

35

사용 Benchmark의 보고서

require 'benchmark' # Might be necessary.

def foo
  Benchmark.bm( 20 ) do |bm|  # The 20 is the width of the first column in the output.
    bm.report( "Access Database:" ) do 
      # Code to access database.
    end
   
    bm.report( "Access Redis:" ) do
      # Code to access redis.
    end
  end
end

그러면 다음과 같은 결과가 출력됩니다.

                        user     system      total        real
Access Database:    0.020000   0.000000   0.020000 (  0.475375)
Access Redis:       0.000000   0.000000   0.000000 (  0.000037)

<------ 20 -------> # This is where the 20 comes in. NOTE: This is not shown in output.

자세한 내용은 여기 에서 확인할 수 있습니다 .


2
나는 방금 내 대답으로 돌아 왔고 Benchmark가 이것을 처리하는 방법에 (다시) 감동했습니다. 사랑 루비.
Joshua Pinter

2
이것이 선호되는 대답이어야합니다. Ruby 2.2부터 Benchmark클래스는 다른 답변에서 논의 된 것처럼 단조로운 시계를 사용하기 때문입니다. : 라인 286에 예를 들어 "데프 측정"에 대한 다음과 같은 소스 코드 및 설명을 참조하십시오 github.com/ruby/ruby/blob/ruby_2_2/lib/benchmark.rb
Purplejacket

17

많은 답변에서 Time.now. 그러나 그것이 Time.now바뀔 수 있다는 것을 아는 것은 가치가 있습니다. 시스템 시계는 드리프트 될 수 있으며 시스템 관리자 또는 NTP를 통해 수정할 수 있습니다. 따라서 Time.now가 앞뒤로 이동하여 벤치마킹 결과가 정확하지 않을 수 있습니다.

더 나은 해결책은 항상 앞으로 나아가는 운영 체제의 단조로운 시계를 사용하는 것입니다. Ruby 2.1 이상에서는 다음을 통해 액세스 할 수 있습니다.

start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# code to time
finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
diff = finish - start # gets time is seconds as a float

여기에서 자세한 내용을 읽을 수 있습니다 . 또한 인기있는 Ruby 프로젝트 인 Sidekiq가 단조 시계로 전환 한 것을 볼 수 있습니다 .


7

두 번째 로 Ruby 코드 블록 인수로 measure () 함수를 정의 하면 시간 측정 코드를 단순화하는 데 도움이 될 수 있습니다.

def measure(&block)
  start = Time.now
  block.call
  Time.now - start
end

# t1 and t2 is the executing time for the code blocks.
t1 = measure { sleep(1) }

t2 = measure do
  sleep(2)
end

당신의 정의에서 당신은 그것을라고 부릅니다 benchmark. 당신이 그것을 사용할 때 그것은 호출 measure됩니다. 이것을 수정하십시오.
Sandro L

4

wquist의 대답 정신으로 조금 더 간단하게 다음과 같이 할 수도 있습니다.

start = Time.now
# code to time
Time.now - start

이 대답은 질문에 대답하는 (약간) 다른 방법입니다. @wquist의 답변에서 알아낼 수 있다고해서 유효하지 않다는 의미는 아닙니다.
thesecretmaster

3

로 봐 ruby-prof패키지, 그것은 당신이 필요 있어야합니다. 타이밍과 함께 거대한 호출 스택을 생성합니다.

http://ruby-prof.rubyforge.org/

너무 세분화되어있는 경우 더 큰 섹션을 감싸는 Benchmark.measure것이 좋은 방법 일 수 있습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.