Jump to content

Slow recursion


UEZ
 Share

Recommended Posts

I wrote a short test case, as is customary with these type of issues.

Part of the output:

Test #20
    Loop result: 2432902008176640000 Time: 0.0203936533833211
    Recursive result: 2432902008176640000 Time: 0.121523824955406

This shows that recursive is indeed slower. The loop approach is around 6 times faster. The validity of this test is questionable, at best, though..

I've also let it run to 500. The results were wrong , but the time it took to calculate them may still be an indication. All it did was make the test results more obvious.

Code to perform the tests:

;; Doing a little test to make sure it works.
$s = "Recursive: " & _RecurFac(5) & @CRLF & _
        "Loop: " & _LoopFac(5) & @CRLF & _
        "Expecting: " & (5*4*3*2*1) & @CRLF
        
ConsoleWrite($s)

For $i = 1 to 20 ; 500
    $startLoop = TimerInit()
    $loopRes = _LoopFac($i)
    $endLoop = TimerDiff($startLoop)
    
    $startRecur = TimerInit()
    $recurRes = _RecurFac($i)
    $endRecur = TimerDiff($startRecur)
    
    ConsoleWrite("Test #" & $i & @CRLF & @TAB & "Loop result: " & $loopRes & " Time: " & $endLoop & @CRLF & @TAB & "Recursive result: " & $recurRes& " Time: " & $endRecur & @CRLF)
Next


Func _RecurFac($n)
    If ($n == 0) Then Return 1
    Return $n * _RecurFac($n-1)
EndFunc

Func _LoopFac($n)
    Local $res = 1
    For $i = 1 to $n
        $res *= $i
    Next
    Return $res
EndFunc
Edited by Manadar
Link to comment
Share on other sites

  • Replies 71
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

I made the same test also with factorial :) but couldn't see any great difference.

Maybe a more complicated example (quicksort ) could help to get more about runtime if a relative big text is sorted.

If I have enough time I will try to implement quicksort :)

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Here an example with Fibonnaci numbers:

$n = 25

$bench_start = TimerInit()
ConsoleWrite(Fibonacci_i($n)  & @CRLF)
$bench_end_i = Round(TimerDiff($bench_start), 4)

$bench_start = TimerInit()
ConsoleWrite(Fibonacci_r($n) & @CRLF)
$bench_end_r = Round(TimerDiff($bench_start), 4)

ConsoleWrite(@CRLF & "Iterative: " & $bench_end_i & " ms" & @CRLF & "Recursive: " & $bench_end_r & " ms" & @CRLF & "Diff: " & Abs($bench_end_i - $bench_end_r) & " ms !" & @CRLF & @CRLF)

Func Fibonacci_i($f)
    Dim $arr_fib[3]
    $arr_fib[0] = 0
    $arr_fib[1] = 1
    For $i = 2 To $f
        $arr_fib[2] = $arr_fib[1] + $arr_fib[0]
        $arr_fib[0] = $arr_fib[1]
        $arr_fib[1] = $arr_fib[2]
    Next
    Return $arr_fib[2]
EndFunc

Func Fibonacci_r($f)
    If $f = 0 Then Return 0
    If $f = 1 Then Return 1
    Return Fibonacci_r($f - 1) + Fibonacci_r($f - 2)
EndFunc

Output results:

CODE
75025

75025

Iterative: 2.4656 ms

Recursive: 1186.7369 ms

Diff: 1184.2713 ms !

Huge difference !

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

The issue with the original code has nothing to do with recursion. It's even obvious while its running that the recursion depth is only like 2 but the redraw times are atrocious (half a second). The slowness is because of GDI. That being said, if someone can provide faster method for drawing then I would try that.

Link to comment
Share on other sites

The issue with the original code has nothing to do with recursion. It's even obvious while its running that the recursion depth is only like 2 but the redraw times are atrocious (half a second). The slowness is because of GDI. That being said, if someone can provide faster method for drawing then I would try that.

How to you measure the GDI+ drawing?

I modified it the code from my 12th post:

#include 
Opt('MustDeclareVars', 1)

Global Const $Pi = 3.1415926535897932384626
Global Const $width = 800
Global Const $height = 600
Global $hGUI, $hGraphic, $Pen
Global $angle = 0, $x1, $y1, $x2, $y2
Global $length, $depth, $dir, $degree, $dist_rel, $average = 0, $c = 0

