<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.autoitscript.com/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Poila</id>
	<title>AutoIt Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://www.autoitscript.com/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Poila"/>
	<link rel="alternate" type="text/html" href="https://www.autoitscript.com/wiki/Special:Contributions/Poila"/>
	<updated>2026-04-21T17:24:17Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>https://www.autoitscript.com/w/index.php?title=Tutorial_Optimizing&amp;diff=12428</id>
		<title>Tutorial Optimizing</title>
		<link rel="alternate" type="text/html" href="https://www.autoitscript.com/w/index.php?title=Tutorial_Optimizing&amp;diff=12428"/>
		<updated>2014-06-04T01:32:35Z</updated>

		<summary type="html">&lt;p&gt;Poila: /* Optimizing code */ Grammatical edits&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
NOTE: This document is work in progress. Your view and contribution on content is welcome. Spellchecking and grammar will be worked on when the document approaches a stable state.&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This tutorial will be about profiling and optimizing code when we have identified a bottleneck. There are several paths down this road. You could analytically evaluate your code, or fragments of it. You could optimize parts that don&#039;t feel good. And you can measure how long time the code takes to run.&lt;br /&gt;
&lt;br /&gt;
=Profiling=&lt;br /&gt;
When we profile the code we use a stopwatch to log how much time that is spent from the code starts until it ends execution. There are two types of time we can use. The real time spent and the CPU time spent to execute the code. Both methods have its usage. But measuring the CPU time should normally result in better knowledge than measuring clock time. The exception could be in routines where the code calls external resources that depends on other factors rather than the CPU. Ex: printer, network, disk IO. &lt;br /&gt;
==The simplest approach==&lt;br /&gt;
Autoit has two handy clock functions to do a regular stopwatch measure of code execution time. Namely &lt;br /&gt;
TimerInit and TimerDiff. TimerInit is used to get a reference point and TimerDiff to get the difference between the reference point and the call to TimerDiff in milliseconds.&lt;br /&gt;
So the simplest possible sample could be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Local $i, $j, $sum, $count, $ts, $td&lt;br /&gt;
 For $j = 1 to 10&lt;br /&gt;
	$ts = TimerInit()&lt;br /&gt;
 	Do&lt;br /&gt;
 		$count += 1&lt;br /&gt;
 		$sum += Random(-5, 5, 1)&lt;br /&gt;
 	Until $sum = 0 OR $count = 100000&lt;br /&gt;
 	; Write/create report&lt;br /&gt;
 	$td = TimerDiff($ts)&lt;br /&gt;
 	ConsoleWrite( StringFormat(&amp;quot;%#.6g ms, Iter=%.6d, avg=%.6g&amp;quot;, $td, $count, $td/$count) &amp;amp; @LF)&lt;br /&gt;
 	$count = 0&lt;br /&gt;
 Next&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now although this is a reasonable way of measuring execution time, it does not give an accurate picture to identify bottlenecks. And the reason is that it measures real time and not the time spent by the CPU to execute this part of the code. You can probably see this if one of the iterations reaches a $sum=0 in few iterations compared to one that uses max iterations.&lt;br /&gt;
&lt;br /&gt;
==The more accurate approach==&lt;br /&gt;
API notes: GetProcessTimes, GetThreadTimes&lt;br /&gt;
Windows versions based on NT kernel has at least two API calls to make profiling easier for us. GetProcessTimes will return the CPU time spent by the given process. GetThreadTimes will return the CPU time spent by the given thread. As AutoIt does not support user defined threads, we will use the GetProcessTimes call. A [http://www.autoitscript.com/forum/index.php?s=&amp;amp;showtopic=38751 profiling UDF] has been created by [http://www.autoitscript.com/forum/index.php?showuser=7836 @uten] in the AutoItScript forum. As for now we will use that code. Save the code in an include file. I have called mine profiler.au3 and saved it in an include directory. (TODO: Link to page explaining userdefined include directories.)&lt;br /&gt;
&amp;lt;pre&amp;gt;Global $FILETIME = &amp;quot;dword;dword&amp;quot;    ;Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).&lt;br /&gt;
Global $SYSTEMTIME = &amp;quot;ushort;ushort;ushort;ushort;ushort;ushort;ushort;ushort&amp;quot;&lt;br /&gt;
Func FileTimeToNum(ByRef $FT)&lt;br /&gt;
   Return BITOr(BitShift(DllStructGetData($FT, 1), 32), DllStructGetData($FT, 2))&lt;br /&gt;
EndFunc&lt;br /&gt;
Func OpenProcess($pid = @AutoItPID)&lt;br /&gt;
    Local $PROCESS_QUERY_INFORMATION = 0x0400&lt;br /&gt;
    Local $PROCESS_VM_READ = 0x0010&lt;br /&gt;
    $Process = DLLCall(&amp;quot;kernel32.dll&amp;quot;,&amp;quot;int&amp;quot;,&amp;quot;OpenProcess&amp;quot;,&amp;quot;int&amp;quot;, _&lt;br /&gt;
            BitOR($PROCESS_QUERY_INFORMATION,$PROCESS_VM_READ),&amp;quot;int&amp;quot;,0,&amp;quot;int&amp;quot;, $pid)&lt;br /&gt;
    If $Process[0] = 0 Then Return SetError(1, 0, 0)&lt;br /&gt;
   Return $Process[0]&lt;br /&gt;
EndFunc&lt;br /&gt;
Func GetProcessTimes(ByRef $hProcess, ByRef $t1, ByRef $t2, ByRef $t3, ByRef $t4)&lt;br /&gt;
&lt;br /&gt;
;BOOL WINAPI GetProcessTimes(&lt;br /&gt;
;  HANDLE hProcess,&lt;br /&gt;
;  LPFILETIME lpCreationTime,&lt;br /&gt;
;  LPFILETIME lpExitTime,&lt;br /&gt;
;  LPFILETIME lpKernelTime,&lt;br /&gt;
;  LPFILETIME lpUserTime&lt;br /&gt;
; )&lt;br /&gt;
;&lt;br /&gt;
   Local $p1 = DllStructGetPtr($t1)&lt;br /&gt;
   Local $p2 = DllStructGetPtr($t2)&lt;br /&gt;
   Local $p3 = DllStructGetPtr($t3)&lt;br /&gt;
   Local $p4 = DllStructGetPtr($t4)&lt;br /&gt;
   ;ConsoleWrite($p1 &amp;amp; &amp;quot;, &amp;quot; &amp;amp; $p2&amp;amp; &amp;quot;, &amp;quot; &amp;amp; $p3 &amp;amp; &amp;quot;, &amp;quot; &amp;amp; $p4 &amp;amp; @LF)&lt;br /&gt;
   Local $ret = dllcall(&amp;quot;kernel32.dll&amp;quot;,&amp;quot;int&amp;quot;, &amp;quot;GetProcessTimes&amp;quot;,&amp;quot;int&amp;quot;,$hProcess ,  &amp;quot;ptr&amp;quot;, $p1, &amp;quot;ptr&amp;quot;, $p2, &amp;quot;ptr&amp;quot;, $p3, &amp;quot;ptr&amp;quot;, $p4)&lt;br /&gt;
   If $ret[0] = 0 Then&lt;br /&gt;
      ConsoleWrite(&amp;quot;(&amp;quot; &amp;amp; @ScriptLineNumber &amp;amp; &amp;quot;) : = Error in GetProcessTimes call&amp;quot; &amp;amp; @LF)&lt;br /&gt;
      SetError(1, 0 , $ret[0])&lt;br /&gt;
   EndIf&lt;br /&gt;
   Return $ret[0]&lt;br /&gt;
EndFunc&lt;br /&gt;
Func ProfileInit()&lt;br /&gt;
   Local $process = OpenProcess(@AutoItPID)&lt;br /&gt;
   if @error then&lt;br /&gt;
      ConsoleWrite(&amp;quot;!OpenProcess failed terminating&amp;quot; &amp;amp; @LF)&lt;br /&gt;
      Exit&lt;br /&gt;
   EndIf&lt;br /&gt;
   Local $ret[4]&lt;br /&gt;
   $ret[0] = 2&lt;br /&gt;
   Local $t1 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t2 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t3 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t4 = DllStructCreate($FILETIME)    &lt;br /&gt;
   If GetProcessTimes($process, $t1, $t2, $t3, $t4) Then&lt;br /&gt;
      $ret[$ret[0] + 1] = $process&lt;br /&gt;
      $ret[1] = FileTimeToNum($t3)&lt;br /&gt;
      $ret[2] = FileTimeToNum($t4)&lt;br /&gt;
   Else&lt;br /&gt;
      ConsoleWrite(&amp;quot;(&amp;quot; &amp;amp; @ScriptLineNumber &amp;amp; &amp;quot;) := @error:=&amp;quot; &amp;amp; @error &amp;amp; &amp;quot;, @extended:?&amp;quot; &amp;amp; @extended &amp;amp; @LF)&lt;br /&gt;
      SetError(@error, @extended, 0)&lt;br /&gt;
   EndIf&lt;br /&gt;
   ;ArrayDump($ret, &amp;quot;ProfileInit Out&amp;quot;)&lt;br /&gt;
   Return $ret&lt;br /&gt;
EndFunc&lt;br /&gt;
Func ProfileDiff(ByRef $init)&lt;br /&gt;
   Local $ret[3]&lt;br /&gt;
   $ret[0] = 2&lt;br /&gt;
   ;ArrayDump($init, &amp;quot;ProfileDiff($init)&amp;quot;)&lt;br /&gt;
   Local $t1 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t2 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t3 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t4 = DllStructCreate($FILETIME)    &lt;br /&gt;
   Local $n1, $n2&lt;br /&gt;
   If GetProcessTimes($init[$init[0] + 1], $t1, $t2, $t3, $t4) Then&lt;br /&gt;
      $ret[1] = FileTimeToNum($t3) - $init[1]&lt;br /&gt;
      $ret[2] = FileTimeToNum($t4) - $init[2]&lt;br /&gt;
   Else&lt;br /&gt;
      ConsoleWrite(&amp;quot;(&amp;quot; &amp;amp; @ScriptLineNumber &amp;amp; &amp;quot;) := @error:=&amp;quot; &amp;amp; @error &amp;amp; &amp;quot;, @extended:=&amp;quot; &amp;amp; @extended &amp;amp; @LF)&lt;br /&gt;
      SetError(@error, 0 , 0)&lt;br /&gt;
   EndIf&lt;br /&gt;
   Return $ret&lt;br /&gt;
EndFunc&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have a some profiling routines. ProfileInit and ProfileDiff we can change our sample to make use of those UDF&#039;s.&lt;br /&gt;
Note that the time returned from ProfileDiff are in 100-nanoseconds intervals. To get ms we have to divide by 10000.&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
 #include &amp;lt;profiler.au3&amp;gt;&lt;br /&gt;
 Local $i, $j, $sum, $count, $ps, $pd, $uk&lt;br /&gt;
 For $j = 1 to 10&lt;br /&gt;
	$ps = ProfileInit()  &lt;br /&gt;
 	Do&lt;br /&gt;
 		$count += 1&lt;br /&gt;
 		$sum += Random(-5, 5, 1)&lt;br /&gt;
 	Until $sum = 0 OR $count = 100000&lt;br /&gt;
 	; Write/create report&lt;br /&gt;
 	$pd = ProfileDiff($ps)&lt;br /&gt;
 	$uk = Round(($pd[1] + $pd[2])/10000, 0) ;User and kernel time&lt;br /&gt;
 	ConsoleWrite( StringFormat(&amp;quot;%#.6g ms, Iter=%.6d, avg=%.6g&amp;quot;, $uk, $count, $uk/$count) &amp;amp; @LF)&lt;br /&gt;
 	$count = 0&lt;br /&gt;
 Next&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Optimizing code=&lt;br /&gt;
When do we need to optimize our code? Well, that&#039;s a good question. A rule of thumb is to make the code work first. If we experience that the code is slow, we have to find the cause. When one or more causes are found, we have to consider if it is possible to optimize the code. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a look at a &#039;&#039;real world&#039;&#039; sample. Sorting stuff is a classic. &lt;br /&gt;
==Getting some data==&lt;br /&gt;
Let&#039;s grab some data from the AutoItScript forum. The data is not relevant for the sample so if you have a fairly big HTML file on your disk, you could use that instead.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;inet.au3&amp;gt;&lt;br /&gt;
$data = _InetGet(&amp;quot;http://www.autoitscript.com/forum/index.php?showtopic=36941&amp;quot;)&lt;br /&gt;
;$data = ReadFile(&amp;quot;&amp;lt;your file&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Data to plain text. Take one==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Func WordList(ByRef $data)&lt;br /&gt;
;Shave of html tags&lt;br /&gt;
Local $res&lt;br /&gt;
;Return string&lt;br /&gt;
EndFunc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Data to plain text. Take two==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Func Wordlist2(ByRef $data)&lt;br /&gt;
Local $res = StringRegExp($data, &amp;quot;TODO&amp;quot;, 3)&lt;br /&gt;
;Array to string&lt;br /&gt;
;Return string&lt;br /&gt;
EndFunc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Sorting the text. Take one==&lt;br /&gt;
Using bouble sort&lt;br /&gt;
==Sorting the text. Take two==&lt;br /&gt;
Using something faster.&lt;/div&gt;</summary>
		<author><name>Poila</name></author>
	</entry>
	<entry>
		<id>https://www.autoitscript.com/w/index.php?title=Tutorial_Optimizing&amp;diff=12427</id>
		<title>Tutorial Optimizing</title>
		<link rel="alternate" type="text/html" href="https://www.autoitscript.com/w/index.php?title=Tutorial_Optimizing&amp;diff=12427"/>
		<updated>2014-06-04T01:26:20Z</updated>

		<summary type="html">&lt;p&gt;Poila: /* The more accurate approach */ Minor grammar edits&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
NOTE: This document is work in progress. Your view and contribution on content is welcome. Spellchecking and grammar will be worked on when the document approaches a stable state.&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This tutorial will be about profiling and optimizing code when we have identified a bottleneck. There are several paths down this road. You could analytically evaluate your code, or fragments of it. You could optimize parts that don&#039;t feel good. And you can measure how long time the code takes to run.&lt;br /&gt;
&lt;br /&gt;
=Profiling=&lt;br /&gt;
When we profile the code we use a stopwatch to log how much time that is spent from the code starts until it ends execution. There are two types of time we can use. The real time spent and the CPU time spent to execute the code. Both methods have its usage. But measuring the CPU time should normally result in better knowledge than measuring clock time. The exception could be in routines where the code calls external resources that depends on other factors rather than the CPU. Ex: printer, network, disk IO. &lt;br /&gt;
==The simplest approach==&lt;br /&gt;
Autoit has two handy clock functions to do a regular stopwatch measure of code execution time. Namely &lt;br /&gt;
TimerInit and TimerDiff. TimerInit is used to get a reference point and TimerDiff to get the difference between the reference point and the call to TimerDiff in milliseconds.&lt;br /&gt;
So the simplest possible sample could be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Local $i, $j, $sum, $count, $ts, $td&lt;br /&gt;
 For $j = 1 to 10&lt;br /&gt;
	$ts = TimerInit()&lt;br /&gt;
 	Do&lt;br /&gt;
 		$count += 1&lt;br /&gt;
 		$sum += Random(-5, 5, 1)&lt;br /&gt;
 	Until $sum = 0 OR $count = 100000&lt;br /&gt;
 	; Write/create report&lt;br /&gt;
 	$td = TimerDiff($ts)&lt;br /&gt;
 	ConsoleWrite( StringFormat(&amp;quot;%#.6g ms, Iter=%.6d, avg=%.6g&amp;quot;, $td, $count, $td/$count) &amp;amp; @LF)&lt;br /&gt;
 	$count = 0&lt;br /&gt;
 Next&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now although this is a reasonable way of measuring execution time, it does not give an accurate picture to identify bottlenecks. And the reason is that it measures real time and not the time spent by the CPU to execute this part of the code. You can probably see this if one of the iterations reaches a $sum=0 in few iterations compared to one that uses max iterations.&lt;br /&gt;
&lt;br /&gt;
==The more accurate approach==&lt;br /&gt;
API notes: GetProcessTimes, GetThreadTimes&lt;br /&gt;
Windows versions based on NT kernel has at least two API calls to make profiling easier for us. GetProcessTimes will return the CPU time spent by the given process. GetThreadTimes will return the CPU time spent by the given thread. As AutoIt does not support user defined threads, we will use the GetProcessTimes call. A [http://www.autoitscript.com/forum/index.php?s=&amp;amp;showtopic=38751 profiling UDF] has been created by [http://www.autoitscript.com/forum/index.php?showuser=7836 @uten] in the AutoItScript forum. As for now we will use that code. Save the code in an include file. I have called mine profiler.au3 and saved it in an include directory. (TODO: Link to page explaining userdefined include directories.)&lt;br /&gt;
&amp;lt;pre&amp;gt;Global $FILETIME = &amp;quot;dword;dword&amp;quot;    ;Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).&lt;br /&gt;
Global $SYSTEMTIME = &amp;quot;ushort;ushort;ushort;ushort;ushort;ushort;ushort;ushort&amp;quot;&lt;br /&gt;
Func FileTimeToNum(ByRef $FT)&lt;br /&gt;
   Return BITOr(BitShift(DllStructGetData($FT, 1), 32), DllStructGetData($FT, 2))&lt;br /&gt;
EndFunc&lt;br /&gt;
Func OpenProcess($pid = @AutoItPID)&lt;br /&gt;
    Local $PROCESS_QUERY_INFORMATION = 0x0400&lt;br /&gt;
    Local $PROCESS_VM_READ = 0x0010&lt;br /&gt;
    $Process = DLLCall(&amp;quot;kernel32.dll&amp;quot;,&amp;quot;int&amp;quot;,&amp;quot;OpenProcess&amp;quot;,&amp;quot;int&amp;quot;, _&lt;br /&gt;
            BitOR($PROCESS_QUERY_INFORMATION,$PROCESS_VM_READ),&amp;quot;int&amp;quot;,0,&amp;quot;int&amp;quot;, $pid)&lt;br /&gt;
    If $Process[0] = 0 Then Return SetError(1, 0, 0)&lt;br /&gt;
   Return $Process[0]&lt;br /&gt;
EndFunc&lt;br /&gt;
Func GetProcessTimes(ByRef $hProcess, ByRef $t1, ByRef $t2, ByRef $t3, ByRef $t4)&lt;br /&gt;
&lt;br /&gt;
;BOOL WINAPI GetProcessTimes(&lt;br /&gt;
;  HANDLE hProcess,&lt;br /&gt;
;  LPFILETIME lpCreationTime,&lt;br /&gt;
;  LPFILETIME lpExitTime,&lt;br /&gt;
;  LPFILETIME lpKernelTime,&lt;br /&gt;
;  LPFILETIME lpUserTime&lt;br /&gt;
; )&lt;br /&gt;
;&lt;br /&gt;
   Local $p1 = DllStructGetPtr($t1)&lt;br /&gt;
   Local $p2 = DllStructGetPtr($t2)&lt;br /&gt;
   Local $p3 = DllStructGetPtr($t3)&lt;br /&gt;
   Local $p4 = DllStructGetPtr($t4)&lt;br /&gt;
   ;ConsoleWrite($p1 &amp;amp; &amp;quot;, &amp;quot; &amp;amp; $p2&amp;amp; &amp;quot;, &amp;quot; &amp;amp; $p3 &amp;amp; &amp;quot;, &amp;quot; &amp;amp; $p4 &amp;amp; @LF)&lt;br /&gt;
   Local $ret = dllcall(&amp;quot;kernel32.dll&amp;quot;,&amp;quot;int&amp;quot;, &amp;quot;GetProcessTimes&amp;quot;,&amp;quot;int&amp;quot;,$hProcess ,  &amp;quot;ptr&amp;quot;, $p1, &amp;quot;ptr&amp;quot;, $p2, &amp;quot;ptr&amp;quot;, $p3, &amp;quot;ptr&amp;quot;, $p4)&lt;br /&gt;
   If $ret[0] = 0 Then&lt;br /&gt;
      ConsoleWrite(&amp;quot;(&amp;quot; &amp;amp; @ScriptLineNumber &amp;amp; &amp;quot;) : = Error in GetProcessTimes call&amp;quot; &amp;amp; @LF)&lt;br /&gt;
      SetError(1, 0 , $ret[0])&lt;br /&gt;
   EndIf&lt;br /&gt;
   Return $ret[0]&lt;br /&gt;
EndFunc&lt;br /&gt;
Func ProfileInit()&lt;br /&gt;
   Local $process = OpenProcess(@AutoItPID)&lt;br /&gt;
   if @error then&lt;br /&gt;
      ConsoleWrite(&amp;quot;!OpenProcess failed terminating&amp;quot; &amp;amp; @LF)&lt;br /&gt;
      Exit&lt;br /&gt;
   EndIf&lt;br /&gt;
   Local $ret[4]&lt;br /&gt;
   $ret[0] = 2&lt;br /&gt;
   Local $t1 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t2 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t3 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t4 = DllStructCreate($FILETIME)    &lt;br /&gt;
   If GetProcessTimes($process, $t1, $t2, $t3, $t4) Then&lt;br /&gt;
      $ret[$ret[0] + 1] = $process&lt;br /&gt;
      $ret[1] = FileTimeToNum($t3)&lt;br /&gt;
      $ret[2] = FileTimeToNum($t4)&lt;br /&gt;
   Else&lt;br /&gt;
      ConsoleWrite(&amp;quot;(&amp;quot; &amp;amp; @ScriptLineNumber &amp;amp; &amp;quot;) := @error:=&amp;quot; &amp;amp; @error &amp;amp; &amp;quot;, @extended:?&amp;quot; &amp;amp; @extended &amp;amp; @LF)&lt;br /&gt;
      SetError(@error, @extended, 0)&lt;br /&gt;
   EndIf&lt;br /&gt;
   ;ArrayDump($ret, &amp;quot;ProfileInit Out&amp;quot;)&lt;br /&gt;
   Return $ret&lt;br /&gt;
EndFunc&lt;br /&gt;
Func ProfileDiff(ByRef $init)&lt;br /&gt;
   Local $ret[3]&lt;br /&gt;
   $ret[0] = 2&lt;br /&gt;
   ;ArrayDump($init, &amp;quot;ProfileDiff($init)&amp;quot;)&lt;br /&gt;
   Local $t1 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t2 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t3 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t4 = DllStructCreate($FILETIME)    &lt;br /&gt;
   Local $n1, $n2&lt;br /&gt;
   If GetProcessTimes($init[$init[0] + 1], $t1, $t2, $t3, $t4) Then&lt;br /&gt;
      $ret[1] = FileTimeToNum($t3) - $init[1]&lt;br /&gt;
      $ret[2] = FileTimeToNum($t4) - $init[2]&lt;br /&gt;
   Else&lt;br /&gt;
      ConsoleWrite(&amp;quot;(&amp;quot; &amp;amp; @ScriptLineNumber &amp;amp; &amp;quot;) := @error:=&amp;quot; &amp;amp; @error &amp;amp; &amp;quot;, @extended:=&amp;quot; &amp;amp; @extended &amp;amp; @LF)&lt;br /&gt;
      SetError(@error, 0 , 0)&lt;br /&gt;
   EndIf&lt;br /&gt;
   Return $ret&lt;br /&gt;
EndFunc&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have a some profiling routines. ProfileInit and ProfileDiff we can change our sample to make use of those UDF&#039;s.&lt;br /&gt;
Note that the time returned from ProfileDiff are in 100-nanoseconds intervals. To get ms we have to divide by 10000.&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
 #include &amp;lt;profiler.au3&amp;gt;&lt;br /&gt;
 Local $i, $j, $sum, $count, $ps, $pd, $uk&lt;br /&gt;
 For $j = 1 to 10&lt;br /&gt;
	$ps = ProfileInit()  &lt;br /&gt;
 	Do&lt;br /&gt;
 		$count += 1&lt;br /&gt;
 		$sum += Random(-5, 5, 1)&lt;br /&gt;
 	Until $sum = 0 OR $count = 100000&lt;br /&gt;
 	; Write/create report&lt;br /&gt;
 	$pd = ProfileDiff($ps)&lt;br /&gt;
 	$uk = Round(($pd[1] + $pd[2])/10000, 0) ;User and kernel time&lt;br /&gt;
 	ConsoleWrite( StringFormat(&amp;quot;%#.6g ms, Iter=%.6d, avg=%.6g&amp;quot;, $uk, $count, $uk/$count) &amp;amp; @LF)&lt;br /&gt;
 	$count = 0&lt;br /&gt;
 Next&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Optimizing code=&lt;br /&gt;
When do we need to optimize our code? Well, thats a good question. A roule of thumb is to make the code work first. If we experience that the code is slow we have to find the reason. When one or more reasons are found we have to consider if it is possible to optimize the code. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a look at a &#039;&#039;real world&#039;&#039; sample. Sorting stuff is a classic. &lt;br /&gt;
==Getting some data==&lt;br /&gt;
Let&#039;s grab some data from autoitscript. The data is not relevant for the sample so if you have a fearly big html file on your disk you could use that instead.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;inet.au3&amp;gt;&lt;br /&gt;
$data = _InetGet(&amp;quot;http://www.autoitscript.com/forum/index.php?showtopic=36941&amp;quot;)&lt;br /&gt;
;$data = ReadFile(&amp;quot;&amp;lt;your file&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Data to plain text. Take one==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Func WordList(ByRef $data)&lt;br /&gt;
;Shave of html tags&lt;br /&gt;
Local $res&lt;br /&gt;
;Return string&lt;br /&gt;
EndFunc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Data to plain text. Take two==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Func Wordlist2(ByRef $data)&lt;br /&gt;
Local $res = StringRegExp($data, &amp;quot;TODO&amp;quot;, 3)&lt;br /&gt;
;Array to string&lt;br /&gt;
;Return string&lt;br /&gt;
EndFunc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Sorting the text. Take one==&lt;br /&gt;
Using bouble sort&lt;br /&gt;
==Sorting the text. Take two==&lt;br /&gt;
Using something faster.&lt;/div&gt;</summary>
		<author><name>Poila</name></author>
	</entry>
	<entry>
		<id>https://www.autoitscript.com/w/index.php?title=Tutorial_Optimizing&amp;diff=12426</id>
		<title>Tutorial Optimizing</title>
		<link rel="alternate" type="text/html" href="https://www.autoitscript.com/w/index.php?title=Tutorial_Optimizing&amp;diff=12426"/>
		<updated>2014-06-04T01:23:29Z</updated>

		<summary type="html">&lt;p&gt;Poila: /* Profiling */ Minor grammar edit&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
NOTE: This document is work in progress. Your view and contribution on content is welcome. Spellchecking and grammar will be worked on when the document approaches a stable state.&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This tutorial will be about profiling and optimizing code when we have identified a bottleneck. There are several paths down this road. You could analytically evaluate your code, or fragments of it. You could optimize parts that don&#039;t feel good. And you can measure how long time the code takes to run.&lt;br /&gt;
&lt;br /&gt;
=Profiling=&lt;br /&gt;
When we profile the code we use a stopwatch to log how much time that is spent from the code starts until it ends execution. There are two types of time we can use. The real time spent and the CPU time spent to execute the code. Both methods have its usage. But measuring the CPU time should normally result in better knowledge than measuring clock time. The exception could be in routines where the code calls external resources that depends on other factors rather than the CPU. Ex: printer, network, disk IO. &lt;br /&gt;
==The simplest approach==&lt;br /&gt;
Autoit has two handy clock functions to do a regular stopwatch measure of code execution time. Namely &lt;br /&gt;
TimerInit and TimerDiff. TimerInit is used to get a reference point and TimerDiff to get the difference between the reference point and the call to TimerDiff in milliseconds.&lt;br /&gt;
So the simplest possible sample could be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Local $i, $j, $sum, $count, $ts, $td&lt;br /&gt;
 For $j = 1 to 10&lt;br /&gt;
	$ts = TimerInit()&lt;br /&gt;
 	Do&lt;br /&gt;
 		$count += 1&lt;br /&gt;
 		$sum += Random(-5, 5, 1)&lt;br /&gt;
 	Until $sum = 0 OR $count = 100000&lt;br /&gt;
 	; Write/create report&lt;br /&gt;
 	$td = TimerDiff($ts)&lt;br /&gt;
 	ConsoleWrite( StringFormat(&amp;quot;%#.6g ms, Iter=%.6d, avg=%.6g&amp;quot;, $td, $count, $td/$count) &amp;amp; @LF)&lt;br /&gt;
 	$count = 0&lt;br /&gt;
 Next&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now although this is a reasonable way of measuring execution time, it does not give an accurate picture to identify bottlenecks. And the reason is that it measures real time and not the time spent by the CPU to execute this part of the code. You can probably see this if one of the iterations reaches a $sum=0 in few iterations compared to one that uses max iterations.&lt;br /&gt;
&lt;br /&gt;
==The more accurate approach==&lt;br /&gt;
API notes: GetProcessTimes, GetThreadTimes&lt;br /&gt;
Windows versions based on NT kernel has at least two API calls to make profiling easier for us. GetProcessTimes will return the CPU time spent by the given process. GetThreadTimes will return the CPU time spent by the given thread. As AutoIt does not support user defined threads, we will use the GetProcessTimes call. A [http://www.autoitscript.com/forum/index.php?s=&amp;amp;showtopic=38751 profiling UDF] has been created by [http://www.autoitscript.com/forum/index.php?showuser=7836 @uten] in the AutoItScript forum. As for now we will use that code. Save the code in an include file. I have called mine profiler.au3 and saved it in a include directory. (TODO: Link to page explaining userdefined include directories.)&lt;br /&gt;
&amp;lt;pre&amp;gt;Global $FILETIME = &amp;quot;dword;dword&amp;quot;    ;Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).&lt;br /&gt;
Global $SYSTEMTIME = &amp;quot;ushort;ushort;ushort;ushort;ushort;ushort;ushort;ushort&amp;quot;&lt;br /&gt;
Func FileTimeToNum(ByRef $FT)&lt;br /&gt;
   Return BITOr(BitShift(DllStructGetData($FT, 1), 32), DllStructGetData($FT, 2))&lt;br /&gt;
EndFunc&lt;br /&gt;
Func OpenProcess($pid = @AutoItPID)&lt;br /&gt;
    Local $PROCESS_QUERY_INFORMATION = 0x0400&lt;br /&gt;
    Local $PROCESS_VM_READ = 0x0010&lt;br /&gt;
    $Process = DLLCall(&amp;quot;kernel32.dll&amp;quot;,&amp;quot;int&amp;quot;,&amp;quot;OpenProcess&amp;quot;,&amp;quot;int&amp;quot;, _&lt;br /&gt;
            BitOR($PROCESS_QUERY_INFORMATION,$PROCESS_VM_READ),&amp;quot;int&amp;quot;,0,&amp;quot;int&amp;quot;, $pid)&lt;br /&gt;
    If $Process[0] = 0 Then Return SetError(1, 0, 0)&lt;br /&gt;
   Return $Process[0]&lt;br /&gt;
EndFunc&lt;br /&gt;
Func GetProcessTimes(ByRef $hProcess, ByRef $t1, ByRef $t2, ByRef $t3, ByRef $t4)&lt;br /&gt;
&lt;br /&gt;
;BOOL WINAPI GetProcessTimes(&lt;br /&gt;
;  HANDLE hProcess,&lt;br /&gt;
;  LPFILETIME lpCreationTime,&lt;br /&gt;
;  LPFILETIME lpExitTime,&lt;br /&gt;
;  LPFILETIME lpKernelTime,&lt;br /&gt;
;  LPFILETIME lpUserTime&lt;br /&gt;
; )&lt;br /&gt;
;&lt;br /&gt;
   Local $p1 = DllStructGetPtr($t1)&lt;br /&gt;
   Local $p2 = DllStructGetPtr($t2)&lt;br /&gt;
   Local $p3 = DllStructGetPtr($t3)&lt;br /&gt;
   Local $p4 = DllStructGetPtr($t4)&lt;br /&gt;
   ;ConsoleWrite($p1 &amp;amp; &amp;quot;, &amp;quot; &amp;amp; $p2&amp;amp; &amp;quot;, &amp;quot; &amp;amp; $p3 &amp;amp; &amp;quot;, &amp;quot; &amp;amp; $p4 &amp;amp; @LF)&lt;br /&gt;
   Local $ret = dllcall(&amp;quot;kernel32.dll&amp;quot;,&amp;quot;int&amp;quot;, &amp;quot;GetProcessTimes&amp;quot;,&amp;quot;int&amp;quot;,$hProcess ,  &amp;quot;ptr&amp;quot;, $p1, &amp;quot;ptr&amp;quot;, $p2, &amp;quot;ptr&amp;quot;, $p3, &amp;quot;ptr&amp;quot;, $p4)&lt;br /&gt;
   If $ret[0] = 0 Then&lt;br /&gt;
      ConsoleWrite(&amp;quot;(&amp;quot; &amp;amp; @ScriptLineNumber &amp;amp; &amp;quot;) : = Error in GetProcessTimes call&amp;quot; &amp;amp; @LF)&lt;br /&gt;
      SetError(1, 0 , $ret[0])&lt;br /&gt;
   EndIf&lt;br /&gt;
   Return $ret[0]&lt;br /&gt;
EndFunc&lt;br /&gt;
Func ProfileInit()&lt;br /&gt;
   Local $process = OpenProcess(@AutoItPID)&lt;br /&gt;
   if @error then&lt;br /&gt;
      ConsoleWrite(&amp;quot;!OpenProcess failed terminating&amp;quot; &amp;amp; @LF)&lt;br /&gt;
      Exit&lt;br /&gt;
   EndIf&lt;br /&gt;
   Local $ret[4]&lt;br /&gt;
   $ret[0] = 2&lt;br /&gt;
   Local $t1 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t2 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t3 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t4 = DllStructCreate($FILETIME)    &lt;br /&gt;
   If GetProcessTimes($process, $t1, $t2, $t3, $t4) Then&lt;br /&gt;
      $ret[$ret[0] + 1] = $process&lt;br /&gt;
      $ret[1] = FileTimeToNum($t3)&lt;br /&gt;
      $ret[2] = FileTimeToNum($t4)&lt;br /&gt;
   Else&lt;br /&gt;
      ConsoleWrite(&amp;quot;(&amp;quot; &amp;amp; @ScriptLineNumber &amp;amp; &amp;quot;) := @error:=&amp;quot; &amp;amp; @error &amp;amp; &amp;quot;, @extended:?&amp;quot; &amp;amp; @extended &amp;amp; @LF)&lt;br /&gt;
      SetError(@error, @extended, 0)&lt;br /&gt;
   EndIf&lt;br /&gt;
   ;ArrayDump($ret, &amp;quot;ProfileInit Out&amp;quot;)&lt;br /&gt;
   Return $ret&lt;br /&gt;
EndFunc&lt;br /&gt;
Func ProfileDiff(ByRef $init)&lt;br /&gt;
   Local $ret[3]&lt;br /&gt;
   $ret[0] = 2&lt;br /&gt;
   ;ArrayDump($init, &amp;quot;ProfileDiff($init)&amp;quot;)&lt;br /&gt;
   Local $t1 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t2 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t3 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t4 = DllStructCreate($FILETIME)    &lt;br /&gt;
   Local $n1, $n2&lt;br /&gt;
   If GetProcessTimes($init[$init[0] + 1], $t1, $t2, $t3, $t4) Then&lt;br /&gt;
      $ret[1] = FileTimeToNum($t3) - $init[1]&lt;br /&gt;
      $ret[2] = FileTimeToNum($t4) - $init[2]&lt;br /&gt;
   Else&lt;br /&gt;
      ConsoleWrite(&amp;quot;(&amp;quot; &amp;amp; @ScriptLineNumber &amp;amp; &amp;quot;) := @error:=&amp;quot; &amp;amp; @error &amp;amp; &amp;quot;, @extended:=&amp;quot; &amp;amp; @extended &amp;amp; @LF)&lt;br /&gt;
      SetError(@error, 0 , 0)&lt;br /&gt;
   EndIf&lt;br /&gt;
   Return $ret&lt;br /&gt;
EndFunc&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have a some profiling routines. ProfileInit and ProfileDiff we can change our sample to make use of those UDF&#039;s.&lt;br /&gt;
Note that the time returned from ProfileDiff are in 100-nanoseconds intervals. TO get ms we have to divide by 10000.&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
 #include &amp;lt;profiler.au3&amp;gt;&lt;br /&gt;
 Local $i, $j, $sum, $count, $ps, $pd, $uk&lt;br /&gt;
 For $j = 1 to 10&lt;br /&gt;
	$ps = ProfileInit()  &lt;br /&gt;
 	Do&lt;br /&gt;
 		$count += 1&lt;br /&gt;
 		$sum += Random(-5, 5, 1)&lt;br /&gt;
 	Until $sum = 0 OR $count = 100000&lt;br /&gt;
 	; Write/create report&lt;br /&gt;
 	$pd = ProfileDiff($ps)&lt;br /&gt;
 	$uk = Round(($pd[1] + $pd[2])/10000, 0) ;User and kernel time&lt;br /&gt;
 	ConsoleWrite( StringFormat(&amp;quot;%#.6g ms, Iter=%.6d, avg=%.6g&amp;quot;, $uk, $count, $uk/$count) &amp;amp; @LF)&lt;br /&gt;
 	$count = 0&lt;br /&gt;
 Next&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Optimizing code=&lt;br /&gt;
When do we need to optimize our code? Well, thats a good question. A roule of thumb is to make the code work first. If we experience that the code is slow we have to find the reason. When one or more reasons are found we have to consider if it is possible to optimize the code. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a look at a &#039;&#039;real world&#039;&#039; sample. Sorting stuff is a classic. &lt;br /&gt;
==Getting some data==&lt;br /&gt;
Let&#039;s grab some data from autoitscript. The data is not relevant for the sample so if you have a fearly big html file on your disk you could use that instead.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;inet.au3&amp;gt;&lt;br /&gt;
$data = _InetGet(&amp;quot;http://www.autoitscript.com/forum/index.php?showtopic=36941&amp;quot;)&lt;br /&gt;
;$data = ReadFile(&amp;quot;&amp;lt;your file&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Data to plain text. Take one==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Func WordList(ByRef $data)&lt;br /&gt;
;Shave of html tags&lt;br /&gt;
Local $res&lt;br /&gt;
;Return string&lt;br /&gt;
EndFunc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Data to plain text. Take two==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Func Wordlist2(ByRef $data)&lt;br /&gt;
Local $res = StringRegExp($data, &amp;quot;TODO&amp;quot;, 3)&lt;br /&gt;
;Array to string&lt;br /&gt;
;Return string&lt;br /&gt;
EndFunc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Sorting the text. Take one==&lt;br /&gt;
Using bouble sort&lt;br /&gt;
==Sorting the text. Take two==&lt;br /&gt;
Using something faster.&lt;/div&gt;</summary>
		<author><name>Poila</name></author>
	</entry>
	<entry>
		<id>https://www.autoitscript.com/w/index.php?title=Tutorial_Optimizing&amp;diff=12425</id>
		<title>Tutorial Optimizing</title>
		<link rel="alternate" type="text/html" href="https://www.autoitscript.com/w/index.php?title=Tutorial_Optimizing&amp;diff=12425"/>
		<updated>2014-06-04T01:22:47Z</updated>

		<summary type="html">&lt;p&gt;Poila: /* Profiling */ Grammatical and spelling changes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Tutorials]]&lt;br /&gt;
NOTE: This document is work in progress. Your view and contribution on content is welcome. Spellchecking and grammar will be worked on when the document approaches a stable state.&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This tutorial will be about profiling and optimizing code when we have identified a bottleneck. There are several paths down this road. You could analytically evaluate your code, or fragments of it. You could optimize parts that don&#039;t feel good. And you can measure how long time the code takes to run.&lt;br /&gt;
&lt;br /&gt;
=Profiling=&lt;br /&gt;
When we profile the code we use a stopwatch to log how much time that is spent from the code starts until it ends execution. There are two types of time we can use. The real time spent and the CPU time spent to execute the code. Both methods have its usage. But messuring the CPU time should normally result in better knowledge than measuring clock time. The exception could be in routines where the code calls external resources that depends on other factors rather than the CPU. Ex: printer, network, disk IO. &lt;br /&gt;
==The simplest approach==&lt;br /&gt;
Autoit has two handy clock functions to do a regular stopwatch measure of code execution time. Namely &lt;br /&gt;
TimerInit and TimerDiff. TimerInit is used to get a reference point and TimerDiff to get the difference between the reference point and the call to TimerDiff in milliseconds.&lt;br /&gt;
So the simplest possible sample could be:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Local $i, $j, $sum, $count, $ts, $td&lt;br /&gt;
 For $j = 1 to 10&lt;br /&gt;
	$ts = TimerInit()&lt;br /&gt;
 	Do&lt;br /&gt;
 		$count += 1&lt;br /&gt;
 		$sum += Random(-5, 5, 1)&lt;br /&gt;
 	Until $sum = 0 OR $count = 100000&lt;br /&gt;
 	; Write/create report&lt;br /&gt;
 	$td = TimerDiff($ts)&lt;br /&gt;
 	ConsoleWrite( StringFormat(&amp;quot;%#.6g ms, Iter=%.6d, avg=%.6g&amp;quot;, $td, $count, $td/$count) &amp;amp; @LF)&lt;br /&gt;
 	$count = 0&lt;br /&gt;
 Next&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now although this is a reasonable way of measuring execution time, it does not give an accurate picture to identify bottlenecks. And the reason is that it measures real time and not the time spent by the CPU to execute this part of the code. You can probably see this if one of the iterations reaches a $sum=0 in few iterations compared to one that uses max iterations.&lt;br /&gt;
&lt;br /&gt;
==The more accurate approach==&lt;br /&gt;
API notes: GetProcessTimes, GetThreadTimes&lt;br /&gt;
Windows versions based on NT kernel has at least two API calls to make profiling easier for us. GetProcessTimes will return the CPU time spent by the given process. GetThreadTimes will return the CPU time spent by the given thread. As AutoIt does not support user defined threads, we will use the GetProcessTimes call. A [http://www.autoitscript.com/forum/index.php?s=&amp;amp;showtopic=38751 profiling UDF] has been created by [http://www.autoitscript.com/forum/index.php?showuser=7836 @uten] in the AutoItScript forum. As for now we will use that code. Save the code in an include file. I have called mine profiler.au3 and saved it in a include directory. (TODO: Link to page explaining userdefined include directories.)&lt;br /&gt;
&amp;lt;pre&amp;gt;Global $FILETIME = &amp;quot;dword;dword&amp;quot;    ;Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).&lt;br /&gt;
Global $SYSTEMTIME = &amp;quot;ushort;ushort;ushort;ushort;ushort;ushort;ushort;ushort&amp;quot;&lt;br /&gt;
Func FileTimeToNum(ByRef $FT)&lt;br /&gt;
   Return BITOr(BitShift(DllStructGetData($FT, 1), 32), DllStructGetData($FT, 2))&lt;br /&gt;
EndFunc&lt;br /&gt;
Func OpenProcess($pid = @AutoItPID)&lt;br /&gt;
    Local $PROCESS_QUERY_INFORMATION = 0x0400&lt;br /&gt;
    Local $PROCESS_VM_READ = 0x0010&lt;br /&gt;
    $Process = DLLCall(&amp;quot;kernel32.dll&amp;quot;,&amp;quot;int&amp;quot;,&amp;quot;OpenProcess&amp;quot;,&amp;quot;int&amp;quot;, _&lt;br /&gt;
            BitOR($PROCESS_QUERY_INFORMATION,$PROCESS_VM_READ),&amp;quot;int&amp;quot;,0,&amp;quot;int&amp;quot;, $pid)&lt;br /&gt;
    If $Process[0] = 0 Then Return SetError(1, 0, 0)&lt;br /&gt;
   Return $Process[0]&lt;br /&gt;
EndFunc&lt;br /&gt;
Func GetProcessTimes(ByRef $hProcess, ByRef $t1, ByRef $t2, ByRef $t3, ByRef $t4)&lt;br /&gt;
&lt;br /&gt;
;BOOL WINAPI GetProcessTimes(&lt;br /&gt;
;  HANDLE hProcess,&lt;br /&gt;
;  LPFILETIME lpCreationTime,&lt;br /&gt;
;  LPFILETIME lpExitTime,&lt;br /&gt;
;  LPFILETIME lpKernelTime,&lt;br /&gt;
;  LPFILETIME lpUserTime&lt;br /&gt;
; )&lt;br /&gt;
;&lt;br /&gt;
   Local $p1 = DllStructGetPtr($t1)&lt;br /&gt;
   Local $p2 = DllStructGetPtr($t2)&lt;br /&gt;
   Local $p3 = DllStructGetPtr($t3)&lt;br /&gt;
   Local $p4 = DllStructGetPtr($t4)&lt;br /&gt;
   ;ConsoleWrite($p1 &amp;amp; &amp;quot;, &amp;quot; &amp;amp; $p2&amp;amp; &amp;quot;, &amp;quot; &amp;amp; $p3 &amp;amp; &amp;quot;, &amp;quot; &amp;amp; $p4 &amp;amp; @LF)&lt;br /&gt;
   Local $ret = dllcall(&amp;quot;kernel32.dll&amp;quot;,&amp;quot;int&amp;quot;, &amp;quot;GetProcessTimes&amp;quot;,&amp;quot;int&amp;quot;,$hProcess ,  &amp;quot;ptr&amp;quot;, $p1, &amp;quot;ptr&amp;quot;, $p2, &amp;quot;ptr&amp;quot;, $p3, &amp;quot;ptr&amp;quot;, $p4)&lt;br /&gt;
   If $ret[0] = 0 Then&lt;br /&gt;
      ConsoleWrite(&amp;quot;(&amp;quot; &amp;amp; @ScriptLineNumber &amp;amp; &amp;quot;) : = Error in GetProcessTimes call&amp;quot; &amp;amp; @LF)&lt;br /&gt;
      SetError(1, 0 , $ret[0])&lt;br /&gt;
   EndIf&lt;br /&gt;
   Return $ret[0]&lt;br /&gt;
EndFunc&lt;br /&gt;
Func ProfileInit()&lt;br /&gt;
   Local $process = OpenProcess(@AutoItPID)&lt;br /&gt;
   if @error then&lt;br /&gt;
      ConsoleWrite(&amp;quot;!OpenProcess failed terminating&amp;quot; &amp;amp; @LF)&lt;br /&gt;
      Exit&lt;br /&gt;
   EndIf&lt;br /&gt;
   Local $ret[4]&lt;br /&gt;
   $ret[0] = 2&lt;br /&gt;
   Local $t1 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t2 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t3 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t4 = DllStructCreate($FILETIME)    &lt;br /&gt;
   If GetProcessTimes($process, $t1, $t2, $t3, $t4) Then&lt;br /&gt;
      $ret[$ret[0] + 1] = $process&lt;br /&gt;
      $ret[1] = FileTimeToNum($t3)&lt;br /&gt;
      $ret[2] = FileTimeToNum($t4)&lt;br /&gt;
   Else&lt;br /&gt;
      ConsoleWrite(&amp;quot;(&amp;quot; &amp;amp; @ScriptLineNumber &amp;amp; &amp;quot;) := @error:=&amp;quot; &amp;amp; @error &amp;amp; &amp;quot;, @extended:?&amp;quot; &amp;amp; @extended &amp;amp; @LF)&lt;br /&gt;
      SetError(@error, @extended, 0)&lt;br /&gt;
   EndIf&lt;br /&gt;
   ;ArrayDump($ret, &amp;quot;ProfileInit Out&amp;quot;)&lt;br /&gt;
   Return $ret&lt;br /&gt;
EndFunc&lt;br /&gt;
Func ProfileDiff(ByRef $init)&lt;br /&gt;
   Local $ret[3]&lt;br /&gt;
   $ret[0] = 2&lt;br /&gt;
   ;ArrayDump($init, &amp;quot;ProfileDiff($init)&amp;quot;)&lt;br /&gt;
   Local $t1 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t2 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t3 = DllStructCreate($FILETIME)&lt;br /&gt;
   Local $t4 = DllStructCreate($FILETIME)    &lt;br /&gt;
   Local $n1, $n2&lt;br /&gt;
   If GetProcessTimes($init[$init[0] + 1], $t1, $t2, $t3, $t4) Then&lt;br /&gt;
      $ret[1] = FileTimeToNum($t3) - $init[1]&lt;br /&gt;
      $ret[2] = FileTimeToNum($t4) - $init[2]&lt;br /&gt;
   Else&lt;br /&gt;
      ConsoleWrite(&amp;quot;(&amp;quot; &amp;amp; @ScriptLineNumber &amp;amp; &amp;quot;) := @error:=&amp;quot; &amp;amp; @error &amp;amp; &amp;quot;, @extended:=&amp;quot; &amp;amp; @extended &amp;amp; @LF)&lt;br /&gt;
      SetError(@error, 0 , 0)&lt;br /&gt;
   EndIf&lt;br /&gt;
   Return $ret&lt;br /&gt;
EndFunc&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have a some profiling routines. ProfileInit and ProfileDiff we can change our sample to make use of those UDF&#039;s.&lt;br /&gt;
Note that the time returned from ProfileDiff are in 100-nanoseconds intervals. TO get ms we have to divide by 10000.&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
 #include &amp;lt;profiler.au3&amp;gt;&lt;br /&gt;
 Local $i, $j, $sum, $count, $ps, $pd, $uk&lt;br /&gt;
 For $j = 1 to 10&lt;br /&gt;
	$ps = ProfileInit()  &lt;br /&gt;
 	Do&lt;br /&gt;
 		$count += 1&lt;br /&gt;
 		$sum += Random(-5, 5, 1)&lt;br /&gt;
 	Until $sum = 0 OR $count = 100000&lt;br /&gt;
 	; Write/create report&lt;br /&gt;
 	$pd = ProfileDiff($ps)&lt;br /&gt;
 	$uk = Round(($pd[1] + $pd[2])/10000, 0) ;User and kernel time&lt;br /&gt;
 	ConsoleWrite( StringFormat(&amp;quot;%#.6g ms, Iter=%.6d, avg=%.6g&amp;quot;, $uk, $count, $uk/$count) &amp;amp; @LF)&lt;br /&gt;
 	$count = 0&lt;br /&gt;
 Next&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Optimizing code=&lt;br /&gt;
When do we need to optimize our code? Well, thats a good question. A roule of thumb is to make the code work first. If we experience that the code is slow we have to find the reason. When one or more reasons are found we have to consider if it is possible to optimize the code. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a look at a &#039;&#039;real world&#039;&#039; sample. Sorting stuff is a classic. &lt;br /&gt;
==Getting some data==&lt;br /&gt;
Let&#039;s grab some data from autoitscript. The data is not relevant for the sample so if you have a fearly big html file on your disk you could use that instead.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;inet.au3&amp;gt;&lt;br /&gt;
$data = _InetGet(&amp;quot;http://www.autoitscript.com/forum/index.php?showtopic=36941&amp;quot;)&lt;br /&gt;
;$data = ReadFile(&amp;quot;&amp;lt;your file&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Data to plain text. Take one==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Func WordList(ByRef $data)&lt;br /&gt;
;Shave of html tags&lt;br /&gt;
Local $res&lt;br /&gt;
;Return string&lt;br /&gt;
EndFunc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Data to plain text. Take two==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Func Wordlist2(ByRef $data)&lt;br /&gt;
Local $res = StringRegExp($data, &amp;quot;TODO&amp;quot;, 3)&lt;br /&gt;
;Array to string&lt;br /&gt;
;Return string&lt;br /&gt;
EndFunc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Sorting the text. Take one==&lt;br /&gt;
Using bouble sort&lt;br /&gt;
==Sorting the text. Take two==&lt;br /&gt;
Using something faster.&lt;/div&gt;</summary>
		<author><name>Poila</name></author>
	</entry>
</feed>