I have run the code in the first post with these results:
Time to run with AdlibRegistered: 14571.9029530593
Time to run with AdlibUnRegistered: 13025.2308415184
Time to run with AdlibRegistered to _FakeTray: 13365.1403195613
A few comments:
A large number of loops are much faster in 64 bit code.
The outer loop (j-loop) is always faster in second and third passes. In this code about 1 second faster. This gives incorrect results. It should be taken into account by introducing an initial first run.
$aSmallerArray is not be reset between each pass.
Tooltip: If Not Mod( $i, 20736 ) Then ToolTip("We are " & $i/20736 & "% done", 0, 0)
Added _ArrayDisplayEx that can display large arrays
New code:
#AutoIt3Wrapper_UseX64=y
#AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include "Display\Functions\ArrayDisplayEx\ArrayDisplayEx.au3"
Global $iBlockSize = 20, $iWidth = 1920, $iHeight = 1080, $iIndexLength = $iWidth * $iHeight, $iPercentDone, $sLastMsg
Global $aBigArray[$iIndexLength], $aSmallerArray[$iWidth / $iBlockSize * $iHeight / $iBlockSize]
Global $sAdlib = [" First run: ", "Registered: ", "UnRegistered: ", "Registered to _FakeTray: "]
Global $ixBlocks = $iWidth / $iBlockSize, $iBlockIndex, $iBlockX, $iBlockY, $timer, $x, $y
For $j = 0 To 3
If $j = 1 Then
AdlibRegister("_CheckTray", 100)
ElseIf $j = 2 Then
AdlibUnRegister("_CheckTray")
ElseIf $j = 3 Then
AdlibRegister("_FakeTray", 100)
EndIf
$aSmallerArray = 0
Dim $aSmallerArray[$iWidth / $iBlockSize * $iHeight / $iBlockSize]
$timer = TimerInit()
For $i = 0 To $iIndexLength - 1 ; Loop through $aBigArray
$aBigArray[$i] = Random(1, 10, 1)
If Not Mod( $i, 20736 ) Then ToolTip("We are " & $i/20736 & "% done", 0, 0)
$y = Floor($i / $iWidth) ; Convert index to Y coordinate
$x = Floor($i - ($y * $iWidth)) ; Convert index to X coordinate
$iBlockX = Floor($x / $iBlockSize) ; Convert X coord to xBlock coord
$iBlockY = Floor($y / $iBlockSize) ; Convert Y coord to yBlock coord
$iBlockIndex = Int($iBlockX + ($iBlockY * $ixBlocks)) ; Convert into a blockIndex
$aSmallerArray[$iBlockIndex] += Int($aBigArray[$i]) ; Add into $aSmallerArray
Next
ConsoleWrite("Time to run with Adlib" & $sAdlib[$j] & TimerDiff($timer) & @CRLF)
Next
Global $aWidth = [ 0, 65 ]
Global $aAlign = [ [ 0, "l" ], [ 1, "r" ] ]
Global $aFeatures = [ [ "ColWidthMin", $aWidth ], _
[ "ColAlign", $aAlign ] ]
_ArrayDisplayEx( $aBigArray, "$aBigArray", "", 0, $aFeatures )
_ArrayDisplayEx( $aSmallerArray, "$aSmallerArray", "", 0, $aFeatures )
Func _CheckTray()
Switch TrayGetMsg()
Case "Meow"
Return
Case "Woof"
Return
EndSwitch
EndFunc ;==>_CheckTray
Func _FakeTray()
Local $sMeow = "Oink"
Switch $sMeow
Case "Meow"
Return
Case "Woof"
Return
EndSwitch
EndFunc ;==>_FakeTray
Exit
#cs
Time to run with Adlib First run: 9354.58487313101
Time to run with AdlibRegistered: 8572.65596364715
Time to run with AdlibUnRegistered: 8436.5804675481
Time to run with AdlibRegistered to _FakeTray: 8573.66191708517
#ce
And results:
Time to run with Adlib First run: 9354.58487313101
Time to run with AdlibRegistered: 8572.65596364715
Time to run with AdlibUnRegistered: 8436.5804675481
Time to run with AdlibRegistered to _FakeTray: 8573.66191708517
Now there is not much difference between the last 3 results.
For arrays with 2 million elements, it's a great advantage to use compiled code. Since UDFs already exist to execute VB code (and C# code) in an AutoIt script through the .NET Framework, it's not difficult.
c.vb:
Imports System
Class Au3Class
Dim aSmallerArray As Integer()
Public Function MyMethod1( iBlockSize As Integer, iWidth As Integer, iHeight As Integer ) As Integer()
Dim ixBlocks As Integer = iWidth / iBlockSize
ReDim aSmallerArray(ixBlocks * iHeight/iBlockSize - 1)
Dim iIndexLength As Integer = iWidth * iHeight
Dim aBigArray(iIndexLength-1) As Integer
Dim oRnd As New Random()
Dim x, y, iBlockX, iBlockY, iBlockIndex As Integer
For i As Integer = 0 To iIndexLength - 1
aBigArray(i) = oRnd.Next( 1, 10+1 )
y = Math.Floor( i / iWidth ) : x = Math.Floor( i - y * iWidth )
iBlockX = Math.Floor( x / iBlockSize ) : iBlockY = Math.Floor( y / iBlockSize )
iBlockIndex = iBlockX + iBlockY * ixBlocks
aSmallerArray(iBlockIndex) += aBigArray(i)
Next
Return aBigArray
End Function
Public Function MyMethod2() As Integer()
Return aSmallerArray
End Function
End Class
c.au3:
#AutoIt3Wrapper_UseX64=y
#AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include "DotNet\DotNetAll.au3"
#include "Display\Functions\ArrayDisplayEx\ArrayDisplayEx.au3"
Opt( "MustDeclareVars", 1 )
Example()
Func Example()
Local $oNetCode = DotNet_LoadVBcode( FileRead( "c.vb" ), "System.dll" )
Local $oAu3Class = DotNet_CreateObject( $oNetCode, "Au3Class" )
Local $timer = TimerInit()
Local $aBigArray = $oAu3Class.MyMethod1( 20, 1920, 1080 )
Local $aSmallerArray = $oAu3Class.MyMethod2()
ConsoleWrite( TimerDiff( $timer ) & @CRLF ) ; 221.589018567889
Local $aWidth = [ 0, 65 ]
Local $aAlign = [ [ 0, "l" ], [ 1, "r" ] ]
Local $aFeatures = [ [ "ColWidthMin", $aWidth ], _
[ "ColAlign", $aAlign ] ]
_ArrayDisplayEx( $aBigArray, "$aBigArray", "", 0, $aFeatures )
_ArrayDisplayEx( $aSmallerArray, "$aSmallerArray", "", 0, $aFeatures )
EndFunc
Note the time: 221 milliseconds.
You cannot do anything about the Sleep function in TrayGetMsg() and GUIGetMsg(), but you can completely avoid the functions by using Windows messages directly through GUIRegisterMsg() (still in MessageLoop mode).
Tests.7z