VBA 코드의 실행 시간을 어떻게 테스트합니까?


답변:


81

기능이 매우 느리지 않는 한 매우 고해상도 타이머가 필요합니다. 내가 아는 가장 정확한 것은 QueryPerformanceCounter입니다. 더 많은 정보를 원하시면 구글을하세요. 다음을 클래스에 밀어 넣고 CTimer말한 다음 인스턴스를 전역 어딘가에 만들고 호출 .StartCounter하고.TimeElapsed

Option Explicit

Private Type LARGE_INTEGER
    lowpart As Long
    highpart As Long
End Type

Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long

Private m_CounterStart As LARGE_INTEGER
Private m_CounterEnd As LARGE_INTEGER
Private m_crFrequency As Double

Private Const TWO_32 = 4294967296# ' = 256# * 256# * 256# * 256#

Private Function LI2Double(LI As LARGE_INTEGER) As Double
Dim Low As Double
    Low = LI.lowpart
    If Low < 0 Then
        Low = Low + TWO_32
    End If
    LI2Double = LI.highpart * TWO_32 + Low
End Function

Private Sub Class_Initialize()
Dim PerfFrequency As LARGE_INTEGER
    QueryPerformanceFrequency PerfFrequency
    m_crFrequency = LI2Double(PerfFrequency)
End Sub

Public Sub StartCounter()
    QueryPerformanceCounter m_CounterStart
End Sub

Property Get TimeElapsed() As Double
Dim crStart As Double
Dim crStop As Double
    QueryPerformanceCounter m_CounterEnd
    crStart = LI2Double(m_CounterStart)
    crStop = LI2Double(m_CounterEnd)
    TimeElapsed = 1000# * (crStop - crStart) / m_crFrequency
End Property