$hGUI = GUICreate("GDI+: L-System Fractals by UEZ 2009", $width, $height)
GUISetState()

_GDIPlus_Startup ()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND ($hGUI)
$Pen = _GDIPlus_PenCreate(0, 1) ; create a pen to use later on
_GDIPlus_GraphicsSetSmoothingMode($hGraphic, 4) ; AntiAlias
_GDIPlus_GraphicsClear($hGraphic, 0xFFFFFFFF)


$x1 = $width / 2
$y1 = $height / 1.1
$length = 110
$depth = 10
$dir = 1
$angle = 5
Pythagoras($length, $depth, $dir)
ConsoleWrite(@CRLF & "Average: " & Round ($average / $c, 2) & " ms." & @CRLF)
Sleep(1000 * 10)
_Exit()

Func Pythagoras($length, $split, $dir)
    If $split = 0 Then
        Pythagoras_Square($length)
    Else
        $dist_rel = Sqrt(3) / 2
        $degree = 30
        Pythagoras_Square($length)
        Forward_Only($length)
        Turn(-$dir * 1 * $degree)
        Pythagoras($length * $dist_rel, $split - 1, 1)
        Turn($dir * 3 * $degree)
        Forward_Only($length * $dist_rel)
        Pythagoras($length / 2, $split - 1, 1)
        Forward_Only(-$length * $dist_rel)
        Turn(-$dir * 2 * $degree)
        Forward_Only(-$length)
    EndIf
    Sleep(1)
EndFunc

Func Pythagoras_Square($length)
    Local $i
    For $i = 1 To 4
        Draw_and_Forward($length)
        Turn($dir * 90)
    Next
EndFunc

Func Turn ($degrees)
    $angle = $angle + ($degrees * $Pi / 180)
EndFunc

Func Draw_and_Forward($length)
    Local $bench_start = TimerInit()
    $x2 = $x1 + Cos($angle) * $length
    $y2 = $y1 + Sin($angle) * $length
    _GDIPlus_PenSetColor($Pen, "0x7F000000") ;Set the pen color
    _GDIPlus_GraphicsDrawLine($hGraphic, $x1, $y1, $x2, $y2, $Pen)
    $x1 = $x2
    $y1 = $y2
    Local $bench_end = TimerDiff($bench_start)
;~  ConsoleWrite(Round($bench_end, 4) & @CRLF)
    $average += $bench_end
    $c += 1
EndFunc

Func Forward_Only($length)
    $x2 = $x1 + Cos($angle) * $length
    $y2 = $y1 + Sin($angle) * $length
    $x1 = $x2
    $y1 = $y2
EndFunc


Func _Exit()
    ; Clean up resources
    _GDIPlus_PenDispose($Pen)
    _GDIPlus_GraphicsDispose ($hGraphic)
    _GDIPlus_Shutdown ()
    Exit
