Ruby에서 밀리 초 단위로 작업 시간을 측정하는 방법은 무엇입니까?


79

특정 기능이 몇 밀리 초를 사용하는지 알고 싶습니다. 그래서 나는 높고 낮게 보였지만 루비에서 밀리 초의 정밀도로 시간을 얻을 수있는 방법을 찾지 못했습니다.

어떻게하나요? 대부분의 프로그래밍 언어에서

start = now.milliseconds
myfunction()
end = now.milliseconds
time = end - start

답변:


92

루비의 Time클래스를 사용할 수 있습니다 . 예를 들면 :

t1 = Time.now
# processing...
t2 = Time.now
delta = t2 - t1 # in seconds

이제 deltaA는 float객체와 당신은 미세 입자로 클래스가 제공 할 것 같은 결과를 얻을 수 있습니다.


2
이것은 쉬운 해결책이지만 Process.clock_gettime의 답이 더 좋습니다. blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way
Guy C

60

내장 된 Benchmark.measure 함수를 사용할 수도 있습니다.

require "benchmark"
puts(Benchmark.measure { sleep 0.5 })

인쇄물:

0.000000   0.000000   0.000000 (  0.501134)

1
내장 라이브러리를 사용하는 것이 마음에 들지만 처음 세 개의 숫자 ( 0.000000)는 무엇입니까? 업데이트 : 문서에서 조회 했으며 사용자 CPU 시간, 시스템 CPU 시간 및이 둘의 합계입니다.
lyonsinbeta 2012 년

1
예. 를 사용하면 레이블이 지정됩니다 Benchmark.bm. 때때로 시간을 보내는 곳을 보는 것이 유용합니다. 여기에서 블록이 유휴 상태임을 알 수 있습니다 (총 0 개, 실제 0.5 개)
Simon Perepelitsa

13
아니면 거기에 Benchmark.realtime하나의 이해 플로트 : 반환
세르지오 Tulentsev

26

사용하여 Time.now베이스 라인으로하여 (벽 시계 시간을 반환) 예상치 못한 동작이 발생할 수있는 문제의 몇 가지가 있습니다. 이는 wallclock 시간이 삽입 된 윤초 또는 현지 시간을 기준 시간으로 조정하는 시간 슬 루잉 과 같이 변경 될 수 있기 때문에 발생합니다 .

예를 들어 측정 중에 삽입 된 윤초가 있으면 1 초씩 꺼집니다. 마찬가지로 로컬 시스템 조건에 따라 일광 절약 시간, 더 빠르거나 느리게 작동하는 시계를 처리해야 할 수도 있고, 시계가 시간을 거슬러 올라가서 시간이 감소하고 기타 여러 문제가 발생할 수도 있습니다.

이 문제에 대한 해결책은 다른 시계 시간 인 단조 시계를 사용하는 것입니다. 이 유형의 시계는 벽시계와 다른 속성을 갖습니다. 단조롭게 증가합니다. 즉, 절대로 되돌아 가지 않고 일정한 속도로 증가합니다. 그것으로, 그것은 벽시계 (즉, 벽에있는 시계에서 읽은 시간)를 나타내지 않고 차이를 얻기 위해 나중의 타임 스탬프와 비교할 수있는 타임 스탬프를 나타냅니다.

Ruby에서는 Process.clock_gettime(Process::CLOCK_MONOTONIC)다음 과 같은 타임 스탬프를 사용할 수 있습니다 .

t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# => 63988.576809828

sleep 1.5 # do some work

t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# => 63990.08359163

delta = t2 - t1
# => 1.5067818019961123
delta_in_milliseconds = delta * 1000
# => 1506.7818019961123

Process.clock_gettime메서드는 소수 초가있는 부동 소수점으로 타임 스탬프를 반환합니다. 반환 된 실제 숫자에는 정의 된 의미가 없습니다 (신뢰해야 함). 그러나 다음 호출에서 더 큰 숫자를 반환하고 값을 비교하여 실시간 차이를 얻을 수 있습니다.

이러한 속성은 프로그램이 최소한의 적절한 시간 (예 : 다른 윤초가 삽입 된 새해 전야 자정)에 실패하는 것을 보지 않고 시간 차이를 측정하기위한 주요 후보로 만듭니다.