2
저는 이것을 Excel VBA에서 구현했습니다 (KB 문서 support.microsoft.com/kb/172338 에서 언급 한대로 오버 헤드에 추가 했습니다. 훌륭하게 작동했습니다. 감사합니다.
Lance Roberts

2
고마워요, 이것도 저에게 잘 작동합니다. TimeElapsed()결과를 밀리 초 단위로 제공합니다. 완벽한 정확도보다 오버 헤드 계산에서 버벅 거림이 미치는 영향에 대해 더 걱정했기 때문에 오버 헤드 보상을 구현하지 않았습니다.
저스틴

2
그것은 (관리 할 코드 줄에서) 많이 들었습니다. ~ 10ms의 정확도로 살 수 있다면 아래 @Kodak의 대답은 한 줄의 코드에서 동일한 것을 제공합니다 ( GetTickCountkernel32에서 가져 오기 ).
BrainSlugs83 2014 년

StartCounterAnd를 어떻게 사용 TimeElapsed합니까? 처음에는 인스턴스 타이머를 CTimer했고 서브가 시작된 후 With StartCounter방금 썼는데 응답이 나왔습니다 . 나는 물론 개체가 설정되지 않았다고 말할 때 . .StartCounter.TimeElapsedInvalid use of property.StartCounter
Monica에 대한 Revolucion

Excel 2010 : Declare PtrSafe Function stackoverflow.com/questions/21611744/…
user3226167

48

VBA의 타이머 기능은 자정 이후 경과 된 시간 (초의 1/100 초)을 제공합니다.

Dim t as single
t = Timer
'code
MsgBox Timer - t

18
그것은 작동하지 않을 것입니다-당신은 그런 평균을 취하는 것에서 더 많은 해결책을 얻을 수 없습니다.
Andrew Scagnelli 2009-06-04

4
그래도 VBA에서 성능을 측정하는 경우 1/100 초 해상도를 얻는 것은 나쁘지 않습니다. -타이밍 호출 만 호출하면 몇 ms가 걸릴 수 있습니다. 통화가 너무 빠르기 때문에 시간을 맞추기 위해 많은 해결 방법이 필요한 경우 해당 통화에 대한 성능 데이터가 필요하지 않을 수 있습니다.
BrainSlugs83 2014 년

1
참고 : Mac에서 타이머는 1 초까지만 정확합니다. 자정 이전에 시작하여 자정 이후에 끝나는 경우 음수가 될 수 있습니다
TmTron

32

스톱워치처럼 시간을 반환하려는 경우 시스템 시작 이후 시간을 밀리 초 단위로 반환하는 다음 API를 사용할 수 있습니다.

Public Declare Function GetTickCount Lib "kernel32.dll" () As Long
Sub testTimer()
Dim t As Long
t = GetTickCount

For i = 1 To 1000000
a = a + 1
Next

MsgBox GetTickCount - t, , "Milliseconds"
End Sub

http://www.pcreview.co.uk/forums/grab-time-milliseconds-included-vba-t994765.html 이후 (winmm.dll의 timeGetTime이 작동하지 않았고 QueryPerformanceCounter가 필요한 작업에 너무 복잡했기 때문에)


이것은 훌륭한 대답입니다. 참고 : 반환 된 데이터 의 정밀도 는 밀리 초이지만, 카운터는 MSDN : msdn.microsoft.com을 통해 약 1/100 초 (즉, 10 ~ 16ms 정도 차이가 날 수 있음 )까지만 정확 합니다. / ko-kr / library / windows / desktop /…
BrainSlugs83

해상도가 타이머와 여기 같은 경우 흠, 그럼 내가 타이머와 함께 갈 것
코닥

Public Declare Function ...부분 은 무엇입니까 ? 광산의 하단에 코드를 추가 할 때 오류가 생성
모니카에 대한 혁명의

이 공개 선언을 모듈의 맨 위로 이동해야합니다
Kodak


3
Sub Macro1()
    Dim StartTime As Double
    StartTime = Timer

        ''''''''''''''''''''
            'Your Code'
        ''''''''''''''''''''
    MsgBox "RunTime : " & Format((Timer - StartTime) / 86400, "hh:mm:ss")
End Sub

산출:

런타임 : 00:00:02


2

우리는 수년 동안 밀리 초 정확도를 위해 winmm.dll의 timeGetTime 기반 솔루션을 사용해 왔습니다. 참조 http://www.aboutvb.de/kom/artikel/komstopwatch.htm를

이 기사는 독일어로되어 있지만 다운로드 코드 (dll 함수 호출을 래핑하는 VBA 클래스)는 기사를 읽지 않고도 사용하고 이해할 수있을만큼 간단합니다.


0

소수점 2 자리가있는 초 :

Dim startTime As Single 'start timer
MsgBox ("run time: " & Format((Timer - startTime) / 1000000, "#,##0.00") & " seconds") 'end timer

초 형식

밀리 초 :

Dim startTime As Single 'start timer
MsgBox ("run time: " & Format((Timer - startTime), "#,##0.00") & " milliseconds") 'end timer

밀리 초 형식

쉼표 구분자를 사용한 밀리 초 :

Dim startTime As Single 'start timer
MsgBox ("run time: " & Format((Timer - startTime) * 1000, "#,##0.00") & " milliseconds") 'end timer

쉼표 구분자를 사용한 밀리 초

제가 그랬던 것처럼 소수점 이하 2 자리까지의 초 단위로 포맷 된 간단한 타이머를 찾는 사람을 위해 여기에 남겨 두세요. 이것들은 내가 사용하는 짧고 달콤한 작은 타이머입니다. 하위 또는 함수의 시작 부분에서 한 줄의 코드 만 차지하고 끝에서 다시 한 줄의 코드를 차지합니다. 이것은 엄청나게 정확한 것은 아닙니다. 저는 개인적으로 1/100 초 미만의 것은 신경 쓰지 않지만, 밀리 초 타이머는이 3 번의 가장 정확한 실행 시간을 제공 할 것입니다. 자정을 넘어가는 동안 실행되는 경우, 드문 경우이지만 참고로 잘못된 판독 값을 얻을 수 있습니다.


타이머의 해상도는 10ms이므로 첫 번째 만 유용합니다.
구스타프
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.