คุณทดสอบเวลาทำงานของรหัส VBA ได้อย่างไร?


95

มีโค้ดใน VBA หรือไม่ที่ฉันสามารถรวมฟังก์ชั่นที่จะแจ้งให้ฉันทราบเวลาที่ใช้ในการทำงานเพื่อที่ฉันจะได้เปรียบเทียบเวลาทำงานที่แตกต่างกันของฟังก์ชันได้หรือไม่

คำตอบ:


82

เว้นแต่ว่าฟังก์ชันของคุณจะช้ามากคุณจะต้องใช้ตัวจับเวลาที่มีความละเอียดสูงมาก QueryPerformanceCounterหนึ่งที่ถูกต้องที่สุดที่ฉันรู้คือ Google มันสำหรับข้อมูลเพิ่มเติม. ลองผลักดันสิ่งต่อไปนี้ลงในชั้นเรียนเรียก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 ด้านล่างจะให้สิ่งเดียวกันในโค้ดบรรทัดเดียว (นำเข้าGetTickCountจาก kernel32)
BrainSlugs83

คุณใช้อย่างไรStartCounterและTimeElapsed? ฉันไม่ได้เป็นตัวอย่างของการจับเวลาCTimerที่จุดเริ่มต้นและWith StartCounterผมเพิ่งเขียน.StartCounterหลังจากย่อยของฉันเริ่มต้นและและมันก็ตอบฉัน.TimeElapsed Invalid use of propertyเมื่อฉันปล่อยให้.StartCounterอยู่คนเดียวมันบอกฉันว่าวัตถุไม่ได้ตั้ง
Revolucion for Monica

สำหรับ excel 2010: Declare PtrSafe Function stackoverflow.com/questions/21611744/…
user3226167

49

ฟังก์ชัน Timer ใน VBA ช่วยให้คุณทราบจำนวนวินาทีที่ผ่านไปตั้งแต่เที่ยงคืนถึง 1/100 วินาที

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

18
นั่นจะไม่ได้ผล - คุณไม่สามารถรับความละเอียดได้มากขึ้นจากการหาค่าเฉลี่ยแบบนั้น
Andrew Scagnelli

4
ถึงกระนั้นหากคุณกำลังวัดประสิทธิภาพใน VBA การรับ 1/100 ของความละเอียดวินาทีก็ไม่เลว - การเรียกใช้เวลาโทรเพียงอย่างเดียวอาจใช้เวลาสองถึงสามมิลลิวินาที หากการโทรนั้นเร็วมากจนคุณต้องใช้ความละเอียดมากพอสมควรคุณอาจไม่ต้องการข้อมูลประสิทธิภาพเกี่ยวกับการโทรนั้น
BrainSlugs83

1
หมายเหตุ: บน Mac ตัวจับเวลาจะแม่นยำเพียงหนึ่งวินาที - และอาจได้รับตัวเลขติดลบหากเริ่มก่อนเที่ยงคืนและสิ้นสุดหลังเที่ยงคืน
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 (เนื่องจาก timeGetTime ใน winmm.dll ไม่ทำงานสำหรับฉันและ QueryPerformanceCounter ซับซ้อนเกินไปสำหรับงานที่ต้องการ)


นี่คือคำตอบที่ยอดเยี่ยม หมายเหตุ: ความแม่นยำของข้อมูลที่ส่งคืนอยู่ในหน่วยมิลลิวินาทีอย่างไรก็ตามตัวนับมีความแม่นยำเพียงประมาณ 1/100 วินาที (นั่นคืออาจปิดได้ 10 ถึง 16 มิลลิวินาที) ผ่าน MSDN: msdn.microsoft.com / en-us / library / windows / desktop / …
BrainSlugs83

อืมถ้าความละเอียดตรงนี้กับ Timer ฉันจะใช้ Timer
Kodak

คือPublic Declare Function ...ส่วนไหน? มันสร้างข้อผิดพลาดเมื่อเพิ่มรหัสของคุณที่ด้านล่างของฉัน
Revolucion for Monica

คุณต้องย้ายการประกาศสาธารณะนี้ไปที่ด้านบนสุดของโมดูลของคุณ
Kodak

4

สำหรับ newbees ลิงก์เหล่านี้จะอธิบายวิธีการสร้างโปรไฟล์อัตโนมัติของส่วนย่อยทั้งหมดที่คุณต้องการตรวจสอบเวลา:

http://www.nullskull.com/a/1602/profiling-and-optimizing-vba.aspx

http://sites.mcpher.com/share/Home/excelquirks/optimizationlink ดู procProfiler.zip ในhttp://sites.mcpher.com/share/Home/excelquirks/downlable-items


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

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

เอาท์พุต:

RunTime: 00:00:02 น


2

เราใช้วิธีแก้ปัญหาตาม timeGetTime ใน winmm.dll เพื่อความแม่นยำในระดับมิลลิวินาทีเป็นเวลาหลายปี ดูhttp://www.aboutvb.de/kom/artikel/komstopwatch.htm

บทความนี้เป็นภาษาเยอรมัน แต่โค้ดในการดาวน์โหลด (คลาส VBA ที่ตัดการเรียกฟังก์ชัน dll) นั้นง่ายพอที่จะใช้และทำความเข้าใจโดยไม่สามารถอ่านบทความได้


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 ช่องว่างทศนิยมเหมือนฉัน นี่คือตัวจับเวลาที่สั้นและไพเราะที่ฉันชอบใช้ โดยใช้โค้ดเพียงบรรทัดเดียวที่จุดเริ่มต้นของ sub หรือ function และโค้ดอีกบรรทัดในตอนท้าย สิ่งเหล่านี้ไม่ได้หมายความว่าจะแม่นยำอย่างบ้าคลั่งโดยทั่วไปฉันไม่สนใจอะไรเลยแม้แต่ 1/100 วินาทีเป็นการส่วนตัว แต่ตัวจับเวลามิลลิวินาทีจะทำให้คุณได้เวลาวิ่งที่แม่นยำที่สุดใน 3 สิ่งนี้ฉันยังอ่านคุณ สามารถอ่านค่าที่ไม่ถูกต้องได้หากเกิดขึ้นขณะวิ่งข้ามเที่ยงคืนซึ่งเป็นตัวอย่างที่หายาก แต่เป็นเพียง FYI


อันแรกเท่านั้นที่มีประโยชน์เนื่องจาก Timer มีความละเอียด 10ms
Gustav
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.