Если вы хотите большей точности, используйте %N
с date
(и используйте bc
для diff, потому что $(())
обрабатывает только целые числа).
Вот как это сделать:
start=$(date +%s.%N)
# do some stuff here
dur=$(echo "$(date +%s.%N) - $start" | bc)
printf "Execution time: %.6f seconds" $dur
Пример:
start=$(date +%s.%N); \
sleep 0.1s; \
dur=$(echo "$(date +%s.%N) - $start" | bc); \
printf "Execution time: %.6f seconds\n" $dur
Результат:
Execution time: 0.104623 seconds
Да, вы можете использовать Win32 API:
DWORD WINAPI GetTickCount(void);
Чтобы импортировать его в VB6, объявите его следующим образом:
Private Declare Function GetTickCount Lib "kernel32" () As Long
Вызовите его перед операцией и после нее, а затем вычислите разницу во времени. .
Вы также можете рассмотреть возможность использования другого подхода. Попробуйте вызвать свои подпрограммы из цикла с достаточным количеством итераций, чтобы получить измеримую разницу во времени.
Поместите следующий код в класс секундомера:
Option Explicit
Private Declare Function QueryPerformanceCounter Lib "Kernel32" (X As Currency) As Boolean
Private Declare Function QueryPerformanceFrequency Lib "Kernel32" (X As Currency) As Boolean
Private m_startTime As Currency
Private m_freq As Currency
Private m_overhead As Currency
Public Sub start()
QueryPerformanceCounter m_startTime
End Sub
Public Function ElapsedSeconds() As Double
Dim currentTime As Currency
QueryPerformanceCounter currentTime
ElapsedSeconds = (currentTime - m_startTime - m_overhead) / m_freq
End Function
Public Function ElapsedMilliseconds() As Double
ElapsedMilliseconds = ElapsedSeconds * 1000
End Function
Private Sub Class_Initialize()
QueryPerformanceFrequency m_freq
Dim ctr1 As Currency
Dim ctr2 As Currency
QueryPerformanceCounter ctr1
QueryPerformanceCounter ctr2
m_overhead = ctr2 - ctr1
End Sub
Вы можете использовать его следующим образом:
Dim sw as StopWatch
sw = New StopWatch
sw.Start
' Code you want to time
Debug.Print "Code took " & sw.ElapsedMilliseconds " ms"
Вы можете использовать два Win32 API:
Они используют LARGE_INTEGER для представления 64-битных чисел.
Вы можете попробовать использовать System :: Diagnostics :: Stopwatch
Imports System.Diagnostics
Dim sw As New Stopwatch()
sw.Start()
// do something
LOG("Elapsed " + sw.ElapsedMilliseconds + " ms")
Код и объяснение в статье базы знаний MSDN Q172338 Как использовать QueryPerformanceCounter to Time Code
Есть история Томаса Эдисона, где он берет интервью у некоторых перспективных инженеров.
Он просит их определить объем лампочки. Кандидат А измеряет его, а затем использует формулу для объема сферы, другую формулу для объема шеи и так далее. Кандидат B наполняет его водой и переливает в мерную чашку. Как вы думаете, кто получил эту работу?
Выполните ее 1000 раз и посмотрите на свои часы до и после. Секунды = миллисекунды.
Я всегда использую это где-нибудь в модуле (хотя может быть в классе). Этот код позволяет поддерживать до шести таймеров с высокой точностью:
Option Explicit
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As Currency) As Long
Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As Currency) As Long
Private cFrequency As Currency
Private cCounters(0 To 5) As Currency
Public Sub StartCounter(Optional lCounterIndex As Long)
QueryPerformanceFrequency cFrequency
QueryPerformanceCounter cCounters(lCounterIndex)
End Sub
Public Function GetCounter(Optional lCounterIndex As Long) As Double
Dim cCount As Currency
QueryPerformanceFrequency cFrequency
QueryPerformanceCounter cCount
GetCounter = Format$((cCount - cCounters(lCounterIndex) - CCur(0.0008)) / cFrequency, "0.000000000")
End Function
Public Function Scientific(ByVal dValue As Double) As String
Dim lMultiplier As Long
Dim vNames As Variant
lMultiplier = 5
vNames = Array("peta", "tera", "giga", "mega", "kilo", "", "milli", "micro", "nano", "pico", "femto")
If Abs(dValue) < 1 Then
While Abs(dValue) < 1
dValue = dValue * 1000
lMultiplier = lMultiplier + 1
Wend
ElseIf Abs(dValue) >= 1000 Then
While Abs(dValue) >= 1000
dValue = dValue / 1000
lMultiplier = lMultiplier - 1
Wend
End If
Scientific = Format$(dValue, "0.000") & " " & vNames(lMultiplier)
End Function