EndFuncoÝ÷ Ù¬º[[÷«j´Û¬2>v¶°x?mh­­v¶°x+axºÚ"µÍÚ[ÛYH    ÑÑTË]LÉÝÂÜ
    ÌÎNÓ]ÝXÛUÉÌÎNËJBÛØ[ÛÛÝ    ÌÍÔHHËMMNLLÍNMÎLÌÎ

ÛØ[ÛÛÝ ÌÍÝÚYHÛØ[ÛÛÝ   ÌÍÚZYÚH
ÛØ[   ÌÍÚÕRK  ÌÍÚÜXË ÌÍÔ[ÛØ[    ÌÍØ[ÛHH ÌÍÞK ÌÍÞLK    ÌÍÞ  ÌÍÞLÛØ[    ÌÍÛ[Ý   ÌÍÙ  ÌÍÙ  ÌÍÙYÜYK ÌÍÙÝÜ[ ÌÍØ]YÙHH    ÌÍØÈHß ÌÍÚÕRHHÕRPÜX]J    ][ÝÑÑJÎTÞÝ[HXÝ[ÈHQVI][ÝË  ÌÍÝÚY   ÌÍÚZYÚ
BßÕRTÙ]Ý]J
BßÑÑT×ÔÝ

Bß ÌÍÚÜXÈHÑÑT×ÑÜXÜÐÜX]QÛRÓ
    ÌÍÚÕRJBß   ÌÍÔ[HÑÑT×Ô[ÜX]JJHÈÜX]HH[ÈÙH]ÛßÑÑT×ÑÜXÜÔÙ]Û[ÛÝ[Ó[ÙJ   ÌÍÚÜXË
HÈ[P[XÂßÑÑT×ÑÜXÜÐÛX  ÌÍÚÜXËBÌÍÞHH    ÌÍÝÚYÈÌÍÞLHH    ÌÍÚZYÚÈKBÌÍÛ[ÝHLLÌÍÙHLÌÍÙHBÌÍØ[ÛHH
BÛØ[  ÌÍØ[ÚÜÝH[Y[]

B]YÛÜÊ   ÌÍÛ[Ý   ÌÍÙ  ÌÍÙBÛØ[    ÌÍØ[ÚÙ[H[YY    ÌÍØ[ÚÜÝ
BÛÛÛÛUÜ]JÔ    [È ][ÝÔ[[YN  ][ÝÈ  [ÈÝ[
    ÌÍØ[ÚÙ[ÈL
H   [È ][ÝÈÙXÛÛË][ÝÈ   [ÈÔBÛY
L
L
BÑ^]

B[È]YÛÜÊ    ÌÍÛ[Ý   ÌÍÜÜ]   ÌÍÙBY    ÌÍÜÜ]H[]YÛÜ×ÔÜ]XJ  ÌÍÛ[Ý
B[ÙB   ÌÍÙÝÜ[HÜ
ÊHÈ   ÌÍÙYÜYHHÌ]YÛÜ×ÔÜ]XJ   ÌÍÛ[Ý
BÜØÓÛJ  ÌÍÛ[Ý
BIÌÍÙ
H
    ÌÍÙYÜYJB]YÛÜÊ    ÌÍÛ[Ý
    ÌÍÙÝÜ[ ÌÍÜÜ]HKJB   ÌÍÙ
È
    ÌÍÙYÜYJBÜØÓÛJ   ÌÍÛ[Ý
    ÌÍÙÝÜ[
B]YÛÜÊ   ÌÍÛ[ÝÈ ÌÍÜÜ]HKJBÜØÓÛJIÌÍÛ[Ý
    ÌÍÙÝÜ[
BIÌÍÙ

    ÌÍÙYÜYJBÜØÓÛJIÌÍÛ[Ý
B[YÛY
JB[[Â[È]YÛÜ×ÔÜ]XJ    ÌÍÛ[Ý
BØØ[  ÌÍÚBÜ   ÌÍÚHHHÈ
]×Ø[ÑÜØ
    ÌÍÛ[Ý
B   ÌÍÙ
L
B^[[Â[È
    ÌÍÙYÜYÊB   ÌÍØ[ÛHH ÌÍØ[ÛH
È
    ÌÍÙYÜYÈ
    ÌÍÔHÈN
B[[Â[È]×Ø[ÑÜØ
    ÌÍÛ[Ý
B   ÌÍÞH ÌÍÞH
ÈÛÜÊ    ÌÍØ[ÛJH
    ÌÍÛ[Ý   ÌÍÞLH    ÌÍÞLH
ÈÚ[   ÌÍØ[ÛJH
    ÌÍÛ[ÝßÑÑT×Ô[Ù]ÛÛÜ  ÌÍÔ[ ][ÝÌ
Ñ  ][ÝÊHÔÙ]H[ÛÛÜßÑÑT×ÑÜXÜÑ]Ó[J ÌÍÚÜXË ÌÍÞK ÌÍÞLK    ÌÍÞ  ÌÍÞL ÌÍÔ[B    ÌÍÞHH    ÌÍÞ  ÌÍÞLHH   ÌÍÞL[[Â[ÈÜØÓÛJ ÌÍÛ[Ý
B   ÌÍÞH ÌÍÞH
ÈÛÜÊ    ÌÍØ[ÛJH
    ÌÍÛ[Ý   ÌÍÞLH    ÌÍÞLH
ÈÚ[   ÌÍØ[ÛJH
    ÌÍÛ[Ý   ÌÍÞHH    ÌÍÞ  ÌÍÞLHH   ÌÍÞL[[Â[ÈÑ^]

BÈÛX[ÛÝÙÂßÑÑT×Ô[ÜÜÙJ  ÌÍÔ[BßÑÑT×ÑÜXÜÑÜÜÙH
    ÌÍÚÜXÊBßÑÑT×ÔÚ]ÝÛ

B^][[

If I compare the GDI+ drawing time against without drawing GDI+:

Without GDI+ drawing: Runtime: 31.9456 seconds.

With GDI+ drawing: Runtime: 31.9378 seconds.

My conclusion: I cannot agree what you said! Fibonacci numbers is also a proof that recursion is the problem in AutoIt (mentioned by Valik in post #24).

If I can find time I will try to implement one of the L-System example to an iterative version. I bet it would be much faster...

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Would you please elaborate on that? I am very interested in how AutoIt works "under the hook" in this particular instance.

It's irrelevant, it's an implementation detail. It's subject to change and off the top of my head I'm not sure exactly what we're doing at the moment.
Link to comment
Share on other sites

If I compare the GDI+ drawing time against without drawing GDI+:

Without GDI+ drawing: Runtime: 31.9456 seconds.

With GDI+ drawing: Runtime: 31.9378 seconds.

My conclusion: I cannot agree what you said! Fibonacci numbers is also a proof that recursion is the problem in AutoIt (mentioned by Valik in post #24).

If I can find time I will try to implement one of the L-System example to an iterative version. I bet it would be much faster...

UEZ

The speed of the Pythagoras() function is irrelevant when putting a timer around _GDIPlus_GraphicsDrawImage() alone is taking over 500ms.

Link to comment
Share on other sites

I wrote L-System Fractals using recursion but the drawing is relatively slow when I compare it with e.g. web based implementations.

Is this a limit of AutoIt or better say a limit of an interpreter language?

Of course it depends also on recursions depth...

Regards,

UEZ

First, in your code, you need to avoid division as much as possible - it is a relatively slow operation (replace it with multiplication). Calculate any of your constants (such as $Pi / 180) before hand, and simply multiply by that. "Sqrt" is also a relatively slow function (as is Cos, Sin, etc. unless they use a lookup table) - calculate it once at the beginning, and use the result as a constant. Secondly, that "Sleep" call in your "Pythagoras" function is pointless and slows down the program by quite a bit. Thirdly, anti-aliasing is a killer operation for any program (or game). Avoid using anti-aliasing unless it is absolutely required (such as quality rendering). Also use double-buffering. Render to an off-screen surface (back-buffer), then flip the back-buffer and front-buffer. Finally, avoid using GDI for speed critical graphics applications (hence why Vista/7 uses Direct3D for rendering). Use Direct3D or OpenGL for the rendering (even if it is just the off-screen rendering), and then if you must, you can copy over the back-buffer and render it using GDI. (And then, of course, you have the inevitable speed loss from using AutoIt.) Edited by cppman
Link to comment
Share on other sites

I think _WinAPI_BitBlt should be the fastest way to refresh your gui but I can't adapt any examples of its usage in AutoIt.

Argh, this is the second time I fail at just that. I fucking hate device contexts :)

#include <gdiplus.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode",1)

Global Const $Width=800
Global Const $Height=600
$hWnd=GUICreate("Double buffering with GDI(+)",$Width,$Height)

GUISetOnEvent(-3,"close")


_GDIPlus_Startup()

$hGraphics=_GDIPlus_GraphicsCreateFromHWND($hWnd)

$hBitmap=_GDIPlus_BitmapCreateFromGraphics($Width,$Height,$hGraphics)
$hBackbuffer=_GDIPlus_ImageGetGraphicsContext($hBitmap)

$ScreenDc=_WinAPI_GetDC($hWnd)

GUISetState()

$i=0
$timepool=0
Do
    _GDIPlus_GraphicsClear($hBackbuffer,0xFF0000FF)
    
    $timer=TimerInit()



    
    
   ; GDI+ method
   ;~    _GDIPlus_GraphicsDrawImageRect($hGraphics,$hBitmap,0,0,$Width,$Height)
    
    
   ; GDI method
    $dc=_GDIPlus_GraphicsGetDC($hBackbuffer)
    _WinAPI_BitBlt($ScreenDc,0,0,$Width,$Height,$dc,0,0,$SRCCOPY )
    _GDIPlus_GraphicsReleaseDC($hBackbuffer,$dc)
    
    If Not Mod($i,10) Then
        ConsoleWrite("Avarage Buffer flipping time: "&Round($timepool/10,1)&" ms."&@CRLF)
        $timepool=0
    Else
        $timepool+=TimerDiff($timer)
    EndIf
    
    
    $i+=1
Until Not Sleep(100)



Func close()
    _WinAPI_ReleaseDC($hWnd,$ScreenDc)
    _GDIPlus_GraphicsDispose($hBackbuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()

    Exit
EndFunc

After som debugging I found out that the method fails because you cannot access the bitmap from $dc, why I cannot figure out, it works when you get the dc from a graphics that was created from the screen.

Argh I fucking hate device contexts :)

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

Why are you mixing GDI+ and GDI stuff? Shouldn't you being using one or the other?

I can't believe you guys are struggling with BitBlt(). There are a billion examples on the internet for using it and it should be a pretty simple conversion from the C code to AutoIt since I think all the C functions have WinAPI wrappers.

Link to comment
Share on other sites

Why are you mixing GDI+ and GDI stuff? Shouldn't you being using one or the other?

I can't believe you guys are struggling with BitBlt(). There are a billion examples on the internet for using it and it should be a pretty simple conversion from the C code to AutoIt since I think all the C functions have WinAPI wrappers.

Because Bitmap::DrawImage is a really slow, and weaponx suggested that bitblt would be faster, which it should since it's hardware accelerated which DrawImage is not.

Well yeah, and it's not a very hard function, that's why I'm so frustrated with it.

Another failed attempt:

#include <gdiplus.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode",1)

Global Const $Width=800
Global Const $Height=600
$hWnd=GUICreate("Double buffering with GDI(+)",$Width,$Height)

GUISetOnEvent(-3,"close")


_GDIPlus_Startup()

$hGraphics=_GDIPlus_GraphicsCreateFromHWND($hWnd)

$hBitmap=_GDIPlus_BitmapCreateFromGraphics($Width,$Height,$hGraphics)
$hBackbuffer=_GDIPlus_ImageGetGraphicsContext($hBitmap)

$ScreenDc=_WinAPI_GetDC($hWnd)

GUISetState()

Do
    _GDIPlus_GraphicsClear($hBackbuffer,0xFF0000FF)
    

    
    $gdibitmap=_GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
    $dc=_WinAPI_CreateCompatibleDC($ScreenDc)
    _WinAPI_SelectObject($dc,$gdibitmap)
    _WinAPI_DeleteDC($dc)
    _WinAPI_DeleteObject($gdibitmap)
    
    _WinAPI_BitBlt($ScreenDc,0,0,$Width,$Height,$dc,0,0,$SRCCOPY )

    


Until Not Sleep(250)



Func close()
    _WinAPI_ReleaseDC($hWnd,$ScreenDc)
    _GDIPlus_GraphicsDispose($hBackbuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()

    Exit
EndFunc
Edited by monoceres

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

You're skipping stuff and trying to mix in GDI+ stuff and it's no wonder you're getting frustrated. Chances are, the HBITMAP you are trying to load into a DC is not compatible.

Use the Windows API. Or use GD+. Don't mix the two unless you are 100% sure you know what you're doing.

Link to comment
Share on other sites

First, in your code, you need to avoid division as much as possible - it is a relatively slow operation (replace it with multiplication). Calculate any of your constants (such as $Pi / 180) before hand, and simply multiply by that. "Sqrt" is also a relatively slow function (as is Cos, Sin, etc. unless they use a lookup table) - calculate it once at the beginning, and use the result as a constant. Secondly, that "Sleep" call in your "Pythagoras" function is pointless and slows down the program by quite a bit. Thirdly, anti-aliasing is a killer operation for any program (or game). Avoid using anti-aliasing unless it is absolutely required (such as quality rendering). Also use double-buffering. Render to an off-screen surface (back-buffer), then flip the back-buffer and front-buffer. Finally, avoid using GDI for speed critical graphics applications (hence why Vista/7 uses Direct3D for rendering). Use Direct3D or OpenGL for the rendering (even if it is just the off-screen rendering), and then if you must, you can copy over the back-buffer and render it using GDI. (And then, of course, you have the inevitable speed loss from using AutoIt.)

Thanks for your hints - this is definitely a way to tune a code :) but my issue is with recursion!

Neither I'm an amateur nor a pro coder just a hobbyist but I wanted to know why recursion starting at a particular level gets much (exponential?) slower. Have a look on Fibonacci numbers. Valik already answered shortly why it is slower...

Currently the discussion is about double buffering methods but I like it :) .

THANKS ANYWAY FOR YOUR POSTS!

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Comparison of both double buffering methods:

#include <gdiplus.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode", 1)

Global $hBackbuffer, $hBitmap, $hGraphics, $ScreenDc, $gdibitmap, $dc 
Global $hGraphic, $Bitmap, $GDI_Buffer
Global $bench_start_BitBlt, $bench_start_Classic, $time_diff_bb, $time_diff_c
Global Const $Width = 800
Global Const $Height = 600
Global $ticks = 2345
$hGUI = GUICreate("Double buffering with GDI(+)", $Width, $Height)

;~ GUISetOnEvent(-3, "close")

GDIPlus_DB_BitBlt()
Sleep(500)
GDIPlus_DB_Classic()

ConsoleWrite("Diff: " & Round($time_diff_c - $time_diff_bb, 4) & " ms | " & Round(Abs(100 - $time_diff_c / $time_diff_bb * 100), 2) & "%" & @CRLF & @CRLF)

Exit

Func GDIPlus_DB_BitBlt()
    _GDIPlus_Startup()
    $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics($Width, $Height, $hGraphics)
    $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    $ScreenDc = _WinAPI_GetDC($hGUI)
    GUISetState()
    
    $bench_start_BitBlt = TimerInit()
    For $x = 1 To $ticks
        _GDIPlus_GraphicsClear($hBackbuffer, 0xFF0000FF)
;~         _GDIPlus_GraphicsFillEllipse($hBackbuffer, $Width / Random(1, 8, 1), $Height / Random(1, 8, 1), Random(1, $Width, 1), Random(1, $Height, 1))
        $gdibitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
        $dc = _WinAPI_CreateCompatibleDC($ScreenDc)
        _WinAPI_SelectObject($dc, $gdibitmap)
        _WinAPI_DeleteObject($gdibitmap)
        _WinAPI_BitBlt($ScreenDc, 0, 0, $Width, $Height, $dc, 0, 0, $SRCCOPY)
        _WinAPI_DeleteDC($dc)
    Next
    $time_diff_bb = TimerDiff($bench_start_BitBlt)
    ConsoleWrite("BitBlt Runtime: " & Round($time_diff_bb, 2) & " ms. Average: " & Round($time_diff_bb / $ticks, 4) & " ms." & @CRLF)
    close()
EndFunc

Func GDIPlus_DB_Classic()
    _GDIPlus_Startup ()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND ($hGUI)
    $Bitmap = _GDIPlus_BitmapCreateFromGraphics($width, $height, $hGraphic)
    $GDI_Buffer = _GDIPlus_ImageGetGraphicsContext($Bitmap)
    GUISetState()
    
    $bench_start_Classic = TimerInit()
    For $x = 1 To $ticks
        _GDIPlus_GraphicsClear($GDI_Buffer, 0xFF0000FF)
;~         _GDIPlus_GraphicsFillEllipse($GDI_Buffer, $Width / Random(1, 8, 1), $Height / Random(1, 8, 1), Random(1, $Width, 1), Random(1, $Height, 1))
        _GDIPlus_GraphicsDrawImageRect($hGraphic, $Bitmap, 0, 0, $width, $height)
    Next
    $time_diff_c = TimerDiff($bench_start_Classic)
    ConsoleWrite("Classic Runtime: " & Round($time_diff_c, 2) & " ms. Average: " & Round($time_diff_c / $ticks, 4) & " ms." & @CRLF & @CRLF)
    close2()
EndFunc

Func Close2()
    _GDIPlus_BitmapDispose($Bitmap)
    _GDIPlus_GraphicsDispose($GDI_Buffer)
    _GDIPlus_GraphicsDispose ($hGraphic)
    _GDIPlus_Shutdown ()
EndFunc

Func close()
    _WinAPI_ReleaseDC($hGUI, $ScreenDc)
    _GDIPlus_GraphicsDispose($hBackbuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
EndFunc   ;==>close

My results on Dell Latitude D830 (Vista x32):

BitBlt Runtime: 18269.56 ms. Average: 7.7909 ms.
   Classic Runtime: 20401.94 ms. Average: 8.7002 ms.
   
   Diff: 2132.3756 ms | 11.67%

Seems to be approx. 10% faster!

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Another point to note is that recursion is generally an operation that sacrifices speed in the name of clarity and simplicity. Frequently if efficiency is the concern then you turn the recursion into iteration. This is the heart of the idea of dynamic programming.

From the code I see, this isn't terribly relevant, but topic's name begged me to mention this.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...