<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=40173&amp;view=findpost&amp;p=332045</guid>
        <pubDate>Mon, 05 Apr 2004 13:38:22 +0000</pubDate>
        <title>Как замерять время выполнения кода?</title>
        <link>https://forum.sources.ru/index.php?showtopic=40173&amp;view=findpost&amp;p=332045</link>
        <description><![CDATA[Александр.: А на TMT можно использовать модуль ZenTimer.]]></description>
        <author>Александр.</author>
        <category>Pascal: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=40173&amp;view=findpost&amp;p=299081</guid>
        <pubDate>Fri, 13 Feb 2004 22:49:03 +0000</pubDate>
        <title>Как замерять время выполнения кода?</title>
        <link>https://forum.sources.ru/index.php?showtopic=40173&amp;view=findpost&amp;p=299081</link>
        <description><![CDATA[romtek: <div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">{ Это только интерфейсная часть кода. Целый код модуля находится в архиве }</div><div class="code_line">Unit XTIMER;</div><div class="code_line">&nbsp;</div><div class="code_line">INTERFACE</div><div class="code_line">Var elapsed: Longint; { прошедшее время, в милисекундах. }</div><div class="code_line">Procedure ClockOn; &nbsp; &nbsp;{ включает счётчик времени }</div><div class="code_line">Procedure ClockOff; &nbsp; { выключает его }</div><div class="code_line">Procedure PrintTime; &nbsp;{ выводит прошедшее время }</div><div class="code_line">&nbsp;</div><div class="code_line">IMPLEMENTATION</div><div class="code_line">&nbsp;</div><div class="code_line">END.</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
тестировалось также на Пентиумах II и III, без использования модуля CRT.<br>
Исходник модуля в архиве.]]></description>
        <author>romtek</author>
        <category>Pascal: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=40173&amp;view=findpost&amp;p=273171</guid>
        <pubDate>Tue, 30 Dec 2003 13:55:31 +0000</pubDate>
        <title>Как замерять время выполнения кода?</title>
        <link>https://forum.sources.ru/index.php?showtopic=40173&amp;view=findpost&amp;p=273171</link>
        <description><![CDATA[vesper1: Не стал править предыдущий пост, он не расконвертился :(<br>
Насчет таймера в памяти ДОС:<br>
При каждом срабатывании прерывания 08 происходит увеличение значения meml[0:&#036;046C] на единицу, далее оно проверяется на достижение значения &#036;1800B0 (в десятичной системе 1573040), которое соответствует переходу через полночь (24 часа). Если на часах полночь, ставится в единицу байт по адресу (вроде бы mem[0:&#036;0467], точно не помню). Это значение меняется 18.2 раза в секунду (Some1 был прав) и доступно через &quot;массив&quot; meml любой программе, работающей под ДОС. Чтобы измерить время, нужно:<br>
1) Определить кусок программы, для которого вам нужно узнать время его работы;<br>
2) Сохранить значение этого участка памяти: starttime:=meml[0:&#036;046C]; вставив этот оператор сразу перед началом куска;<br>
3) Сразу после него считать значение еще раз: endtime:=meml[0:&#036;046C]; Для иллюстрации я написал 2 переменные, можно обойтись и одной :)<br>
4) Проверить, не было ли пОлночи в процессе работы: if endtime&lt;starttime then inc(endtime,&#036;1800B0);<br>
5) Осталось взять разницу между значениями и разделить её на 18.2. Результат - время в секундах с точностью плюс-минус 0.05с.<br>
Например, для тестовых задач оно определяется вот так:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">time:=meml[0:6C];</div><div class="code_line">proces;</div><div class="code_line">time:=meml[0:6C]-time;</div><div class="code_line">if time&#60;0 then time:=time+00B0;</div><div class="code_line">writeln(time/18.2:6:2);</div></ol></div></div></div></div><br>
Использован кусок кода Кришкина, немного подправленный. proces - процедура, решающая задачу.<br>
<br>
PS. Если в запрошенном куске будет запрос данных от пользователя, чистого времени вы уже не получите. Если, конечно, вам не нужно время реакции (или скорость набора) пользователя. :D Например, вам нужно узнать, сколько времени ваш ребенок (если есть, иначе ученик ;) ) решал задачку в уме. Делаем так:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">write(&#39;Задача №3: траляляляляляля. Введите ответ:&#39;);</div><div class="code_line">time:=meml[0:6C];</div><div class="code_line">readln(x);</div><div class="code_line">time:=meml[0:6C]-time;</div><div class="code_line">if time&#60;0 then time:=time+00B0;</div><div class="code_line">writeln(&#39;Долговато пожалуй, целых &#39;,time/18.2:6:2,&#39; секунд&#39;);</div><div class="code_line">if x&#60;&#62;n then writeln(&#39;Кстати, ответ неверен.&#39;) else writeln(&#39;Правильно.&#39;);</div></ol></div></div></div></div><br>
Хотя вряд ли вы будете ребенка пытать арифметикой в полночь. :D  :D]]></description>
        <author>vesper1</author>
        <category>Pascal: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=40173&amp;view=findpost&amp;p=262073</guid>
        <pubDate>Fri, 12 Dec 2003 10:44:47 +0000</pubDate>
        <title>Как замерять время выполнения кода?</title>
        <link>https://forum.sources.ru/index.php?showtopic=40173&amp;view=findpost&amp;p=262073</link>
        <description><![CDATA[vesper1: Если не хочется подключать модуль DOS, замерить время можно с помощью взятия значения напрямую из памяти по адресу &#036;0046C (4 байта). Там хранится число &quot;тиков&quot; встроенных часов реального времени, которые тикают 18.54 раз в секунду. И именно оттуда тащат его функции модуля.<br>
Если у вас все еще нет процессора Pentium (или есть, но нужно измерять время на процессоре ниже него), можно разогнать встроенный таймер, при этом нужно будет использовать встроенный ассемблер. Вот этот код по-моему достаточно откомментирован:<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">procedure bogusprocedure;near; assembler;</div><div class="code_line">asm</div><div class="code_line">end;</div><div class="code_line">var int08save:pointer;</div><div class="code_line">&nbsp;   int08handler_count:longint;</div><div class="code_line">&nbsp;   int08handler_lessercount:word;</div><div class="code_line">&nbsp;   int08handler_tickin:boolean;</div><div class="code_line">procedure int08handler;assembler;{no sense of far, it&#39;s int handler, so must have iret inside}</div><div class="code_line">asm</div><div class="code_line">&nbsp; sti</div><div class="code_line">&nbsp; push ax</div><div class="code_line">&nbsp; push dx</div><div class="code_line">&nbsp; push ds</div><div class="code_line">&nbsp; mov ax,seg @data</div><div class="code_line">&nbsp; mov ds,ax {loading DS, probably it&#39;s changed}</div><div class="code_line">&nbsp; mov al,int08handler_tickin</div><div class="code_line">&nbsp; or al,al</div><div class="code_line">&nbsp; je @hnd_l1 {if not tickin jump forward}</div><div class="code_line">&nbsp; db 66h</div><div class="code_line">&nbsp; inc word ptr int08handler_count</div><div class="code_line">@hnd_l1:</div><div class="code_line">&nbsp; dec int08handler_lessercount</div><div class="code_line">&nbsp; jne @hnd_l3</div><div class="code_line">&nbsp; mov int08handler_lessercount,0100h {256, must be 65536 div (speedup level)}</div><div class="code_line">&nbsp; {ok, let&#39;s call normal handler after all that}</div><div class="code_line">&nbsp; pushf</div><div class="code_line">&nbsp; call dword ptr int08save</div><div class="code_line">&nbsp; jmp @hnd_l2</div><div class="code_line">@hnd_l3:</div><div class="code_line">&nbsp; mov al,20h</div><div class="code_line">&nbsp; out 20h,al   {funny, BIOS caller uses call blablabla and ret instead of jmp short}</div><div class="code_line">&nbsp; db 0ebh,0</div><div class="code_line">&nbsp; call bogusprocedure</div><div class="code_line">@hnd_l2:</div><div class="code_line">&nbsp; pop ds</div><div class="code_line">&nbsp; pop dx</div><div class="code_line">&nbsp; pop ax</div><div class="code_line">&nbsp; iret</div><div class="code_line">end;</div></ol></div></div></div></div><br>
Обработчик прерывания устанавливается на прерывание 08, перед этим нужно сохранить старый вектор вызовом getintvec(&#036;08,addr(int08save)), иначе процедура не будет работать :( <br>
Таймер программируется вот так:<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">{programming timer channel 0, tickin 256, mode 3, hex counter, greater byte only}</div><div class="code_line">asm</div><div class="code_line">&nbsp;   cli</div><div class="code_line">&nbsp;   mov al,00100110b</div><div class="code_line">&nbsp;   out 43h,al</div><div class="code_line">&nbsp;   call bogusprocedure</div><div class="code_line">&nbsp;   mov al,1</div><div class="code_line">&nbsp;   out 40h,al</div><div class="code_line">&nbsp;   call bogusprocedure</div><div class="code_line">&nbsp;   sti</div><div class="code_line">end;</div></ol></div></div></div></div>Вызов bogusprocedure стоит из-за того, что порт может не успеть принять записанный байт до того, как в него запишут следующий. <br>
Значение AL в первом OUT флаговое, это байт управления таймером. Биты 7 и 6 содержат номер канала (для часов это 0), 5й и 4й управляют записью соответственно старшего и младшего байта счетчика таймера, 3,2,1 биты содержат режим работы (новый) счетчика, для часов используется режим 3 - периодические прямоугольные колебания выходного сигнала, каждый полупериод длится N/2 колебаний генератора (1193182 Гц), прерывание генерируется каждый переход с низкого на высокий уровень. 0й байт определяет формат записываемого счетчика (1 - двоично-десятичный, 0 - шестнадцатеричный). При записи обоих байтов счетчика сначала записывается младший байт. Для возврата в нормальное состояние в счетчик должен быть записан 0 в оба байта, что соответствует значению счетчика 65536 и нормальной частоте прерываний. Т.е. код для возврата:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">asm</div><div class="code_line">&nbsp;   cli</div><div class="code_line">&nbsp;   mov al,00110110b</div><div class="code_line">&nbsp;   out 43h,al</div><div class="code_line">&nbsp;   call bogusprocedure</div><div class="code_line">&nbsp;   mov al,0</div><div class="code_line">&nbsp;   out 40h,al</div><div class="code_line">&nbsp;   call bogusprocedure {ok, delay also goes here}</div><div class="code_line">&nbsp;   out 40h,al</div><div class="code_line">&nbsp;   call bogusprocedure</div><div class="code_line">&nbsp;   sti</div><div class="code_line">end;</div></ol></div></div></div></div><br>
Естественно, нужно еще и вернуть старый вектор, setintvec(&#036;08,addr(int08save));<br>
Работой счетчика (на случай выключения из анализа процедуры или двух ;) ) можно управлять переменной int08handler_tickin, если она true, то счет идет. Вне зависимости от нее, старый вектор прерывания вызывается с нужной частотой.]]></description>
        <author>vesper1</author>
        <category>Pascal: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=40173&amp;view=findpost&amp;p=261770</guid>
        <pubDate>Thu, 11 Dec 2003 19:11:51 +0000</pubDate>
        <title>Как замерять время выполнения кода?</title>
        <link>https://forum.sources.ru/index.php?showtopic=40173&amp;view=findpost&amp;p=261770</link>
        <description><![CDATA[Visitor: Совсем забыл, что хотел запостить :(<br>
<br>
Для процессоров выше i486 существует способ очень точно сравнить время выполнения двух участков кода -- ето встроенный в процессор счетчик тактов. Ниже приведены два исходника -- процедура, считывающая значение етого счетчика, и пример ее использования на BP7.<br>
<strong class='tag-b'>tsc.asm</strong><div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;       .MODEL LARGE</div><div class="code_line">&nbsp;       .CODE</div><div class="code_line">&nbsp;       .386c</div><div class="code_line">PUBLIC  READTSC</div><div class="code_line">READTSC PROC FAR</div><div class="code_line">&nbsp;       enter 0, 0</div><div class="code_line">&nbsp;       push ds</div><div class="code_line">&nbsp;       db   0fh, 31h; RDTSC opcode</div><div class="code_line">&nbsp;       mov  bx, ss:[bp+8]</div><div class="code_line">&nbsp;       mov  ds, bx</div><div class="code_line">&nbsp;       mov  bx, ss:[bp+6]</div><div class="code_line">&nbsp;       mov  [bx], eax</div><div class="code_line">&nbsp;       mov  [bx+4], edx</div><div class="code_line">&nbsp;       pop ds</div><div class="code_line">&nbsp;       leave</div><div class="code_line">&nbsp;       retf 4</div><div class="code_line">READTSC ENDP</div><div class="code_line">&nbsp;       END</div></ol></div></div></div></div><br>
<br>
<strong class='tag-b'>sample.pas</strong><div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">{$N+}</div><div class="code_line">procedure ReadTSC(Var counter : Comp); far; external;</div><div class="code_line">{$L tsc.obj}</div><div class="code_line">&nbsp;</div><div class="code_line">Var a1, a2, a3 : Comp;</div><div class="code_line">&nbsp;</div><div class="code_line">begin</div><div class="code_line">&nbsp;   ReadTSC(a1);</div><div class="code_line">&nbsp;   Writeln(&#39;Working :)&#39;);</div><div class="code_line">&nbsp;   ReadTSC(a2);</div><div class="code_line">&nbsp;   Writeln(a1:20:0, &#39;, &#39;, a2:20:0, &#39;, &#39;, (a2-a1):20:0)</div><div class="code_line">end.</div></ol></div></div></div></div><br>
<br>
В прикрепленном файле то же самое, tsc.asm оттранслирован.<br>
<br>
P.S. Обратите внимание и сделайте выводы, как много времени занимает вывод на екран. :)]]></description>
        <author>Visitor</author>
        <category>Pascal: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=40173&amp;view=findpost&amp;p=260403</guid>
        <pubDate>Tue, 09 Dec 2003 15:26:45 +0000</pubDate>
        <title>Как замерять время выполнения кода?</title>
        <link>https://forum.sources.ru/index.php?showtopic=40173&amp;view=findpost&amp;p=260403</link>
        <description><![CDATA[Some1: Самым простым способом является одновременно самый очевидный:<br>
Узнаём и запоминаем время, потом делаем нужное нам действие, и сразу после него опять узнаём и запоминаем время.<br>
Разница между временем до действия и временем после действия и будет временем выполнения действия.<br>
<br>
В паскале есть стандартная процедура модуля Dos - <strong class='tag-b'>GetTime</strong>.<br>
Она узнаёт, сколько времени в момент её выполнения.<br>
Вот её синтаксис:<br>
<strong class='tag-b'>procedure GetTime(var Hour, Minute, Second, Second100:word);</strong><br>
<br>
Её параметрамы должны быть обязательно переменные. После её выполнения в этих переменных будет содержаться время того момента, когда выполнится эта процедура:<ul class="tag-list"><li><strong class='tag-b'>Hour</strong> - Час (значение от 0 до 23)</li><li><strong class='tag-b'>Minute</strong> - Минута (значение от 0 до 59)</li><li><strong class='tag-b'>Second</strong> - Секунда (значение от 0 до 59)</li><li><strong class='tag-b'>Second100</strong> - Сотая часть секунды (значение от 0 до 99)</li></ul>Используя эту процедуру мы можем занести в переменные время до выполнения нужного нам действия, и в другие переменные время после выполнения нужного нам действия.<br>
После этого можно посчитать разницу во времени, и эта разница будет длительностью выполнения замеряемого действия.<br>
<br>
Чтобы посчитать разницу нужно перевести время до выполнения и время после выполнения к количеству сотых частей секунды. Нельзя напрямую сравнивать к примеру просто секунды. Почему?<br>
Предположим в момент замера времени до выполнения нужного нам действия было время 10 минут 58 секунд. А в момент замера времени после выполнения было 11 минут 15 секунд. Если мы вычтем из секунд-после секунды-до, мы получим (15-58)=-43 секунды. Но ведь это неверно %)<br>
Так получилось из-за того, что за время, пока выполнялась программа началась новая минута. Если же преобразовать всё время к количеству сотых частей секунды, то такой проблемы не возникнет.<br>
Вот пример действующего кода:<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">uses dos;</div><div class="code_line">var</div><div class="code_line">&nbsp; h1,m1,s1,t1:word;</div><div class="code_line">&nbsp; h2,m2,s2,t2:word;</div><div class="code_line">&nbsp; d:longint;</div><div class="code_line">begin</div><div class="code_line">&nbsp; gettime(h1,m1,s1,t1);</div><div class="code_line">&nbsp; ... {любое действие, продолжительность которого измеряем}</div><div class="code_line">&nbsp; gettime(h2,m2,s2,t2);</div><div class="code_line">&nbsp; {вычислим время выполнения d - результат будет в сотых долях секунды}</div><div class="code_line">&nbsp; d:=(longint(h2)*360000+longint(m2)*6000+s2*100+t2)- {количество сотых долей секунды после выполнения}</div><div class="code_line">&nbsp;    (longint(h1)*360000+longint(m1)*6000+s1*100+t1); {их количество до выполнения действия}</div><div class="code_line">&nbsp; writeln(&#39;Действие выполнялось &#39;,d/100:0:2,&#39; секунды&#39;);</div><div class="code_line">end.</div></ol></div></div></div></div><br>
П.С. Следует добавить, что хотя этот способ и является самым простым, он отнюдь не самый точный, поскольку во время замера входит так же время выполнения процедуры <strong class='tag-b'>GetTime</strong>, и кроме того это время может зависеть от состояния <a class='tag-url' href='http://forum.sources.ru/index.php?showtopic=40131' target='_blank'>Директив компилятора</a>.<br>
<br>
<em class='tag-i'>P.P.S:<br>
Можно пойти чуть дальше, и написать функцию fGetTime:</em><br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">function fGetTime: LongInt;</div><div class="code_line">var hr, min, sec, sec_100: word;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;GetTime(hr, min, sec, sec_100);</div><div class="code_line">&nbsp;&nbsp;fGetTime := longint(hr)*360000 + longint(min)*6000 + sec*100 + sec_100;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">{ и работать с ней: }</div><div class="code_line">var before, after: longint;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;before := fGetTime;</div><div class="code_line">&nbsp;&nbsp;...</div><div class="code_line">&nbsp;&nbsp;after := fGetTime;</div><div class="code_line">&nbsp;&nbsp;writeln(&#39;Действие выполнялось &#39;, (after - before) / 100:0:2,&#39; секунды&#39;)</div><div class="code_line">end;</div></ol></div></div></div></div><br>
<em class='tag-i'>V877</em>]]></description>
        <author>Some1</author>
        <category>Pascal: Общие вопросы</category>
      </item>
	
      </channel>
      </rss>
	