Страницы: 1
RSS
Как правильно определить время выполнения кода?
 
Попробовал поработать с таймером, определить время выполнения кода.
Код
 Sub TestTimer()
  Dim TimeBeg As Date, TimeEnd As Date, TimeWork As Date, i, j, res
  TimeBeg = Timer
  For i = 0 To 100000
    res = res + 1
  Next i
  TimeEnd = Timer
  TimeWork = TimeEnd - TimeBeg
  Debug.Print TimeWork
End Sub
в результате получаю 0:11:15. Возникли следующие вопросы:
а) как трактовать эти значения? Это 11 милисекунд и 15 микросекунд?
б) как вывести данные в мили и микросекундах? Файл прикрепил.
 
И Вам тоже здравствуйте.

Возникли следующие вопросы:
1) в чём проблема нажать F1 в VBE на слове Timer и прочитать справку по функции? Там ровно одна строчка описания и ровно одна строчка примечания. И пример кода есть. В том числе - как нужно объявлять переменные, которым будут присваиваться значения функции.
2) отпадает, если внимательно прочитать справку.
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Timer As Single вроде бы... но можно и просто Dim TimeWork... сам начинает считать с нуля (если задаётся в начале кода) - всегда думала так... попробуйте так
Код
Sub TestTimer()
  Dim TimeWork, i, j, res
  TimeWork = Timer
  For i = 0 To 100000
    res = res + 1
  Next i
  
  Debug.Print Timer - TimeWork & " секунд"
End Sub
хотя по справке означает " fractional portions of a second" ??
(поправила код)
Изменено: JeyCi - 14.02.2015 20:03:46
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
 
Цитата
JeyCi пишет: fractional portions
дробная часть, очевидно.
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
кстати. на всякий случай - использование функции Timer может дать неверные результаты, если между вызовами происходит смена суток.
ну или это надо учитывать с помощью дополнительных проверок.

впрочем, и это тоже очевидно из справки:
Цитата
the number of seconds elapsed since midnight
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
ikki спасибо за уточнение... а насчёт "дробного" - пока не поправила код, долго не верила себе, что знаю английский (выдавал что-то вроде 7235,21)... теперь порядок
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
 
А вы понимаете, что такое микросекунда? Ответ: это одна миллионная часть секунды. Такую точность в измерениях едва ли можно получить. Да и для повседневных целей такая точность, в общем-то, и не нужна.
Для профилирования кода я использую класс StopWatch, который подсмотрел у Walkenbach'a.
Stopwatch инкапсулирует GetTickCount (вроде так, поправьте, если что). Вот код класса:
Код
Option Explicit

Private mlngStart As Long
Private Declare Function GetTickCount Lib "kernel32" () As Long 

Public Sub StartTimer()
   mlngStart = GetTickCount
End Sub 

Public Function EndTimer() As Long
   EndTimer = (GetTickCount - mlngStart)
End Function
Далее в теле процедуры использую примерно вот так:
Код
Sub test() 
   Dim sw as New StopWatch 
   sw.StartTimer  

   Тело процедуры 

   MsgBox "Done. Elapsed time: " & Format(sw.EndTimer / 1000 / 60 / 60 / 24, "hh:mm:ss")
End Sub 
Чтобы получить точно до миллисекунд, просто добавляем к MsgBox остаток от деления sw.EndTimer на 1000.
С уважением,
Федор/Все_просто
 
что-то как-то не заценил я реальную необходимость заводить целый класс для GetTickCount...
достаточно объявить функцию публично в любом модуле - и никакого класса не надо.
думаю, Уокенбах использовал этот простой пример для демонстрации принципов работы с модулями классов.

личное мнение, конечно.
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
ikki, уже и не помню, что он этим хотел объяснить.
Я уже привык, поэтому не обращаю внимания. Добавил в проект add-in'а собственного разлива, и импортирую себе в удовольствие, где нужно, просто перетаскивая соответствующий модуль в нужный проект. Если это не устраивает, можно сделать модуль класса PublicNotCreatable и реферировать через Tools/References или через CreateObject.  
С уважением,
Федор/Все_просто
 
ну, в принципе, если удобно - почему бы и нет?
кстати, возможно имеет смысл добавить пару свойств?
например, sEndTimer и dEndTimer - возврат в виде строки "hh:mm:ss" и в долях суток
тогда использование объекта было бы лаконичней и наглядней.
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
ikki, интересное предложение. Странно, что раньше до этого руки не дошли. :)
С уважением,
Федор/Все_просто
 
А вот эта строчка
Код
Private Declare Function GetTickCount Lib "kernel32" () As Long

только для 32-бит? в 64-бит будет работать?
 
Есть мощная тема по разным таймерам: http://www.planetaexcel.ru/forum/?PAGE_NAME=read&FID=1&TID=46336
 
В свое время для этой темы измерения быстродействия утащил функцию MicroTimer, так как разрешения обычной Timer() не хватало для анализа одной операции типа Find
Ссылку на эту функцию тогда же дал, кстати, Все_просто
Код
#If VBA7 Then
Private Declare PtrSafe Function getFrequency Lib "kernel32" Alias _
"QueryPerformanceFrequency" (cyFrequency As Currency) As Long
Private Declare PtrSafe Function getTickCount Lib "kernel32" Alias _
"QueryPerformanceCounter" (cyTickCount As Currency) As Long
#Else
Private Declare Function getFrequency Lib "kernel32" Alias _
"QueryPerformanceFrequency" (cyFrequency As Currency) As Long
Private Declare Function getTickCount Lib "kernel32" Alias _
"QueryPerformanceCounter" (cyTickCount As Currency) As Long
#End If
Public Function MicroTimer() As Double
'
' returns seconds
' uses Windows API calls to the high resolution timer
'
Dim cyTicks1 As Currency
Dim cyTicks2 As Currency
Static cyFrequency As Currency
'
MicroTimer = 0
'
' get frequency
'
If cyFrequency = 0 Then getFrequency cyFrequency
'
' get ticks
'
getTickCount cyTicks1
getTickCount cyTicks2
If cyTicks2 < cyTicks1 Then cyTicks2 = cyTicks1
'
' calc seconds
'
If cyFrequency Then MicroTimer = cyTicks2 / cyFrequency
End Function
F1 творит чудеса
Страницы: 1
Читают тему
Наверх