Для точного измерения времени под Windows в Free PASCAL используется функция QueryPerformanceCounter. Ниже показан пример использования данной функции:
program Time;
uses
Windows;
var
start, finish, res: int64;
begin
QueryPerformanceFrequency(res); {Вызывается один раз в начале программы}
QueryPerformanceCounter(start);
{Участок кода, для которого будет замеряться время выполнения}
QueryPerformanceCounter(finish);
writeln(‘Затрачено ‘, (finish — start) / res, ‘ секунд’ );
end.
В PASCAL ABC.NET необходимо использовать встроенный класс Stopwatch. Пример кода приведен ниже (код взят из примеров интегрированной среды разработки PABCWork.NETSamplesNETLibrariesOther).
program Time;
var
ts : System.TimeSpan;
// Sto9pwatch — класс высокоточного таймера (с точностью до 0.001 с)
begin
var stopWatch := new System.Diagnostics.Stopwatch;
stopWatch.Start;
{Участок кода, для которого будет замеряться время выполнения}
stopWatch.Stop;
ts := stopWatch.Elapsed;
writelnFormat(‘Время работы: {0:00}:{1:00}:{2:00}.{3:000}’,ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
end.
Most of the softwares you write need implementing some form of date functions returning current date and time. Dates are so much part of everyday life that it becomes easy to work with them without thinking. Pascal also provides powerful tools for date arithmetic that makes manipulating dates easy. However, the actual name and workings of these functions are different for different compilers.
Getting the Current Date & Time
Pascal’s TimeToString function gives you the current time in a colon(: ) delimited form. The following example shows how to get the current time −
program TimeDemo; uses sysutils; begin writeln ('Current time : ',TimeToStr(Time)); end.
When the above code was compiled and executed, it produces the following result −
Current time : 18:33:08
The Date function returns the current date in TDateTime format. The TDateTime is a double value, which needs some decoding and formatting. The following program demonstrates how to use it in your program to display the current date −
Program DateDemo; uses sysutils; var YY,MM,DD : Word; begin writeln ('Date : ',Date); DeCodeDate (Date,YY,MM,DD); writeln (format ('Today is (DD/MM/YY): %d/%d/%d ',[dd,mm,yy])); end.
When the above code was compiled and executed, it produces the following result −
Date: 4.111300000000000E+004 Today is (DD/MM/YY):23/7/2012
The Now function returns the current date and time −
Program DatenTimeDemo; uses sysutils; begin writeln ('Date and Time at the time of writing : ',DateTimeToStr(Now)); end.
When the above code was compiled and executed, it produces the following result −
Date and Time at the time of writing : 23/7/2012 18:51:
Free Pascal provides a simple time stamp structure named TTimeStamp, which has the following format −
type TTimeStamp = record Time: Integer; Date: Integer; end;
Various Date & Time Functions
Free Pascal provides the following date and time functions −
Sr.No. | Function Name & Description |
---|---|
1 |
function DateTimeToFileDate(DateTime: TDateTime):LongInt; Converts DateTime type to file date. |
2 |
function DateTimeToStr( DateTime: TDateTime):; Constructs string representation of DateTime |
3 |
function DateTimeToStr(DateTime: TDateTime; const FormatSettings: TFormatSettings):; Constructs string representation of DateTime |
4 |
procedure DateTimeToString(out Result: ;const FormatStr: ;const DateTime: TDateTime); Constructs string representation of DateTime |
5 |
procedure DateTimeToString(out Result: ; const FormatStr: ; const DateTime: TDateTime; const FormatSettings: TFormatSettings); Constructs string representation of DateTime |
6 |
procedure DateTimeToSystemTime(DateTime: TDateTime; out SystemTime: TSystemTime); Converts DateTime to system time |
7 |
function DateTimeToTimeStamp( DateTime: TDateTime):TTimeStamp;Converts DateTime to timestamp |
8 |
function DateToStr(Date: TDateTime):; Constructs string representation of date |
9 |
function DateToStr(Date: TDateTime; const FormatSettings: TFormatSettings):; Constructs string representation of date |
10 |
function Date: TDateTime; Gets current date |
11 |
function DayOfWeek(DateTime: TDateTime):Integer; Gets day of week |
12 |
procedure DecodeDate(Date: TDateTime; out Year: Word; out Month: Word; out Day: Word); Decodes DateTime to year month and day |
13 |
procedure DecodeTime(Time: TDateTime; out Hour: Word; out Minute: Word; out Second: Word; out MilliSecond: Word); Decodes DateTime to hours, minutes and seconds |
14 |
function EncodeDate(Year: Word; Month: Word; Day: Word):TDateTime; Encodes year, day and month to DateTime |
15 |
function EncodeTime(Hour: Word; Minute: Word; Second: Word; MilliSecond: Word):TDateTime; Encodes hours, minutes and seconds to DateTime |
16 |
function FormatDateTime(const FormatStr: ; DateTime: TDateTime):; Returns string representation of DateTime |
17 |
function FormatDateTime(const FormatStr: ; DateTime: TDateTime; const FormatSettings: TFormatSettings):; Returns string representation of DateTime |
18 |
function IncMonth(const DateTime: TDateTime; NumberOfMonths: Integer = 1):TDateTime; Adds 1 to month |
19 |
function IsLeapYear(Year: Word):Boolean; Determines if year is leap year |
20 |
function MSecsToTimeStamp(MSecs: Comp):TTimeStamp; Converts number of milliseconds to timestamp |
21 |
function Now: TDateTime; Gets current date and time |
22 |
function StrToDateTime(const S:):TDateTime; Converts string to DateTime |
23 |
function StrToDateTime(const s: ShortString; const FormatSettings: TFormatSettings):TDateTime; Converts string to DateTime |
24 |
function StrToDateTime(const s: AnsiString; const FormatSettings: TFormatSettings):TDateTime; Converts string to DateTime |
25 |
function StrToDate(const S: ShortString):TDateTime; Converts string to date |
26 |
function StrToDate(const S: Ansistring):TDateTime; Converts string to date |
27 |
function StrToDate(const S: ShortString; separator: Char):TDateTime; Converts string to date |
28 |
function StrToDate(const S: AnsiString; separator: Char):TDateTime; Converts string to date |
29 |
function StrToDate(const S: ShortString; const useformat: ; separator: Char):TDateTime; Converts string to date |
30 |
function StrToDate(const S: AnsiString; const useformat: ; separator: Char):TDateTime; Converts string to date |
31 |
function StrToDate(const S: PChar; Len: Integer; const useformat: ; separator: Char = #0):TDateTime; Converts string to date |
32 |
function StrToTime(const S: Shortstring):TDateTime; Converts string to time |
33 |
function StrToTime(const S: Ansistring):TDateTime; Converts string to time |
34 |
function StrToTime(const S: ShortString; separator: Char):TDateTime; Converts string to time |
35 |
function StrToTime(const S: AnsiString; separator: Char):TDateTime; Converts string to time |
36 |
function StrToTime(const S: ; FormatSettings: TFormatSettings):TDateTime; Converts string to time |
37 |
function StrToTime(const S: PChar; Len: Integer; separator: Char = #0):TDateTime; Converts string to time |
38 |
function SystemTimeToDateTime(const SystemTime: TSystemTime):TDateTime; Converts system time to datetime |
39 |
function TimeStampToDateTime(const TimeStamp: TTimeStamp):TDateTime; Converts time stamp to DateTime |
40 |
function TimeStampToMSecs(const TimeStamp: TTimeStamp):comp; Converts Timestamp to number of milliseconds |
41 |
function TimeToStr(Time: TDateTime):; Returns string representation of Time |
42 |
function TimeToStr(Time: TDateTime; const FormatSettings: TFormatSettings):; Returns string representation of Time |
43 |
function Time: TDateTime; Get current time |
The following example illustrates the use of some of the above functions −
Program DatenTimeDemo; uses sysutils; var year, month, day, hr, min, sec, ms: Word; begin writeln ('Date and Time at the time of writing : ',DateTimeToStr(Now)); writeln('Today is ',LongDayNames[DayOfWeek(Date)]); writeln; writeln('Details of Date: '); DecodeDate(Date,year,month,day); writeln (Format ('Day: %d',[day])); writeln (Format ('Month: %d',[month])); writeln (Format ('Year: %d',[year])); writeln; writeln('Details of Time: '); DecodeTime(Time,hr, min, sec, ms); writeln (format('Hour: %d:',[hr])); writeln (format('Minutes: %d:',[min])); writeln (format('Seconds: %d:',[sec])); writeln (format('Milliseconds: %d:',[hr])); end.
When the above code was compiled and executed, it produced the following result:
Date and Time at the time of writing : 7/24/2012 8:26: Today is Tuesday Details of Date: Day:24 Month:7 Year: 2012 Details of Time: Hour: 8 Minutes: 26 Seconds: 21 Milliseconds: 8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
rogram Tower_of_hanoi; uses CRT; procedure Hanoi (n : integer; x, y, z : char); begin if n <> 0 then begin Hanoi (n - 1, x, z, y); writeLn ('Перемещаем диск ', n, ' c ', x, ' на ', y); Hanoi (n - 1, z, y, x) end end; var disk : integer; begin ClrScr; write ('Сколько дисков ?'); readLn (disk); GetTime(hour,min,sec,hund);//определяем время начала программы writeln(hour,':',min,':',sec,':',hund); t1:=sec*100+min*6000+hund; Hanoi (disk, 'X', 'Y', 'Z') GetTime(hour,min,sec,hund);//время окончания writeln(hour,':',min,':',sec,':',hund); t2:=sec*100+min*6000+hund;; t:=t2-t1;//прошло времени end. |
Как замерять время выполнения кода?
, Например сколько времени выполняется алгоритм
- Подписаться на тему
- Сообщить другу
- Скачать/распечатать тему
|
|
Самым простым способом является одновременно самый очевидный: В паскале есть стандартная процедура модуля Dos — GetTime. Её параметрамы должны быть обязательно переменные. После её выполнения в этих переменных будет содержаться время того момента, когда выполнится эта процедура:
Используя эту процедуру мы можем занести в переменные время до выполнения нужного нам действия, и в другие переменные время после выполнения нужного нам действия. Чтобы посчитать разницу нужно перевести время до выполнения и время после выполнения к количеству сотых частей секунды. Нельзя напрямую сравнивать к примеру просто секунды. Почему? uses dos; var h1,m1,s1,t1:word; h2,m2,s2,t2:word; d:longint; begin gettime(h1,m1,s1,t1); … {любое действие, продолжительность которого измеряем} gettime(h2,m2,s2,t2); {вычислим время выполнения d — результат будет в сотых долях секунды} d:=(longint(h2)*360000+longint(m2)*6000+s2*100+t2)- {количество сотых долей секунды после выполнения} (longint(h1)*360000+longint(m1)*6000+s1*100+t1); {их количество до выполнения действия} writeln(‘Действие выполнялось ‘,d/100:0:2,’ секунды’); end. П.С. Следует добавить, что хотя этот способ и является самым простым, он отнюдь не самый точный, поскольку во время замера входит так же время выполнения процедуры GetTime, и кроме того это время может зависеть от состояния Директив компилятора. P.P.S: function fGetTime: LongInt; var hr, min, sec, sec_100: word; begin GetTime(hr, min, sec, sec_100); fGetTime := longint(hr)*360000 + longint(min)*6000 + sec*100 + sec_100; end; { и работать с ней: } var before, after: longint; begin before := fGetTime; … after := fGetTime; writeln(‘Действие выполнялось ‘, (after — before) / 100:0:2,’ секунды’) end; V877 Сообщение отредактировано: volvo877 — 01.09.08, 07:35 |
Visitor |
|
Совсем забыл, что хотел запостить Для процессоров выше i486 существует способ очень точно сравнить время выполнения двух участков кода — ето встроенный в процессор счетчик тактов. Ниже приведены два исходника — процедура, считывающая значение етого счетчика, и пример ее использования на BP7. .MODEL LARGE .CODE .386c PUBLIC READTSC READTSC PROC FAR enter 0, 0 push ds db 0fh, 31h; RDTSC opcode mov bx, ss:[bp+8] mov ds, bx mov bx, ss:[bp+6] mov [bx], eax mov [bx+4], edx pop ds leave retf 4 READTSC ENDP END sample.pas {$N+} procedure ReadTSC(Var counter : Comp); far; external; {$L tsc.obj} Var a1, a2, a3 : Comp; begin ReadTSC(a1); Writeln(‘Working :)’); ReadTSC(a2); Writeln(a1:20:0, ‘, ‘, a2:20:0, ‘, ‘, (a2-a1):20:0) end. В прикрепленном файле то же самое, tsc.asm оттранслирован. P.S. Обратите внимание и сделайте выводы, как много времени занимает вывод на екран. |
Vesper |
|
Если не хочется подключать модуль DOS, замерить время можно с помощью взятия значения напрямую из памяти по адресу $0046C (4 байта). Там хранится число «тиков» встроенных часов реального времени, которые тикают 18.54 раз в секунду. И именно оттуда тащат его функции модуля. procedure bogusprocedure;near; assembler; asm end; var int08save:pointer; int08handler_count:longint; int08handler_lessercount:word; int08handler_tickin:boolean; procedure int08handler;assembler;{no sense of far, it’s int handler, so must have iret inside} asm sti push ax push dx push ds mov ax,seg @data mov ds,ax {loading DS, probably it’s changed} mov al,int08handler_tickin or al,al je @hnd_l1 {if not tickin jump forward} db 66h inc word ptr int08handler_count @hnd_l1: dec int08handler_lessercount jne @hnd_l3 mov int08handler_lessercount,0100h {256, must be 65536 div (speedup level)} {ok, let’s call normal handler after all that} pushf call dword ptr int08save jmp @hnd_l2 @hnd_l3: mov al,20h out 20h,al {funny, BIOS caller uses call blablabla and ret instead of jmp short} db 0ebh,0 call bogusprocedure @hnd_l2: pop ds pop dx pop ax iret end;
Обработчик прерывания устанавливается на прерывание 08, перед этим нужно сохранить старый вектор вызовом getintvec($08,addr(int08save)), иначе процедура не будет работать {programming timer channel 0, tickin 256, mode 3, hex counter, greater byte only} asm cli mov al,00100110b out 43h,al call bogusprocedure mov al,1 out 40h,al call bogusprocedure sti end; Вызов bogusprocedure стоит из-за того, что порт может не успеть принять записанный байт до того, как в него запишут следующий. asm cli mov al,00110110b out 43h,al call bogusprocedure mov al,0 out 40h,al call bogusprocedure {ok, delay also goes here} out 40h,al call bogusprocedure sti end;
Естественно, нужно еще и вернуть старый вектор, setintvec($08,addr(int08save)); |
Vesper |
|
Не стал править предыдущий пост, он не расконвертился time:=meml[0:$046C]; proces; time:=meml[0:$046C]-time; if time<0 then time:=time+$1800B0; writeln(time/18.2:6:2); Использован кусок кода Кришкина, немного подправленный. proces — процедура, решающая задачу. PS. Если в запрошенном куске будет запрос данных от пользователя, чистого времени вы уже не получите. Если, конечно, вам не нужно время реакции (или скорость набора) пользователя. write(‘Задача №3: траляляляляляля. Введите ответ:’); time:=meml[0:$046C]; readln(x); time:=meml[0:$046C]-time; if time<0 then time:=time+$1800B0; writeln(‘Долговато пожалуй, целых ‘,time/18.2:6:2,’ секунд’); if x<>n then writeln(‘Кстати, ответ неверен.’) else writeln(‘Правильно.’);
Хотя вряд ли вы будете ребенка пытать арифметикой в полночь. |
Romtek |
|
Moderator Рейтинг (т): 188 |
{ Это только интерфейсная часть кода. Целый код модуля находится в архиве } Unit XTIMER; INTERFACE Var elapsed: Longint; { прошедшее время, в милисекундах. } Procedure ClockOn; { включает счётчик времени } Procedure ClockOff; { выключает его } Procedure PrintTime; { выводит прошедшее время } IMPLEMENTATION END.
тестировалось также на Пентиумах II и III, без использования модуля CRT. Сообщение отредактировано: Romtek — 02.12.04, 12:22
|
Александр. |
|
Junior Рейтинг (т): 0 |
А на TMT можно использовать модуль ZenTimer. |
0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
0 пользователей:
- Предыдущая тема
- Pascal: Общие вопросы
- Следующая тема
[ Script execution time: 0,0376 ] [ 16 queries used ] [ Generated: 27.05.23, 23:01 GMT ]
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Несколько лет назад я описывал четыре способа измерения точного времени выполнения операции в Delphi. Сегодня рассмотрим этот же вопрос, но уже применительно к Lazarus и Free Pascal. Учитывая, что Lazarus можно использовать как в Windows, так и в Linux, способы того, как измерить точное время выполнения операции в Lazarus и Delphi будут немного различаться. Для начала, определимся с тем, время выполнения какой операции мы будем измерять. Путь это будет вот такая простенькая процедура:
procedure DoSomething; var i,k: QWord; begin k:=0; for i:=0 to 999999999 do inc(k); end;
Учитывая то, что на данный момент я могу проверить работоспособность того или иного способа только на двух платформах: Windows и Linux, ниже я буду давать описание применимости различных способов точного измерения времени, исходя из проверок именно на этих платформах.
Способ №1 — использование функции Now()
Платформы: Windows, Linux.
Как и в случае с Delphi этот способ вполне подойдет для измерения времени, например, следующим образом:
procedure TForm1.Button2Click(Sender: TObject); var start, stop: TDateTime; begin start:=Now;//засекаем начальное время DoSomething; stop:=Now;//засекаем конечное время {выводим время выполнения операции с точностью до секунды} Memo1.Lines.Add(SecondsBetween(start, stop).ToString); end;
И, хотя в справке Free Pascal ничего не сказано про точность функции Now() (в справке Delphi написано, что точность составляет порядка секунды), я не стал рисковать и все также использовал функцию SecondsBetween() из модуля DateUtils для расчёта количества секунд, пошедших на выполнение операции.
Способ №2 — использование функции GetTickCount
Платформы: Windows, Linux
В настоящее время, в модуле sysutils Free Pascal содержатся две функции, одна из которых помечена как deprecated:
function GetTickCount: LongWord; deprecated 'Use GetTickCount64 instead'; function GetTickCount64: QWord;
Как и в случае с Delphi, используя GetTickCount можно получить время в миллисекундах, затраченное на выполнение операции. Однако, в справке Free Pascal про эту функцию сказано следующее: функция полезна для измерения времени, но не следует делать никаких предположений относительно интервала между тиками. В принципе, примерно тоже сказано и в справке Windows относительно их функций GetTickCount.
Использование функций:
procedure TForm1.Button1Click(Sender: TObject); var Start, Stop: QWord; begin Start:=GetTickCount64; DoSomething; Stop:=GetTickCount64; Memo1.Lines.Add((stop-start).ToString); end;
Стоит отметить, что в зависимости от платформы на которой собирается приложение, GetTickCount64 имеет различные реализации. Так, например, если мы собираем приложение под Windows, то GetTickCount64 будет использовать одноименную функцию из модуля Windows:
function GetTickCount64: QWord; {$IFNDEF WINCE} var lib: THandle; {$ENDIF} begin {$IFNDEF WINCE} { on Vista and newer there is a GetTickCount64 implementation } if Win32MajorVersion >= 6 then begin if not Assigned(WinGetTickCount64) then begin lib := LoadLibrary('kernel32.dll'); WinGetTickCount64 := TGetTickCount64( GetProcAddress(lib, 'GetTickCount64')); end; Result := WinGetTickCount64(); end else {$ENDIF} Result := Windows.GetTickCount; end;
Если же мы используем Linux, то реализация GetTickCount64 основывается на использовании clock_gettime() — функции из языка Си:
function GetTickCount64: QWord; var tp: TTimeVal; {$IFDEF HAVECLOCKGETTIME} ts: TTimeSpec; {$ENDIF} begin {$IFDEF HAVECLOCKGETTIME} if clock_gettime(CLOCK_MONOTONIC, @ts)=0 then begin Result := (Int64(ts.tv_sec) * 1000) + (ts.tv_nsec div 1000000); exit; end; {$ENDIF} fpgettimeofday(@tp, nil); Result := (Int64(tp.tv_sec) * 1000) + (tp.tv_usec div 1000); end;
Способ №3 — использование функций QueryPerformanceCounter и QueryPerformanceFrequency
Платформы: Windows
Использовать функции можно, подключив в uses модуль windows. Соответственно, под Linux метод использовать невозможно, а посмотреть реализацию способа в Windows можно в предыдущей статье про точное измерение времени выполнения операций.
Способ №4 — когда разбираться с функциями лень. Используем компонент TEpikTimer
По аналогии с классом TStopwatch из Delphi, компонент TEpikTimer дает нам широкие возможности по определению времени, затраченного на выполнение какой-либо операции. В принципе, этим компонентом я обычно и пользуюсь.
Чтобы установить компонент, заходим в меню «Пакет — Установить/удалить пакеты»
В списке «Доступные для установки» ищем пакет под названием etpackage_dsgn
Жмем кнопку «Установить выбранное» под списком и, потом, «Сохранить и перезапустить IDE». В новом окне жмем «Продолжить», Lazarus пересоберется и на вкладке System появится новый компонент TEpikTimer:
У компонента есть множество полезных функций, позволяющих измерить точное время выполнения операции в Lazarus, я продемонстрирую только одну из них.
procedure TForm1.Button3Click(Sender: TObject); begin EpikTimer1.Clear; //сбрасываем таймер EpikTimer1.Start; //засекаем время DoSomething; EpikTimer1.Stop; //останавливаем таймер {выводим время выполнения операции в секундах} Memo1.Lines.Add(EpikTimer1.Elapsed.ToString); end;
Здесь я вывел время выполнения операции в секундах. Также EpikTimer умеет выводить время в различных форматах.
Помимо представленных выше способов, вы можете также воспользоваться и другими способами измерения точного времени выполнения операции в Lazarus и Free Pascal, например компонентом TJclCounter от JEDI, однако, в любом случае, эти компоненты будут использовать один из способов, рассмотренных выше, как это делает EpikTimer.
4
2
голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.