Process::CLOCK_MONOTONIC여기에 사용 된 상수는 모든 최신 Linux, BSD 및 macOS 시스템과 Windows 용 Linux 하위 시스템에서 사용할 수 있습니다. 그러나 "원시"Windows 시스템에서는 아직 사용할 수 없습니다. 여기 에서 Windows (> = Windows Vista, Windows Server 2008)에서 타이머 값을 밀리 초 단위로 반환하는 GetTickCount64대신 시스템 호출을 사용할 수 있습니다 Process.clock_gettime.

Ruby를 사용하면이 함수를 다음과 같이 호출 할 수 있습니다.

require 'fiddle'

# Get a reference to the function once
GetTickCount64 = Fiddle::Function.new(
  Fiddle.dlopen('kernel32.dll')['GetTickCount64'],
  [],
  -Fiddle::TYPE_LONG_LONG # unsigned long long
)

timestamp = GetTickCount64.call / 1000.0
# => 63988.576809828

1
이것은 받아 들여지는 것은 말할 것도없고 받아 들일 수있는 유일한 대답입니다.
Rob Kinyon

OS 지원에 대한 세부 정보를 추가 할 가치가있을 수 있습니다 : SUSv3 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 3.4, macOS 10.12
Guy C

이 솔루션을 사용할 수 있기 전에 원래 질문과 답변이 모두 제공되었습니다. 이것이 유일한 "허용되는"대답이어야하는 이유는 무엇입니까?
CitizenX

13

벤치 마크를 수행하려면 벤치 마크 모듈을 살펴 봐야합니다. 그러나 빠르고 더러운 타이밍 방법으로 다음과 같이 사용할 수 있습니다.

def time
  now = Time.now.to_f
  yield
  endd = Time.now.to_f
  endd - now
end

의 사용은 Time.now.to_fto_i와 달리 초로 잘리지 않습니다.


6
여기에 떠 다니는 시간은 불필요합니다.
Sergio Tulentsev

또한 "endd"의 오타
nightpool

@nightpool end은 키워드 이기 때문에 그렇게 철자가되어 있습니다.
sepp2k

1
그런 다음 좋아요 end_time또는 무언가를하세요. 단어의 철자를 잘못 입력하지 마세요.
그건 엉망입니다


1

absolute_time보석 드롭 인 벤치 마크 교체,하지만 훨씬 더 정확 기본 지침을 사용합니다.


1
또는 ... absolute_time 이상의 창에 더 세분화 할 수 있습니다 보석을 hitimes
rogerdpack

1

또한 코드 블록을 기록하는 간단한 함수를 만들 수 있습니다.

def log_time
  start_at = Time.now

  yield if block_given?

  execution_time = (Time.now - start_at).round(2)
  puts "Execution time: #{execution_time}s"
end

log_time { sleep(2.545) } # Execution time: 2.55s

0

사용하는 경우

date = Time.now.to_i

특히 코드의 작은 덩어리를 타이밍하는 경우 정확하지 않은 초 단위의 시간을 얻습니다.


0

Time.now.to_i1970/01/01에서 전달 된 두 번째 반환 의 사용 . 이것을 알고 당신이 할 수 있습니다

date1 = Time.now.to_f
date2 = Time.now.to_f
diff = date2 - date1

이것 으로 두 번째 크기의 차이가 있습니다 . 밀리 초 단위로 원하는 경우 코드에 추가하십시오.

diff = diff * 1000

2
.to_i정수를 제공하고 밀리 초를 자릅니다. 방금 변경 한 경우 작동합니다.to_f
Ryan Taylor

1
예, Ryan이 말했듯이; 반대표에 대해 사과드립니다. 그러나 이것은 실제로 하나의 찬성표를 가지고 있었고 나는 그것을 반박해야한다고 느꼈습니다. 초 단위 의 정수 시차에 1000을 곱하여 밀리 초를 얻습니까? 어서, MARC.RS, 확실히 당신은 우리를 트롤링했습니다! :-)
앤드류 Hodgkinson

아니, 그냥 내 최고의 노력
MARC.RS

0

루비 메서드 (인스턴스 또는 클래스)를 프로파일 링 할 수있는 보석이 있습니다-https: //github.com/igorkasyanchuk/benchmark_methods .

다음과 같은 코드는 더 이상 없습니다.

t = Time.now
user.calculate_report
puts Time.now - t

이제 다음을 수행 할 수 있습니다.

benchmark :calculate_report # in class

그리고 당신의 방법을 호출하십시오

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