PerfCt.bas
上传用户:bcdefg2008
上传日期:2013-02-28
资源大小:144k
文件大小:5k
源码类别:

Email服务器

开发平台:

Visual Basic

  1. Attribute VB_Name = "modPerfCount"
  2. Option Explicit
  3. Public Declare Function QueryPerformanceCounter Lib "kernel32" _
  4.     (lpPerformanceCount As Currency) As Long
  5. Public Declare Function QueryPerformanceFrequency Lib "kernel32" _
  6. (lpFrequency As Currency) As Long
  7. Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
  8. Private curStart As Currency
  9. Private curFinish As Currency
  10. Private curFreq As Currency
  11. Private fTimeLag As Double
  12. Private fStdError As Double
  13. Private bRunning As Boolean
  14. Private bWarned As Boolean
  15. Public Sub PerfInit()
  16. Dim I As Long
  17. Dim fMillis As Double
  18. Const COUNTS As Long = 1000
  19. Dim fTest As Double
  20.     'get the counter frequency
  21.     
  22.     If QueryPerformanceFrequency(curFreq) = 0 Then
  23.         MsgBox "You are not able to access a Performance Counter, sorry."
  24.         Exit Sub
  25.     End If
  26.     
  27.     'now we need to find out how long it actually takes
  28.     'to make the function calls, so we can subtract by that amount.
  29.     
  30.     fMillis = 0
  31.     fTimeLag = 0
  32.     For I = 1 To COUNTS
  33.         PerfStart
  34.         PerfFinish
  35.         fMillis = fMillis + PerfElapsedInternal
  36.         
  37.     Next
  38.     
  39.     fTest = fMillis / COUNTS
  40.     
  41.     'Here fTimeLag is the mean time that it takes to call PerfStart then
  42.     'PerfFinish, that is, how expensive the function calls are themselves.
  43.     'We need to subtract this amount from our result to get a more accurate
  44.     'number.
  45.     
  46.     fTimeLag = fTest
  47.     
  48.     'Now we are going to see how accurate our calls are by looking at the
  49.     'standard deviation from the mean.  Here the mean function call time
  50.     'will be fTimeLag.
  51.     
  52.     fMillis = 0
  53.     fStdError = 0
  54.     For I = 1 To COUNTS
  55.         PerfStart
  56.         PerfFinish
  57.         
  58.         'compute the square of the distance from the mean
  59.         fMillis = fMillis + (PerfElapsedInternal - fTimeLag) * _
  60.             (PerfElapsedInternal - fTimeLag)
  61.     Next
  62.     
  63.     'now divide by number of iterations and take square root to get std deviation.
  64.     'this is a measure of how accurate this Perf counter really is.
  65.     
  66.     fStdError = Sqr(fMillis / COUNTS)
  67.     
  68.     
  69. End Sub
  70. Public Function PerfTimeLag() As Single
  71.     PerfTimeLag = MakeSignificant(fTimeLag, fStdError)
  72. End Function
  73. Public Function PerfStdError() As Single
  74.     PerfStdError = MakeSignificant(fStdError, fStdError)
  75. End Function
  76. Public Sub PerfStart()
  77.     'We only allow one start/finish session at a time here
  78.     If bRunning Then Exit Sub
  79.     
  80.     'If curFreq is zero then either PerfInit has not yet been called,
  81.     'or there is no performance counter on the equipment.
  82.     
  83.     If curFreq = 0 Then
  84.         If Not bWarned Then
  85.             MsgBox "Please Initialize with PerfInit before calling this Sub"
  86.             bWarned = True
  87.         End If
  88.         Exit Sub
  89.     End If
  90.     
  91.     'Flag the session as being in progress
  92.     bRunning = True
  93.     
  94.     'Save the current count
  95.     QueryPerformanceCounter curStart
  96. End Sub
  97. Public Sub PerfFinish()
  98.     'save the current final count
  99.     QueryPerformanceCounter curFinish
  100.     
  101.     'Flag the session as complete
  102.     bRunning = False
  103. End Sub
  104. Public Function PerfElapsed() As Single
  105.     'Note: for more accurate results, you should call
  106.     'PerfFinish prior to calling PerfElapsed.  If you want
  107.     'to use this to update a progress bar or something, then
  108.     'calling this before PerfFinish might be OK.
  109.     'Check for initialization and/or presence of a performance counter
  110.     If curFreq = 0 Then
  111.         If Not bWarned Then
  112.             MsgBox "Please Initialize with PerfInit before calling this Sub"
  113.             bWarned = True
  114.         End If
  115.         PerfElapsed = 0
  116.         Exit Function
  117.     End If
  118.     
  119.     PerfElapsed = MakeSignificant(PerfElapsedInternal, fStdError)
  120. End Function
  121. Private Function PerfElapsedInternal() As Double
  122. Dim curTest As Currency
  123. Dim fResult As Double
  124.     'Make a quick check if the session is in progress, otherwise
  125.     'use the value we got by calling PerfFinish (the better way)
  126.     
  127.     If bRunning Then
  128.         QueryPerformanceCounter curTest
  129.     Else
  130.         curTest = curFinish
  131.     End If
  132.     
  133.     'Note that we are dividing a Currency by another Currency, so the
  134.     'factor of 10000 is going to cancel out in the division.  Multiply
  135.     '1000 to get milliseconds, and subtract the time lag we found
  136.     'in PerfInit.
  137.     
  138.     fResult = 1000 * (CDbl(curTest) - CDbl(curStart)) / CDbl(curFreq) - fTimeLag
  139.     PerfElapsedInternal = fResult
  140. End Function
  141. Public Function MakeSignificant(fValue As Double, fError As Double) As Single
  142. Dim fLog As Double
  143. Dim fInt As Double
  144.     'This function is used to strip all the bogus digits off a
  145.     'result.  It uses the standard error to do this.
  146.     If fError = 0 Then
  147.         fLog = -4   'arbitrary, so we don't take log of 0
  148.     Else
  149.         fLog = Log10(fError)
  150.     End If
  151.     fInt = Int(fLog)
  152.     If fInt < 0 Then
  153.         MakeSignificant = CSng(Format(fValue, "0." & String$(-fInt, "0")))
  154.     ElseIf fInt = 0 Then
  155.         MakeSignificant = CSng(Format(fValue, "0"))
  156.     Else
  157.         MakeSignificant = (10 ^ fInt) * CSng(Format(fValue / (10 ^ fInt), "0"))
  158.     End If
  159. End Function
  160. Private Function Log10(fValue As Double) As Double
  161.     'log base 10
  162.     Log10 = Log(fValue) / Log(10#)
  163. End Function