BlitzCoder Essentials
•
Home Page
•
About BlitzCoder
•
Contributors
•
Terms of Use
•
Email Us
Main Areas
•
BlitzCoder Chat
•
Discussions
•
Articles/Tutorials
•
Code Database
•
Link Database
•
Showcase Area
•
Worklogs
•
Competitions
Special Areas
•
Undocumented
Other Blitz Sites
•
Blitz Basic Home
•
Blitz Showcase
•
BlitzPlay Library
Forum Login
Username:
Password:
•
Register Now!
BlitzCoder Code Archives Page
Main Codes Page
"Benchmark Collection"
, by thechange
An elaborate collection of benchmarks purely to demonstrate Blitz' strong and weak sides as well as generic behavior.
Code
;======================================================================================================================; ; The following is a collection of various benchmarks that displays exactly how fast Blitz is (whichever version ; you're running). It also displays which quirks to be found and what anomalies to expect when and where. ; The people over on BlitzCoder have advised me to merge all benchmarks into one file, so you'll have to cut and paste ; each benchmark segment from this file to be able to test it. ; Here's a summary of what you can find in the collection: ; ; Template ; FPS Idle Time ; Loops ; Structures ; Storage ; Screen Operations ; Screen Layers ; Realtime Rotation ; Tiles Light/Heavy ; Plain Text (di,db) ; Line (m,a) ; Plot (lockb) ; Cls (rect) ; Gosub (fn) ; Power (m,a) ; Bitshifting (m,a) ; Capping 1 (if,math) ; Capping 2 (if,math) ; Not Equal ; Local First (glob) ; Object Comparison (!=,<>) ; Object Iteration ; Global.. Local.. Normal ; Object Access ; Sar vs Div ; Mod (m,a) ; ; It's very hard to create accurate benchmarks that actually return correct results. ; Even the most legit benchies depend purely on hardware (and drivers). ; And it often occurs that benchmarks give *different* results on different machines (For example: Intel, AMD). ; So it's near impossible to create an accurate benchmark (to demonstrate Blitz' speed) that gives the same results ; on every system. ; ; To start simple here's a template I use/used for most benchmark comparisons between 2 methods. ; ;======================================================================================================================; ;= TEMPLATE Graphics 300 , 400 , 0 , 2 SeedRnd MilliSecs () SetBuffer FrontBuffer () Delay 100 FlushKeys Const Cycles% = 10^6 Write "Bench One: " : Print Bench1 () Write "Bench Two: " : Print Bench2 () WaitKey End Function Bench1 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles Next Return MilliSecs () - Start End Function Function Bench2 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles Next Return MilliSecs () - Start End Function ; Next, a benchmark to show you how fast your computer can do nothing :P ; ;======================================================================================================================; ;= FPS Idle Time Graphics 640 , 480 , 16 , 2 SetBuffer BackBuffer () Repeat If MilliSecs () > LastTime + 999 FPS = Frames Frames = 0 LastTime = MilliSecs () Else Frames = Frames + 1 End If Text 0 , 0 , "FPS: " + FPS Flip False Cls Until KeyHit ( 1 ) End ; Here you'll find various techniques for looping. ; And it's actually a close match between most of them. ; Just remember not to use maths or MOD to cap a value (use IF instead). ; However, if the value is way out of range, MOD will be faster than using a loop instead. ; Remember to turn off debug, otherwise MOD will seem holy, instead of evil >:P ; ;======================================================================================================================; ;= LOOPS Graphics 300 , 300 , -1 , 2 Const Cycles% = 10^7 ; Set to higher powers (e.g. 10^8) for more accurate readings (and longer waiting) Print "-Started- (numCycles=" + Cycles + ")" Write "While loop without clipping: " : Print bWhileNoClip() Write "Repeat loop with clipping: " : Print bRepeatClip() Write "Repeat loop without clipping: " : Print bRepeatNoClip() Write "For loop with IF: " : Print bForIf() Write "Forever loop with NOT different: " : Print bForeverNotDifferent() Write "While loop with clipping: " : Print bWhileClip() Write "Forever loop with NOT equal: " : Print bForeverNotEqual() Write "For loop with calculation: " : Print bForCalc() Write "For loop with MOD: " : Print bForMod() Print "-Ended-" WaitKey End Function bForCalc() Local Angle% = 0 Local Increment% = 1 Local Iterator% Local EndTime% Local StartTime% = MilliSecs() For Iterator = 0 To Cycles Angle = Angle + Increment + ( Angle < 0 ) * Angle - ( Angle > 358 ) * Angle Next EndTime = MilliSecs() Return ( EndTime - StartTime ) End Function Function bForMod() Local Angle% = 0 Local Increment% = 1 Local Iterator% Local EndTime% Local StartTime% = MilliSecs() For Iterator = 0 To Cycles Angle = ( 360 + Angle ) Mod 360 Next EndTime = MilliSecs() Return ( EndTime - StartTime ) End Function Function bForIf() Local Angle% = 0 Local Increment% = 1 Local Iterator% Local EndTime% Local StartTime% = MilliSecs() For Iterator = 0 To Cycles Angle = Angle + Increment If Angle < 0 Then Angle = Angle + 360 If Angle > 359 Then Angle = Angle - 360 Next EndTime = MilliSecs() Return ( EndTime - StartTime ) End Function Function bRepeatClip() Local Angle% = 0 Local Increment% = 1 Local Iterator% Local EndTime% Local StartTime% = MilliSecs() Iterator = 0 Repeat Angle = Angle + Increment If Angle < 0 Then Angle = Angle + 360 If Angle > 359 Then Angle = Angle - 360 Iterator = Iterator + 1 Until Iterator = Cycles+1 EndTime = MilliSecs() Return ( EndTime - StartTime ) End Function Function bRepeatNoClip() Local Angle% = 0 Local Increment% = 1 Local Iterator% Local EndTime% Local StartTime% = MilliSecs() Iterator = -1 Repeat Iterator = Iterator + 1 Angle = Angle + Increment If Angle < 0 Then Angle = Angle + 360 If Angle > 359 Then Angle = Angle - 360 Until Iterator = Cycles EndTime = MilliSecs() Return ( EndTime - StartTime ) End Function Function bWhileClip() Local Angle% = 0 Local Increment% = 1 Local Iterator% Local EndTime% Local StartTime% = MilliSecs() Iterator = 0 While Not Iterator = Cycles Angle = Angle + Increment If Angle < 0 Then Angle = Angle + 360 If Angle > 359 Then Angle = Angle - 360 Iterator = Iterator + 1 Wend EndTime = MilliSecs() Return ( EndTime - StartTime ) End Function Function bWhileNoClip() Local Angle% = 0 Local Increment% = 1 Local Iterator% Local EndTime% Local StartTime% = MilliSecs() Iterator = -1 While Not Iterator = (Cycles-1) Iterator = Iterator + 1 Angle = Angle + Increment If Angle < 0 Then Angle = Angle + 360 If Angle > 359 Then Angle = Angle - 360 Wend EndTime = MilliSecs() Return ( EndTime - StartTime ) End Function Function bForeverNotDifferent() Local Angle% = 0 Local Increment% = 1 Local Iterator% Local EndTime% Local StartTime% = MilliSecs() Iterator = -1 Repeat Iterator = Iterator + 1 If Not ( Iterator <> Cycles ) Then Exit Angle = Angle + Increment If Angle < 0 Then Angle = Angle + 360 If Angle > 359 Then Angle = Angle - 360 Forever EndTime = MilliSecs() Return ( EndTime - StartTime ) End Function Function bForeverNotEqual() Local Angle% = 0 Local Increment% = 1 Local Iterator% Local EndTime% Local StartTime% = MilliSecs() Iterator = -1 Repeat Iterator = Iterator + 1 If Not ( Not Iterator = Cycles ) Then Exit Angle = Angle + Increment If Angle < 0 Then Angle = Angle + 360 If Angle > 359 Then Angle = Angle - 360 Forever EndTime = MilliSecs() Return ( EndTime - StartTime ) End Function ; It is said that Blitz internally converts Select statements to IF statements. ; Which would explain why the code below gives close results. ; ;======================================================================================================================; ;= STRUCTURES Graphics 400 , 400 , 0 , 2 Const Cycles% = 10^8 Write "SELECT (short) : " : Print BenchSELECT3 () Write "SELECT with DEFAULT : " : Print BenchSELECT2 () Write "SELECT without DEFAULT : " : Print BenchSELECT1 () Write "IF with ELSE without ELSEIF: " : Print BenchIF3 () Write "IF without ELSE without ELSEIF: " : Print BenchIF1 () Write "IF with ELSE with ELSEIF: " : Print BenchIF2 () Write "IF (short) : " : Print BenchIF4 () WaitKey End Function BenchSELECT1 () Local Start% Local Iterator% Local Remember% Start = MilliSecs () For Iterator = 0 To Cycles Select Iterator Case 0 Remember = Iterator Case 1 Remember = Iterator Case 2 Remember = Iterator Case 3 Remember = Iterator Case 4 Remember = Iterator Case 5 Remember = Iterator Case 6 Remember = Iterator Case 7 Remember = Iterator Case 8 Remember = Iterator Case 9 Remember = Iterator End Select Next Return MilliSecs () - Start End Function Function BenchSELECT2 () Local Start% Local Iterator% Local Remember% Start = MilliSecs () For Iterator = 0 To Cycles Select Iterator Case 0 Remember = Iterator Case 1 Remember = Iterator Case 2 Remember = Iterator Case 3 Remember = Iterator Case 4 Remember = Iterator Case 5 Remember = Iterator Case 6 Remember = Iterator Case 7 Remember = Iterator Case 8 Remember = Iterator Case 9 Remember = Iterator Default Remember = -1 End Select Next Return MilliSecs () - Start End Function Function BenchSELECT3 () Local Start% Local Iterator% Local Remember% Start = MilliSecs () For Iterator = 0 To Cycles Select Iterator Case 0,1,2,3,4,5,6,7,8,9 Remember = Iterator Default Remember = -1 End Select Next Return MilliSecs () - Start End Function Function BenchIF1 () Local Start% Local Iterator% Local Remember% Start = MilliSecs () For Iterator = 0 To Cycles If Iterator = 0 Remember = Iterator If Iterator = 1 Remember = Iterator If Iterator = 2 Remember = Iterator If Iterator = 3 Remember = Iterator If Iterator = 4 Remember = Iterator If Iterator = 5 Remember = Iterator If Iterator = 6 Remember = Iterator If Iterator = 7 Remember = Iterator If Iterator = 8 Remember = Iterator If Iterator = 9 Remember = Iterator Next Return MilliSecs () - Start End Function Function BenchIF2 () Local Start% Local Iterator% Local Remember% Start = MilliSecs () For Iterator = 0 To Cycles If Iterator = 0 Remember = Iterator ElseIf Iterator = 1 Remember = Iterator ElseIf Iterator = 2 Then Remember = Iterator ElseIf Iterator = 3 Then Remember = Iterator ElseIf Iterator = 4 Then Remember = Iterator ElseIf Iterator = 5 Then Remember = Iterator ElseIf Iterator = 6 Then Remember = Iterator ElseIf Iterator = 7 Then Remember = Iterator ElseIf Iterator = 8 Then Remember = Iterator ElseIf Iterator = 9 Then Remember = Iterator Else Remember = -1 EndIf Next Return MilliSecs () - Start End Function Function BenchIF3 () Local Start% Local Iterator% Local Remember% Start = MilliSecs () For Iterator = 0 To Cycles If Iterator = 0 Then Remember = Iterator Else If Iterator = 1 Then Remember = Iterator Else If Iterator = 2 Then Remember = Iterator Else If Iterator = 3 Then Remember = Iterator Else If Iterator = 4 Then Remember = Iterator Else If Iterator = 5 Then Remember = Iterator Else If Iterator = 6 Then Remember = Iterator Else If Iterator = 7 Then Remember = Iterator Else If Iterator = 8 Then Remember = Iterator Else If Iterator = 9 Then Remember = Iterator Else Remember = -1 EndIf EndIf EndIf EndIf EndIf EndIf EndIf EndIf EndIf EndIf Next Return MilliSecs () - Start End Function Function BenchIF4 () Local Start% Local Iterator% Local Remember% Start = MilliSecs () For Iterator = 0 To Cycles If Iterator >= 0 If Iterator <= 9 Remember = Iterator Else Remember = -1 EndIf Next Return MilliSecs () - Start End Function ; Here's a generic storage benchmark for reading and writing integers in various ways. ; ;======================================================================================================================; ;= STORAGE Graphics 640 , 480 , 0 , 2 Const Cycles = 10^8 ;------------------------------------------------------------------------------; Function BenchPixel () LockBuffer FrontBuffer () Start = MilliSecs () For Iterator = 0 To Cycles x = ReadPixel ( 0 , 0 ) x = Process ( x ) WritePixelFast 0 , 0 , x Next End = MilliSecs () - Start UnlockBuffer FrontBuffer () Return End End Function Function BenchBank () Bank = CreateBank ( 4 ) Start = MilliSecs () For Iterator = 0 To Cycles x = PeekInt ( Bank , 0 ) x = Process ( x ) PokeInt Bank , 0 , x Next End = MilliSecs () - Start FreeBank Bank Return End End Function Global GlobalBlitzArray[ 0 ] Function BenchGlobalBlitzArray () ;<-- External ;--> GlobalBlitzArray[ 0 ] Start = MilliSecs () For Iterator = 0 To Cycles x = GlobalBlitzArray[ 0 ] x = Process ( x ) GlobalBlitzArray[ 0 ] = x Next End = MilliSecs () - Start Return End End Function Function BenchLocalBlitzArray () Local LocalBlitzArray[ 0 ] Start = MilliSecs () For Iterator = 0 To Cycles x = LocalBlitzArray[ 0 ] x = Process ( x ) LocalBlitzArray[ 0 ] = x Next End = MilliSecs () - Start Return End End Function Dim GlobalArray( 0 ) Function BenchGlobalArray () ;<-- External ;--> GlobalArray( 0 ) Start = MilliSecs () For Iterator = 0 To Cycles x = GlobalArray( 0 ) x = Process ( x ) GlobalArray( 0 ) = x Next End = MilliSecs () - Start Return End End Function Type GlobalObjectBlitzArrayType Field BlitzArray[ 0 ] End Type Global GlobalObjectBlitzArray.GlobalObjectBlitzArrayType Function BenchGlobalObjectBlitzArray () ;<-- External ;--> GlobalObjectBlitzArray GlobalObjectBlitzArray = New GlobalObjectBlitzArrayType Start = MilliSecs () For Iterator = 0 To Cycles x = GlobalObjectBlitzArray\BlitzArray[ 0 ] x = Process ( x ) GlobalObjectBlitzArray\BlitzArray[ 0 ] = x Next End = MilliSecs () - Start Delete GlobalObjectBlitzArray Return End End Function Type LocalObjectBlitzArrayType Field BlitzArray[ 0 ] End Type Function BenchLocalObjectBlitzArray () Local LocalObjectBlitzArray.LocalObjectBlitzArrayType LocalObjectBlitzArray = New LocalObjectBlitzArrayType Start = MilliSecs () For Iterator = 0 To Cycles x = LocalObjectBlitzArray\BlitzArray[ 0 ] x = Process ( x ) LocalObjectBlitzArray\BlitzArray[ 0 ] = x Next End = MilliSecs () - Start Delete LocalObjectBlitzArray Return End End Function Type GlobalObjectVariableType Field Variable% End Type Global GlobalObjectVariable.GlobalObjectVariableType Function BenchGlobalObjectVariable () ;<-- External ;--> GlobalObjectVariable GlobalObjectVariable = New GlobalObjectVariableType Start = MilliSecs () For Iterator = 0 To Cycles x = GlobalObjectVariable\Variable x = Process ( x ) GlobalObjectVariable\Variable = x Next End = MilliSecs () - Start Delete GlobalObjectVariable Return End End Function Type LocalObjectVariableType Field Variable% End Type Function BenchLocalObjectVariable () Local LocalObjectVariable.LocalObjectVariableType LocalObjectVariable = New LocalObjectVariableType Start = MilliSecs () For Iterator = 0 To Cycles x = LocalObjectVariable\Variable x = Process ( x ) LocalObjectVariable\Variable = x Next End = MilliSecs () - Start Delete LocalObjectVariable Return End End Function Global GlobalFunctionVariable% Function BenchGlobalFunctionVariable () ;<-- External ;--> GlobalFunctionVariable Start = MilliSecs () For Iterator = 0 To Cycles x = READ_GlobalFunctionVariable () x = Process ( x ) WRITE_GlobalFunctionVariable ( x ) Next End = MilliSecs () - Start Return End End Function Function READ_GlobalFunctionVariable% () Return ( GlobalFunctionVariable ) End Function Function WRITE_GlobalFunctionVariable ( Variable% ) GlobalFunctionVariable = ( Variable ) End Function Function BenchLocalFunctionVariable () Local LocalFunctionVariable% Start = MilliSecs () For Iterator = 0 To Cycles x = READ_LocalFunctionVariable ( LocalFunctionVariable ) x = Process ( x ) LocalFunctionVariable = WRITE_LocalFunctionVariable ( x ) ; Caution: Blitz limitation Next End = MilliSecs () - Start Return End End Function Function READ_LocalFunctionVariable% ( Variable% ) Return ( Variable ) End Function Function WRITE_LocalFunctionVariable% ( Variable% ) Return ( Variable ) End Function Global GlobalVariable% Function BenchGlobalVariable () ;<-- External ;--> GlobalVariable Start = MilliSecs () For Iterator = 0 To Cycles x = GlobalVariable x = Process ( x ) GlobalVariable = x Next End = MilliSecs () - Start Return End End Function Function BenchLocalVariable () Local LocalVariable% Start = MilliSecs () For Iterator = 0 To Cycles x = LocalVariable x = Process ( x ) LocalVariable = x Next End = MilliSecs () - Start Return End End Function Function BenchShell () Start = MilliSecs () For Iterator = 0 To Cycles x = Process ( x ) Next End = MilliSecs () - Start Return End End Function Function Process% ( Variable% ) Return ( Variable + 1 ) End Function ;------------------------------------------------------------------------------; PrintText " Read | Write | Dist. | Object | Type | Result (ms)" PrintText "------------|------------|--------|--------|-------------|-------------" PrintText " ReadPixel | WritePixel | | No | FrontBuffer | \" PrintText "too slow" ;PrintText BenchPixel () PrintText " PeekInt | PokeInt | Local | No | Bank | \" PrintText BenchBank () PrintText " Assignment | Assignment | Global | No | BlitzArray | \" PrintText BenchGlobalBlitzArray () PrintText " Assignment | Assignment | Local | No | BlitzArray | \" PrintText BenchLocalBlitzArray () PrintText " Assignment | Assignment | Global | No | Array | \" PrintText BenchGlobalArray () PrintText " Assignment | Assignment | Global | Yes | BlitzArray | \" PrintText BenchGlobalObjectBlitzArray () PrintText " Assignment | Assignment | Local | Yes | BlitzArray | \" PrintText BenchLocalObjectBlitzArray () PrintText " Assignment | Assignment | Global | Yes | Variable | \" PrintText BenchGlobalObjectVariable () PrintText " Assignment | Assignment | Local | Yes | Variable | \" PrintText BenchLocalObjectVariable () PrintText " Function | Function | Global | No | Variable | \" PrintText BenchGlobalFunctionVariable () PrintText " Function | Function | Local | No | Variable | \" PrintText BenchLocalFunctionVariable () PrintText " Assignment | Assignment | Global | No | Variable | \" PrintText BenchGlobalVariable () PrintText " Assignment | Assignment | Local | No | Variable | \" PrintText BenchLocalVariable () PrintText " None | None | | No | N/A | \" PrintText BenchShell () PrintText "------------|------------|--------|--------|-------------|-------------" WaitKey End Function PrintText ( Text$ ) If Right ( Text , 1 ) = "\" Write Left ( Text , Len ( Text ) - 1 ) DebugLog Left ( Text , Len ( Text ) - 1 ) Else Print Text DebugLog Text EndIf End Function ; Writing pixels to the screen manually has proved to be very slow in the history of Blitz. ; BlitzPlus however, sets Blitz' pixel manipulation speed in a new light. ; There are some things to care of that can cause a severe slowdown. ; If the buffer isn't locked, using Plot will be faster than any WritePixel* command. ; But if the buffer -is- locked, WPF wins hands down. ; ;======================================================================================================================; ;= SCREEN OPERATIONS Const Screens = 3 Graphics 640 , 480 , 0 , 2 Pixel = CreateImage ( 1 , 1 ) SetBuffer ImageBuffer ( Pixel ) Color 128 , 128 , 255 Plot 0 , 0 SetBuffer FrontBuffer () ClsColor 64 , 64 , 128 Cls SX = GraphicsWidth () SY = GraphicsHeight () X = 0 Y = 0 Screen = 0 Start = MilliSecs () Repeat DrawImage Pixel , X , Y X = X + 1 If X = SX X = 0 Y = Y + 1 If Y = SY Y = 0 Screen = Screen + 1 Cls End If End If Until Screen = Screens r_di = MilliSecs () - Start X = 0 Y = 0 Screen = 0 Start = MilliSecs () Repeat DrawBlock Pixel , X , Y X = X + 1 If X = SX X = 0 Y = Y + 1 If Y = SY Y = 0 Screen = Screen + 1 Cls End If End If Until Screen = Screens r_db = MilliSecs () - Start X = 0 Y = 0 Screen = 0 Color 255 , 255 , 255 Start = MilliSecs () Repeat Rect X , Y , 1 , 1 X = X + 1 If X = SX X = 0 Y = Y + 1 If Y = SY Y = 0 Screen = Screen + 1 Cls End If End If Until Screen = Screens r_rct = MilliSecs () - Start X = 0 Y = 0 Screen = 0 Color 255 , 255 , 255 Start = MilliSecs () Repeat Oval X , Y , 1 , 1 X = X + 1 If X = SX X = 0 Y = Y + 1 If Y = SY Y = 0 Screen = Screen + 1 Cls End If End If Until Screen = Screens r_ovl = MilliSecs () - Start X = 0 Y = 0 Screen = 0 Color 255 , 255 , 255 Start = MilliSecs () Repeat Plot X , Y X = X + 1 If X = SX X = 0 Y = Y + 1 If Y = SY Y = 0 Screen = Screen + 1 Cls End If End If Until Screen = Screens r_plt = MilliSecs () - Start X = 0 Y = 0 Screen = 0 Start = MilliSecs () Repeat Color 255 , 255 , 255 Plot X , Y X = X + 1 If X = SX X = 0 Y = Y + 1 If Y = SY Y = 0 Screen = Screen + 1 Cls End If End If Until Screen = Screens r_plc = MilliSecs () - Start r_wpn$ = "too slow" Goto skip_wpn X = 0 Y = 0 Screen = 0 Start = MilliSecs () Repeat WritePixel X , Y , 16777215 X = X + 1 If X = SX X = 0 Y = Y + 1 If Y = SY Y = 0 Screen = Screen + 1 Cls End If End If Until Screen = Screens r_wpn = MilliSecs () - Start .skip_wpn X = 0 Y = 0 Screen = 0 LockBuffer FrontBuffer () Start = MilliSecs () Repeat WritePixel X , Y , 16777215 X = X + 1 If X = SX X = 0 Y = Y + 1 If Y = SY Y = 0 Screen = Screen + 1 UnlockBuffer FrontBuffer () Cls LockBuffer FrontBuffer () End If End If Until Screen = Screens r_wp = MilliSecs () - Start UnlockBuffer FrontBuffer () X = 0 Y = 0 Screen = 0 LockBuffer FrontBuffer () Start = MilliSecs () Repeat WritePixelFast X , Y , 16777215 X = X + 1 If X = SX X = 0 Y = Y + 1 If Y = SY Y = 0 Screen = Screen + 1 UnlockBuffer FrontBuffer () Cls LockBuffer FrontBuffer () End If End If Until Screen = Screens r_wpf = MilliSecs () - Start UnlockBuffer FrontBuffer () Print "Technique Locked buffer Extras Result (ms) " Print "---------------- -------------- -------- ------------ " Print " DrawImage No - "+r_di Print " DrawBlock No - "+r_db Print " Rect No - "+r_rct Print " Oval No - "+r_ovl Print " Plot No - "+r_plt Print " Plot No Color "+r_plc Print " WritePixel No - "+r_wpn Print " WritePixel Yes - "+r_wp Print " WritePixelFast Yes - "+r_wpf WaitKey End ; Here's a benchmark to see the speed of multiple screen-sized images being drawn over one another. ; ;======================================================================================================================; ;= SCREEN LAYERS ; Adjust the number of layers to your liking Const MaxLayers = 20 Graphics 1024 , 768 Print "Total video memory: " + TotalVidMem () Print "Available video memory before: " + AvailVidMem () Dim layers( MaxLayers ) Print "Allocating " + MaxLayers + " layers of " + GraphicsWidth () + "x" + GraphicsHeight () + "x" + GraphicsDepth () For layer = 1 To MaxLayers layers( layer ) = CreateImage ( GraphicsWidth () , GraphicsHeight () ) Next Print "Available video memory after: " + AvailVidMem () Print "Video memory in use: " + ( TotalVidMem () - AvailVidMem () ) Print Print "Press any key to benchmark" FlushKeys WaitKey SetBuffer BackBuffer () Repeat For layer = 1 To MaxLayers DrawImage layers( layer ) , 0 , 0 Next If MilliSecs()>lasttime+1000 fps=frames frames=0 Color 255,255,255 lasttime=MilliSecs() End If frames=frames+1 Text 0,0,"FPS:"+fps Flip False Cls Until KeyHit ( 1 ) End ; Realtime rotation, a routine that's hard to optimize and even harder to 'algorithmitize'. ; Below you'll find various routines taken from various sources written by various people. ; And each code has its own formatting, so it's one big mess ahead :P ; The conclusion is that 2D Real-time Software Rendering is still too slow on a P4-1G9(RDR) with GF3Ti500. ; Using Blitz3D for example, is a good alternative, as that's hardware rendering instead. ; ;======================================================================================================================= ;= REALTIME ROTATION Graphics 640 , 480 , 0 , 2 SetBuffer BackBuffer () Color 0 , 0 , 0 ClsColor 0 , 0 , 0 TFormFilter True AutoMidHandle False Cls Local CosTable#[ 720 ] Local SinTable#[ 720 ] For i = 0 To 720 CosTable[ i ] = Cos ( i ) SinTable[ i ] = Sin ( i ) Next Bitmap = CreateImage ( 128 , 128 ) MidHandle Bitmap ; MaskImage Bitmap , 255 , 0 , 255 RotatedBitmap = CopyImage ( Bitmap ) SetBuffer ImageBuffer ( Bitmap ) Color 255 , 0 , 255 Rect 0 , 0 , 100 , 100 ; Color 63 , 63 , 127 ; Rect 30 , 30 , 40 , 40 , True SetBuffer BackBuffer () time = MilliSecs () Repeat Cls angle = angle + 1 ;-- Remark one (at a time) of the sections below to test its speed. ;Time taken in ms. (:) Step precision ;w = windowed , f = fullscreen ; w400 : 1 ;--v ; tmp = CopyImage ( Bitmap ) ; rotate2pass tmp , Angle , CosTable , SinTable ; DrawImage tmp , GraphicsWidth () / 2 , GraphicsHeight () / 2 ; FreeImage tmp ;--^ ; w500 : 1 ;--v ; tmp = CopyImage ( Bitmap ) ; rotate3pass tmp , Angle , CosTable , SinTable ; DrawImage tmp , GraphicsWidth () / 2 , GraphicsHeight () / 2 ; FreeImage tmp ;--^ ; f336 : 10 ; f3399 : 1 ; w5400 : 1 ;--v ; DrawImage2D4 Bitmap , GraphicsWidth () / 2 , GraphicsHeight () / 2 , Angle ;--^ ; f333 : 10 ; f3403 : 1 ; w5400 : 1 ;--v ; DrawImage2D3 Bitmap , GraphicsWidth () / 2 , GraphicsHeight () / 2 , Angle ;--^ ; f406 : 10 ; f4155 : 1 ; w6600 : 1 ;--v ; DrawImage2D1 Bitmap , GraphicsWidth () / 2 , GraphicsHeight () / 2 , -Angle ;--^ ; w10K+ : 1 ;--v ; DrawImageR Bitmap , GraphicsWidth () / 2 , GraphicsHeight () / 2 , Angle , CosTable , SinTable ;--^ ; f756 : 10 ; f7610 : 1 ; w10K+ : 1 ;--v ; DrawImage2D2 Bitmap , GraphicsWidth () / 2 , GraphicsHeight () / 2 , -Angle , 0 , 0 , 255 , 0 , 255 ;--^ ; f2497 : 10 ; f9999+ : 1 ; w10K+ : 1 ;--v ; FreeImage RotatedBitmap ; RotatedBitmap = CopyImage ( Bitmap ) ; RotateImage RotatedBitmap , Angle ; DrawImage RotatedBitmap , GraphicsWidth () / 2 , GraphicsHeight () / 2 ;--^ ; f9999+ : 10 ; f9999+ : 1 ; w10K+ : 1 ;--v ; RotatedBitmap = RotateImage2D1 ( Bitmap , -Angle , RotatedBitmap , 0 , 0 , 255 , 0 , 255 ) ; DrawImage RotatedBitmap , GraphicsWidth () / 2 , GraphicsHeight () / 2 ;--^ Flip False Until KeyHit ( 1 ) Or angle = 360 time = MilliSecs () - time Color 255 , 255 , 255 Print "Duration: " + time + "ms" WaitKey End Function DrawImage2D4 ( ImageHandle , PosX , PosY , Angle# ) SizeX = ImageWidth(ImageHandle) SizeY = ImageHeight(ImageHandle) HSizeX = SizeX/2 HSizeY = SizeY/2 SinA# = Sin(Angle) CosA# = Cos(Angle) uX# = 0 uY# = 0 Source = ImageBuffer(ImageHandle) Dest = BackBuffer() LockBuffer Source LockBuffer Dest For X = 1 To SizeX vX = X - HSizeX uX = (PosX+HSizeX) - SinA*vX uY = (PosY+HSizeY) + CosA*vX For Y = 1 To SizeY vY = Y - HSizeY CopyPixelFast X,Y,Source,uX+CosA*vY,uY+SinA*vY,Dest Next Next UnlockBuffer Dest UnlockBuffer Source End Function Function DrawImage2D3 ( ImageHandle , PosX , PosY , Angle# , SizeX = False , SizeY = False ) If ( Not SizeX ) Or ( Not SizeY ) SizeX = ImageWidth(ImageHandle)/2 SizeY = ImageHeight(ImageHandle)/2 EndIf SinA# = Sin(Angle) CosA# = Cos(Angle) uX# = 0 uY# = 0 vX# = 0 vY# = 0 LockBuffer BackBuffer() LockBuffer ImageBuffer(ImageHandle) Width = ImageWidth(ImageHandle) Height = ImageHeight(ImageHandle) For X = 1 To Width vX = X - SizeX uX = (PosX+SizeX) - SinA*vX uY = (PosY+SizeY) + CosA*vX For Y = 1 To Height vY = Y - SizeY CopyPixelFast X,Y,ImageBuffer(ImageHandle),uX+CosA*vY,uY+SinA*vY Next Next UnlockBuffer BackBuffer() UnlockBuffer ImageBuffer(ImageHandle) End Function Function drawImage2D1(image,mX#,mY#,angle#,hX#=0,hY#=0) Local u1#,u2#,vX#,vY# ;-- If Not hX hX = ImageWidth(image) / 2 hY = ImageHeight(image) / 2 EndIf LockBuffer BackBuffer() LockBuffer ImageBuffer(image) For x = 1 To ImageWidth(image) vX = x - hX u1 = (mx+hx) + Cos(angle) * vx:u2 =(my+hy) -Sin(angle) * vx For y = 1 To ImageHeight(Image) vY = y - hY CopyPixelFast x,y,ImageBuffer(image),( (u1+Sin(angle) * vy) ) ,( (u2+Cos(angle)*vy)) Next Next UnlockBuffer BackBuffer() UnlockBuffer ImageBuffer(image) ;-- End Function Function drawImage2D2(image,mX#,mY#,angle#,hX#=0,hY#=0,mR=0,mG=0,mB=0) Local u1#,u2#,vX#,vY# ;-- If Not hX hX = ImageWidth(image) / 2 hY = ImageHeight(image) / 2 EndIf LockBuffer BackBuffer() LockBuffer ImageBuffer(image) For x = 0 To ImageWidth(image)-1 vX = x - hX u1 = (mx+hx) + Cos(angle) * vx:u2 =(my+hy) -Sin(angle) * vx For y = 0 To ImageHeight(Image)-1 vY = y - hY rgb = ReadPixelFast(x,y,ImageBuffer(image)) If Not ( (((rgb Shr 16) And 255) = mR) And (((rgb Shr 8) And 255) = mG) And ((rgb And 255) = mB) ) CopyPixelFast x,y,ImageBuffer(image),( (u1+Sin(angle) * vy) ) ,( (u2+Cos(angle)*vy)) EndIf Next Next UnlockBuffer BackBuffer() UnlockBuffer ImageBuffer(image) ;-- End Function Function RotateImage2D1(image,angle#,imgTo=0,hX#=0,hY#=0,mR=0,mG=0,mB=0) Local u1#,u2#,vX#,vY# ;Local out ;-- If Not hX hX = ImageWidth(image) / 2 hY = ImageHeight(image) / 2 EndIf If Not imgTo imgTo = CreateImage(ImageWidth(image),ImageHeight(image)) SetBuffer ImageBuffer(imgTo) Color mR,mG,mB Rect 0,0,ImageWidth(imgTo),ImageHeight(imgTo) SetBuffer BackBuffer() LockBuffer ImageBuffer(imgTo) LockBuffer ImageBuffer(image) For x# = 1 To ImageWidth(image) vX# = x - hX u1# = (mx+hx) + Cos(angle) * vx:u2 =(hy) -Sin(angle) * vx For y = 1 To ImageHeight(Image) vY# = y - hY rgb = ReadPixelFast(x,y,ImageBuffer(image)) dX# = ( (u1+Sin(angle) * vy) ) dY# = ( (u2+Cos(angle)*vy)) ;angle = angle - 0.0001 If Not ( (((rgb Shr 16) And 255) = mR) And (((rgb Shr 8) And 255) = mG) And ((rgb And 255) = mB) ) CopyPixel x,y,ImageBuffer(image),dX ,dY,ImageBuffer(imgTo) CopyPixel x,y,ImageBuffer(image),dX+1,dY,ImageBuffer(imgTo) EndIf Next Next UnlockBuffer ImageBuffer(image) UnlockBuffer ImageBuffer(imgTo) For x = 2 To ImageWidth(imgTo) - 2 ;Not the fastest way. For y = 2 To ImageHeight(imgTo) - 2 Rgb = ReadPixel(x,Y,ImageBuffer(imgTo)) If Not ( (((rgb Shr 16) And 255) = mR) And (((rgb Shr 8) And 255) = mG) And ((rgb And 255) = mB) ) r=0 g=0 b=0 For dX = x - 1 To x+1 For dY = y - 1 To y+1 nRgb = ReadPixel(dX,dY,ImageBuffer(imgTo)) r = r + ((nRgb Shr 16) And 255) g = g + ((nRgb Shr 8) And 255) b = b + ((nRgb And 255)) Next Next r = r / 9 g = g / 9 b = b / 9 If r<0 r=0 If g<0 g=0 If b<0 b=0 If r>255 r=255 If g>255 g=255 If b>255 b = 255 WritePixel x,y,$ff000000 Or ((r And 255) Shl 16) Or ((g And 255) Shl 8) Or (b And 255),ImageBuffer(imgTo) EndIf Next Next ;UnlockBuffer ImageBuffer(imgTo) Return imgTo ;-- End Function Function drawImageR(image,mX#,mY#,angle#,ct#[720],st#[720]) Local xI#,yI#,u1#,u2# ;-- For x = 1 To ImageWidth(image) u1 = ct[angle] * x u2 = -st[angle] * x For y = 1 To ImageHeight(Image) CopyRect x,y,1,1,(u1+st[angle] * y)+mX,(u2+ct[angle]*y)+mY,ImageBuffer(image),BackBuffer() Next Next ;-- End Function Function rotate2pass(img,angle#,CosTable#[720],SinTable#[720]) ;precalc a few values gb=GraphicsBuffer() buf=ImageBuffer(img) width=ImageWidth(img) height=ImageHeight(img) xhandle=ImageXHandle(img) yHandle=ImageYHandle(img) ;This function requires a spare image to work with. spare=CreateImage(width,height) HandleImage spare,xhandle,yhandle sparebuf=ImageBuffer(spare) ;vertical skew operation factor#=SinTable[angle] sfactor#=1/CosTable[angle] For y=0 To height srcx#=(y-yhandle)*factor srcy#=(y-yhandle)/sfactor+yhandle desx#=xhandle desy#=y+yhandle CopyRect srcx,srcy,width,1,desx,desy,buf,sparebuf Next ;clear image SetBuffer buf Cls SetBuffer gb ;horizontal skew operation factor#=SinTable[angle]/CosTable[angle] sfactor#=CosTable[angle] For x=0 To width srcx#=(x-xhandle)/sfactor+xhandle srcy#=0-(x-xhandle)*factor desx#=x+xhandle desy#=yhandle CopyRect srcx,srcy,1,height,desx,desy,sparebuf,buf Next FreeImage spare End Function Function rotate3pass(img,angle,CosTable#[720],SinTable#[720]) ;precalc a few values gb=GraphicsBuffer() buf=ImageBuffer(img) width=ImageWidth(img) height=ImageHeight(img) xhandle=ImageXHandle(img) yHandle=ImageYHandle(img) ;decide whether to flip image If(CosTable[angle]>0) flip180=1 Else flip180=-1 angle=angle+180 EndIf ;This function requires a spare image to work with. spare=CopyImage(img) sparebuf=ImageBuffer(spare) ;clear image SetBuffer buf Cls SetBuffer gb ;vertical skew operation factor#=(1-CosTable[angle])/SinTable[angle] sfactor#=1 For y=0 To height srcx=(y-yhandle)*factor srcy=(y-yhandle)/sfactor+yhandle desx=xhandle desy=y+yhandle CopyRect srcx,srcy,width,1,desx,desy,sparebuf,buf Next ;clear spare image SetBuffer sparebuf Cls SetBuffer gb ;horizontal skew operation factor#=flip180*SinTable[angle] sfactor#=flip180 For x=0 To width srcx=(x-xhandle)/sfactor+xhandle srcy=0-(x-xhandle)*factor desx=x+xhandle desy=yhandle CopyRect srcx,srcy,1,height,desx,desy,buf,sparebuf Next ;clear image SetBuffer buf Cls SetBuffer gb ;vertical skew operation factor#=(1-CosTable[angle])/SinTable[angle] sfactor#=flip180 For y=0 To height srcx=(y-yhandle)*factor srcy=(y-yhandle)/sfactor+yhandle desx=xhandle desy=y+yhandle CopyRect srcx,srcy,width,1,desx,desy,sparebuf,buf Next FreeImage spare End Function ; A light tiles benchmark using large tiles. ; Use FASTEST technique for speed. ; Use COMPACT technique for size. ; ;======================================================================================================================; ;= TILES LIGHT ; TILES Phase 9 - Stripped Tile Engine ; ; 27 Feb 2002 ;-[ Definition ]-------------------------------------------------------------------------------------------------1-2-0-- Const KeySpace% = 57 Const KeyEscape% = 1 Const KeyCursorUp% = 200 Const KeyCursorDown% = 208 Const KeyCursorLeft% = 203 Const KeyCursorRight% = 205 Const KeyControlRight% = 157 ;--> Const ScreenSizeX% = 800 Const ScreenSizeY% = 600 Const ColorDepthBits% = 16 ;--> Const TileCount% = 8 Const TileSizeX% = 32 Const TileSizeY% = 32 Const TileMapSizeX% = 1600 Const TileMapSizeY% = 1200 ;-[ Initialization ]---------------------------------------------------------------------------------------------1-2-0-- Graphics3D( ScreenSizeX , ScreenSizeY , ColorDepthBits , 0 ) SeedRnd MilliSecs() Local Counter% = 0 Local CounterX% = 0 Local CounterY% = 0 Global TileData = CreateImage( TileSizeX , TileSizeY , TileCount ) Local ColorNumber% = 0 SetBuffer( ImageBuffer( TileData , 0 ) ) ;Totally Transparent Tile SetBuffer( ImageBuffer( TileData , 1 ) ) For CounterX = -TileSizeX To TileSizeX ColorNumber = 256 / ( TileSizeX * 2 ) * ( CounterX + TileSizeX ) Color( ColorNumber , 00 , 00 ) Line( CounterX , 0 , CounterX + TileSizeX - 1 , TileSizeY - 1 ) Next SetBuffer( ImageBuffer( TileData , 2 ) ) For CounterX = -TileSizeX To TileSizeX ColorNumber = 256 / ( TileSizeX * 2 ) * ( CounterX + TileSizeX ) Color( 00 , ColorNumber , 00 ) Line( CounterX , 0 , CounterX + TileSizeX - 1 , TileSizeY - 1 ) Next SetBuffer( ImageBuffer( TileData , 3 ) ) For CounterX = -TileSizeX To TileSizeX ColorNumber = 256 / ( TileSizeX * 2 ) * ( CounterX + TileSizeX ) Color( 00 , 00 , ColorNumber ) Line( CounterX , 0 , CounterX + TileSizeX - 1 , TileSizeY - 1 ) Next SetBuffer( ImageBuffer( TileData , 4 ) ) For CounterX = -TileSizeX To TileSizeX ColorNumber = 256 / ( TileSizeX * 2 ) * ( CounterX + TileSizeX ) Color( ColorNumber , ColorNumber , 00 ) Line( CounterX , 0 , CounterX + TileSizeX - 1 , TileSizeY - 1 ) Next SetBuffer( ImageBuffer( TileData , 5 ) ) For CounterX = -TileSizeX To TileSizeX ColorNumber = 256 / ( TileSizeX * 2 ) * ( CounterX + TileSizeX ) Color( 00 , ColorNumber , ColorNumber ) Line( CounterX , 0 , CounterX + TileSizeX - 1 , TileSizeY - 1 ) Next SetBuffer( ImageBuffer( TileData , 6 ) ) For CounterX = -TileSizeX To TileSizeX ColorNumber = 256 / ( TileSizeX * 2 ) * ( CounterX + TileSizeX ) Color( ColorNumber , 00 , ColorNumber ) Line( CounterX , 0 , CounterX + TileSizeX - 1 , TileSizeY - 1 ) Next SetBuffer( ImageBuffer( TileData , 7 ) ) For CounterX = -TileSizeX To TileSizeX ColorNumber = 256 / ( TileSizeX * 2 ) * ( CounterX + TileSizeX ) Color( ColorNumber , ColorNumber , ColorNumber ) Line( CounterX , 0 , CounterX + TileSizeX - 1 , TileSizeY - 1 ) Next Dim TileMap( TileMapSizeX - 1 , TileMapSizeY - 1 ) For CounterY = 1 To TileMapSizeY - 2 For CounterX = 1 To TileMapSizeX - 2 Seek% = Rnd( TileCount% * 3 ) If ( Seek < TileCount% ) Tile% = Seek Else Tile% = 0 TileMap( CounterX , CounterY ) = Tile% Next Next For CounterY = 0 To TileMapSizeY - 1 ; Borderlines not really required TileMap( 0 , CounterY ) = 1 TileMap( TileMapSizeX - 1 , CounterY ) = 1 Next For CounterX = 0 To TileMapSizeX - 1 TileMap( CounterX , 0 ) = 1 TileMap( CounterX , TileMapSizeY - 1 ) = 1 Next SetBuffer( BackBuffer() ) ;Local GameTimer = CreateTimer( 100 ) Local Frames% = 0 Local LastTime% = MilliSecs() Local FPS% = 0 Global TechToggle% = -1 Global AimX# = 0 Global AimY# = 0 Global CursorY% = 0 Global CursorX% = 0 Global IncY# = 0 ; vertical speed Global IncX# = 0 ; horizontal speed Global IncFactor# = 0.25 ; acceleration increment and deceleration decrement Global IncMax% = 16 ; maximum speed ;*** ; Global BeginScreenX% ; Global BeginScreenY% ; Global EndScreenX% ; Global EndScreenY% ; Global BeginTileX% ; Global BeginTileY% ; Global EndTileX% ; Global EndTileY% ;*** ;-[ Main ]-------------------------------------------------------------------------------------------------------1-2-0-- Repeat ;Frames = WaitTimer( GameTimer ) ;For Counter = 1 To Frames Done = Update() ; If ( Done ) Exit ;Next Cls Render() ; * Benchmark * Frames = Frames + 1 If ( MilliSecs() > LastTime + 999 ) FPS = Frames Frames = 0 LastTime = MilliSecs() EndIf Color( 063 , 127 , 191 ) Text( 0 , 0 , "FPS: " + FPS + " TECH: " + TechToggle ) Flip( 0 ) Until Done End ;-[ Sub ]--------------------------------------------------------------------------------------------------------1-2-0-- Function Update() Local Done = KeyDown( KeyEscape ) If ( KeyDown( KeyCursorUp ) ) CursorY = -1 If ( KeyDown( KeyCursorDown ) ) CursorY = 1 If ( KeyDown( KeyCursorLeft ) ) CursorX = -1 If ( KeyDown( KeyCursorRight ) ) CursorX = 1 If ( KeyHit( KeySpace ) ) TechToggle = -TechToggle ;--> If ( CursorY = 0 ) If ( Not IncY = 0 ) IncY = IncY - ( IncY / Abs( IncY ) ) * IncFactor Else IncY = IncY + CursorY * IncFactor If ( Abs( IncY ) > IncMax ) IncY = IncMax * ( IncY / Abs( IncY ) ) CursorY = 0 EndIf If ( CursorX = 0 ) If ( Not IncX = 0 ) IncX = IncX - ( IncX / Abs( IncX ) ) * IncFactor Else IncX = IncX + CursorX * IncFactor If ( Abs( IncX ) > IncMax ) IncX = IncMax * ( IncX / Abs( IncX ) ) CursorX = 0 EndIf If ( Not IncY = 0 ) AimY = AimY + IncY If ( Not IncX = 0 ) AimX = AimX + IncX ;--> Return Done End Function ;--> Function Render() If ( TechToggle = 1 ) ; * COMPACT * For CounterY = ( ( AimY - ScreenSizeY / 2 ) / TileSizeY ) To ( ( AimY + ScreenSizeY / 2 ) / TileSizeY ) For CounterX = ( ( AimX - ScreenSizeX / 2 ) / TileSizeX ) To ( ( AimX + ScreenSizeX / 2 ) / TileSizeX ) If ( CounterX >= 0 ) And ( CounterX < TileMapSizeX ) And ( CounterY >= 0 ) And ( CounterY < TileMapSizeY ) DrawImage( TileData , CounterX * TileSizeX - ( AimX - ScreenSizeX / 2 ) , CounterY * TileSizeY - ( AimY - ScreenSizeY / 2 ) , TileMap( CounterX , CounterY ) ) EndIf Next Next Else ; * FAST * Local BeginScreenX% = AimX - ScreenSizeX / 2 Local BeginScreenY% = AimY - ScreenSizeY / 2 Local EndScreenX% = AimX + ScreenSizeX / 2 Local EndScreenY% = AimY + ScreenSizeY / 2 Local BeginTileX% = BeginScreenX / TileSizeX Local BeginTileY% = BeginScreenY / TileSizeY Local EndTileX% = EndScreenX / TileSizeX Local EndTileY% = EndScreenY / TileSizeY If ( BeginTileX < 0 ) BeginTileX = 0 If ( BeginTileY < 0 ) BeginTileY = 0 If ( BeginTileX >= TileMapSizeX ) BeginTileX = TileMapSizeX - 1 If ( BeginTileY >= TileMapSizeY ) BeginTileY = TileMapSizeY - 1 If ( EndTileX < 0 ) EndTileX = 0 If ( EndTileY < 0 ) EndTileY = 0 If ( EndTileX >= TileMapSizeX ) EndTileX = TileMapSizeX - 1 If ( EndTileY >= TileMapSizeY ) EndTileY = TileMapSizeY - 1 For CounterY = BeginTileY To EndTileY For CounterX = BeginTileX To EndTileX DrawImage( TileData , CounterX * TileSizeX - BeginScreenX , CounterY * TileSizeY - BeginScreenY , TileMap( CounterX , CounterY ) ) Next Next EndIf End Function ;--> ; A heavy tiles benchmark using small tiles. ; Pretty hard to benchmark on a computer with a fast CPU ( 1G9+). ; Try benchmarking on a slower computer ( 600M-). ; 1st place: OLD. ; 2nd place: NEW. ; 3rd place: NEW OPTIMIZED. ; 4th place: NEW COMPACT. ; ;======================================================================================================================; ;= TILES HEAVY ; TILES Phase 9 - Tile Engine Benchmark ; ; 26 Feb 2002 Global DebugMsgY% = 0 Function DebugMsg( Message$ ) Local DebugMsgFont = LoadFont( "Blitz" ) SetBuffer( FrontBuffer() ) SetFont( DebugMsgFont ) Color( 127 , 255 , 191 ) Locate( 0 , DebugMsgY ) Print( Message ) DebugMsgY = DebugMsgY + FontHeight() End Function ; ;-[ Definition ]-------------------------------------------------------------------------------------------------1-2-0-- ; Const KeySpace% = 57 Const KeyEscape% = 1 Const KeyCursorUp% = 200 Const KeyCursorDown% = 208 Const KeyCursorLeft% = 203 Const KeyCursorRight% = 205 Const KeyControlRight% = 157 ; ;--> ; Const ScreenSizeX% = 800 Const ScreenSizeY% = 600 Const ColorDepthBits% = 16 ; ;--> ; Const TileCount% = 4 Const TileSizeX% = 4 Const TileSizeY% = 4 Const TileMapSizeX% = 1024 Const TileMapSizeY% = 1024 ; ;-[ Initialization ]---------------------------------------------------------------------------------------------1-2-0-- ; Graphics( ScreenSizeX , ScreenSizeY , ColorDepthBits , 0 ) ; SeedRnd MilliSecs() ; Local CounterX% = 0 Local CounterY% = 0 ; DebugMsg( "Generating Tiles..." ) ; Global TileData = CreateImage( TileSizeX , TileSizeY , TileCount ) ; Tile 0 is completely transparent SetBuffer( ImageBuffer( TileData , 1 ) ) For CounterX = -TileSizeX To TileSizeX Color( 256 - 256 / ( TileSizeX * 2 ) * ( CounterX + TileSizeX ) , 0 , 0 ) Line( CounterX , TileSizeY - 1 , CounterX + TileSizeX - 1 , 0 ) Next Color( 063 , 000 , 000 ) Rect( -1 , -1 , TileSizeX + 1 , TileSizeY + 1 , 0 ) SetBuffer( ImageBuffer( TileData , 2 ) ) For CounterX = -TileSizeX To TileSizeX Color( 0 , 256 - 256 / ( TileSizeX * 2 ) * ( CounterX + TileSizeX ) , 0 ) Line( CounterX , TileSizeY - 1 , CounterX + TileSizeX - 1 , 0 ) Next Color( 000 , 063 , 000 ) Rect( -1 , -1 , TileSizeX + 1 , TileSizeY + 1 , 0 ) SetBuffer( ImageBuffer( TileData , 3 ) ) For CounterX = -TileSizeX To TileSizeX Color( 0 , 0 , 256 - 256 / ( TileSizeX * 2 ) * ( CounterX + TileSizeX ) ) Line( CounterX , TileSizeY - 1 , CounterX + TileSizeX - 1 , 0 ) Next Color( 000 , 000 , 063 ) Rect( -1 , -1 , TileSizeX + 1 , TileSizeY + 1 , 0 ) ; DebugMsg( "Generating Map..." ) ; Dim TileMap( TileMapSizeX - 1 , TileMapSizeY - 1 ) Local RandomSeek% = 0 Local RandomTile% = 0 For CounterY = 1 To TileMapSizeY - 2 For CounterX = 1 To TileMapSizeX - 2 RandomSeek = Rnd( TileCount * 3 ) If ( RandomSeek < TileCount ) RandomTile = RandomSeek Else RandomTile = 0 TileMap( CounterX , CounterY ) = RandomTile Next Next For CounterY = 0 To TileMapSizeY - 1 TileMap( 0 , CounterY ) = 1 TileMap( TileMapSizeX - 1 , CounterY ) = 1 Next For CounterX = 0 To TileMapSizeX - 1 TileMap( CounterX , 0 ) = 1 TileMap( CounterX , TileMapSizeY - 1 ) = 1 Next ; SetBuffer( BackBuffer() ) ; Local Frames% = 0 Global Mode% = 0 ; Local LastTime% = MilliSecs() Local FrameCount% = 0 Local FrameRate% = 0 ; Number of frames per second (Hz) Local FrameTime% = 0 ; Number of milliseconds per frame ; Global AimX# = TileMapSizeX / 2 * TileSizeX Global AimY# = TileMapSizeY / 2 * TileSizeY ; Global CursorY% = 0 Global CursorX% = 0 ; Global IncY# = 0 ; vertical speed Global IncX# = 0 ; horizontal speed Global IncFactor# = 0.5 ; acceleration increment and deceleration decrement Global IncMax% = 16 ; maximum speed ; ;-[ Main ]-------------------------------------------------------------------------------------------------------1-2-0-- ; Repeat ; Done = Update() Cls() Render() ; FrameCount = FrameCount + 1 If ( MilliSecs() > LastTime + 999 ) FrameRate = FrameCount FrameCount = 0 FrameTime = 1000 / FrameRate LastTime = MilliSecs() EndIf Color( 127 , 191 , 255 ) Text( 0 , 0 , "FPS: " + FrameRate + " TPF: " + FrameTime + " MOD: " + Mode ) ; Flip( False ) ; Until ( Done ) ; End() ; ;-[ Sub ]--------------------------------------------------------------------------------------------------------1-2-0-- ; Function Update() ; Local Done = KeyDown( KeyEscape ) ; If ( KeyDown( KeyCursorUp ) ) CursorY = -1 If ( KeyDown( KeyCursorDown ) ) CursorY = 1 If ( KeyDown( KeyCursorLeft ) ) CursorX = -1 If ( KeyDown( KeyCursorRight ) ) CursorX = 1 If ( KeyHit ( KeySpace ) ) Mode = ( Mode + 1 ) Mod 4 ; ;--> ; If ( CursorY = 0 ) If ( Not IncY = 0 ) IncY = IncY - ( IncY / Abs( IncY ) ) * IncFactor Else IncY = IncY + CursorY * IncFactor If ( Abs( IncY ) > IncMax ) IncY = IncMax * ( IncY / Abs( IncY ) ) CursorY = 0 EndIf ; If ( CursorX = 0 ) If ( Not IncX = 0 ) IncX = IncX - ( IncX / Abs( IncX ) ) * IncFactor Else IncX = IncX + CursorX * IncFactor If ( Abs( IncX ) > IncMax ) IncX = IncMax * ( IncX / Abs( IncX ) ) CursorX = 0 EndIf ; If ( Not IncY = 0 ) AimY = AimY + IncY If ( Not IncX = 0 ) AimX = AimX + IncX ; ;--> ; Return Done ; End Function ; ;--> ; Function Render() ; Select Mode ; Case 0 ;** NEW COMPACT ** For CounterY = ( ( ( ( AimY - ScreenSizeY / 2 ) / TileSizeY ) >= 0 ) * ( ( AimY - ScreenSizeY / 2 ) / TileSizeY ) ) To ( ( ( ( AimY + ScreenSizeY / 2 ) / TileSizeY ) < TileMapSizeY ) * ( ( AimY + ScreenSizeY / 2 ) / TileSizeY ) + ( ( ( ( ( ( AimY + ScreenSizeY / 2 ) / TileSizeY ) < TileMapSizeY ) * ( ( AimY + ScreenSizeY / 2 ) / TileSizeY ) ) = 0 ) And ( ( ( AimY + ScreenSizeY / 2 ) / TileSizeY ) > 0 ) ) * ( TileMapSizeY - 1 ) ) For CounterX = ( ( ( ( AimX - ScreenSizeX / 2 ) / TileSizeX ) >= 0 ) * ( ( AimX - ScreenSizeX / 2 ) / TileSizeX ) ) To ( ( ( ( AimX + ScreenSizeX / 2 ) / TileSizeX ) < TileMapSizeX ) * ( ( AimX + ScreenSizeX / 2 ) / TileSizeX ) + ( ( ( ( ( ( AimX + ScreenSizeX / 2 ) / TileSizeX ) < TileMapSizeX ) * ( ( AimX + ScreenSizeX / 2 ) / TileSizeX ) ) = 0 ) And ( ( ( AimX + ScreenSizeX / 2 ) / TileSizeX ) > 0 ) ) * ( TileMapSizeX - 1 ) ) DrawImage ( TileData , CounterX * TileSizeX - ( AimX - ScreenSizeX / 2 ) , CounterY * TileSizeY - ( AimY - ScreenSizeY / 2 ) , TileMap( CounterX , CounterY ) ) Next Next ; Case 1 ;** NEW OPTIMIZED ** BeginScreenX% = AimX - ScreenSizeX / 2 BeginScreenY% = AimY - ScreenSizeY / 2 EndScreenX% = AimX + ScreenSizeX / 2 EndScreenY% = AimY + ScreenSizeY / 2 BeginTileX% = BeginScreenX / TileSizeX BeginTileY% = BeginScreenY / TileSizeY EndTileX% = EndScreenX / TileSizeX EndTileY% = EndScreenY / TileSizeY ; For CounterY = ( ( BeginTileY >= 0 ) * BeginTileY ) To ( ( EndTileY < TileMapSizeY ) * EndTileY + ( ( ( ( EndTileY < TileMapSizeY ) * EndTileY ) = 0 ) And ( EndTileY > 0 ) ) * ( TileMapSizeY - 1 ) ) For CounterX = ( ( BeginTileX >= 0 ) * BeginTileX ) To ( ( EndTileX < TileMapSizeX ) * EndTileX + ( ( ( ( EndTileX < TileMapSizeX ) * EndTileX ) = 0 ) And ( EndTileX > 0 ) ) * ( TileMapSizeX - 1 ) ) DrawImage( TileData , CounterX * TileSizeX - BeginScreenX , CounterY * TileSizeY - BeginScreenY , TileMap( CounterX , CounterY ) ) Next Next ; Case 2 ;** NEW ** BeginScreenX% = AimX - ScreenSizeX / 2 BeginScreenY% = AimY - ScreenSizeY / 2 EndScreenX% = AimX + ScreenSizeX / 2 EndScreenY% = AimY + ScreenSizeY / 2 BeginTileX% = BeginScreenX / TileSizeX BeginTileY% = BeginScreenY / TileSizeY EndTileX% = EndScreenX / TileSizeX EndTileY% = EndScreenY / TileSizeY ; BeginTileX = ( BeginTileX >= 0 ) * BeginTileX BeginTileY = ( BeginTileY >= 0 ) * BeginTileY EndTileX = ( EndTileX < TileMapSizeX ) * EndTileX + ( ( ( ( EndTileX < TileMapSizeX ) * EndTileX ) = 0 ) And ( EndTileX > 0 ) ) * ( TileMapSizeX - 1 ) EndTileY = ( EndTileY < TileMapSizeY ) * EndTileY + ( ( ( ( EndTileY < TileMapSizeY ) * EndTileY ) = 0 ) And ( EndTileY > 0 ) ) * ( TileMapSizeY - 1 ) ; For CounterY = BeginTileY To EndTileY For CounterX = BeginTileX To EndTileX DrawImage( TileData , CounterX * TileSizeX - BeginScreenX , CounterY * TileSizeY - BeginScreenY , TileMap( CounterX , CounterY ) ) Next Next ; Case 3 ;** OLD ** BeginScreenX% = AimX - ScreenSizeX / 2 BeginScreenY% = AimY - ScreenSizeY / 2 EndScreenX% = AimX + ScreenSizeX / 2 EndScreenY% = AimY + ScreenSizeY / 2 BeginTileX% = BeginScreenX / TileSizeX BeginTileY% = BeginScreenY / TileSizeY EndTileX% = EndScreenX / TileSizeX EndTileY% = EndScreenY / TileSizeY ; If ( BeginTileX < 0 ) BeginTileX = 0 If ( BeginTileY < 0 ) BeginTileY = 0 If ( BeginTileX >= TileMapSizeX ) BeginTileX = TileMapSizeX - 1 If ( BeginTileY >= TileMapSizeY ) BeginTileY = TileMapSizeY - 1 If ( EndTileX < 0 ) EndTileX = 0 If ( EndTileY < 0 ) EndTileY = 0 If ( EndTileX >= TileMapSizeX ) EndTileX = TileMapSizeX - 1 If ( EndTileY >= TileMapSizeY ) EndTileY = TileMapSizeY - 1 ; For CounterY = BeginTileY To EndTileY For CounterX = BeginTileX To EndTileX DrawImage( TileData , CounterX * TileSizeX - BeginScreenX , CounterY * TileSizeY - BeginScreenY , TileMap( CounterX , CounterY ) ) Next Next ; End Select ; End Function ; ;--> ; This benchmark compares individual calls to Text, DrawImage and DrawBlock. ; However, using temporary images for each line of a message system in combination with DrawImage is faster than Text. ; A game called Mini Gravity Well uses this same technique, which you can find here: ; ; http://www.blitzcoder.com/cgi-bin/ubb-cgi/postdisplay.cgi?forum=Forum3&topic=000841 ; ; Look for a file called "Advanced Message System.BB" to find what you're looking for. ; ; In a regular or most simplistic scenario, Text wins, but it's a close match. ; ;======================================================================================================================; ;= PLAIN TEXT Const Cycles% = 1000 Graphics 640 , 480 , 0 , 0 SetBuffer FrontBuffer () ClsColor 63 , 63 , 63 Color 255 , 255 , 255 Delay 500 Local Counter% Local Result1% Local Result2% Local Result3% Local BigFont BigFont = LoadFont ( "Blitz" , 255 ) SetFont BigFont Global TextImage = CreateImage ( FontWidth () , FontHeight () , 128 ) For Counter = 0 To 127 SetBuffer ImageBuffer ( TextImage , Counter ) Text 0 , 0 , Chr ( Counter + 32 ) Next SetBuffer FrontBuffer () Cls:Cls SeedRnd MilliSecs() Result1 = Bench1 () : Cls SeedRnd MilliSecs() Result2 = Bench2 () : Cls SeedRnd MilliSecs() Result3 = Bench3 () : Cls SeedRnd MilliSecs() FreeImage TextImage FreeFont BigFont Print "Text : " + Result1 Print "DrawImage: " + Result2 Print "DrawBlock: " + Result3 WaitKey End Function Bench1 () Local Counter% Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles For Counter = 0 To 127 Text 0 , 0 , Chr ( Counter + 32 ) Next Next Return MilliSecs () - Start End Function Function Bench2 () Local Counter% Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles For Counter = 0 To 127 DrawImage TextImage , 0 , 0 , Counter Next Next Return MilliSecs () - Start End Function Function Bench3 () Local Counter% Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles For Counter = 0 To 127 DrawBlock TextImage , 0 , 0 , Counter Next Next Return MilliSecs () - Start End Function ; This benchmark proves that Blitz' native Line function is already as fast as can be (as it should be :P). ; Writing pixels manually will not cut it. However, ; the power of this function lies within the ability to draw lines when the buffer is locked. ;======================================================================================================================; ;= LINE ; (Line function by Antony) Function dLine(x1#,y1#,x2#,y2#,rgb) Local steps,xI# x2 = x2-x1 y2 = y2-y1 If Abs(x2)>Abs(y2) steps = Abs(x2) Else steps = Abs(y2) xI = x2 / steps y2 = Y2 / steps For x2 = 1 To steps WritePixelFast x1,y1,rgb x1=x1+xI:y1=y1+y2 Next End Function sx=640 sy=480 Graphics sx,sy,0,2 SetBuffer FrontBuffer() cycles=10000 i=0 start=MilliSecs() Color 0,0,255 For i=1 To cycles Line 0,0,sx-1,sy-1 Next Print MilliSecs()-start start=MilliSecs () LockBuffer FrontBuffer() For i=1 To cycles dline 0,0,sx-1,sy-1,255 Next UnlockBuffer FrontBuffer() Print MilliSecs()-start WaitKey End ; Locking buffers is a speed killer. ; This benchmark demonstrates. ; ;======================================================================================================================; ;= PLOT Graphics 1280 , 1024 , 32 sx = GraphicsWidth()/4-1 sy = GraphicsHeight()/4-1 SeedRnd MilliSecs () SetBuffer FrontBuffer () Delay 1000 Print "PLOT" start = MilliSecs() For x = 0 To sx For y = 0 To sy Color 255 , 255 , 255 Plot x , y Next Next plot_time = MilliSecs()-start Print "WPF" start = MilliSecs() For x = 0 To sx For y = 0 To sy LockBuffer WritePixelFast x , y , 0 UnlockBuffer Next Next wpf_time = MilliSecs()-start Print "Plot: " + plot_time Print "WPF: " + wpf_time WaitKey End ; Using a call to Rect to wipe the screen? ; Cls is still slightly faster. ; ;======================================================================================================================; ;= CLS Const sx = 300 Const sy = 400 Graphics sx , sy , 0 , 2 Const Cycles% = 10^5 SetBuffer FrontBuffer () ClsColor 128,64,64 : b1 = Bench1 () Color 64,64,128 : b2 = Bench2 () Print "Bench One: " + b1 Print "Bench Two: " + b2 WaitKey End Function Bench1 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles Cls Next Color 255,255,255 Return MilliSecs () - Start End Function Function Bench2 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles Rect 0,0,sx,sy,True Next Color 255,255,255 Return MilliSecs () - Start End Function ; The good'ol Function vs Gosub battle. ; Gosub still wins, but the difference is small to medium. ; So in the end it's just what you prefer :) ; ;======================================================================================================================; ;= GOSUB Graphics 300 , 400 , 0 , 2 SeedRnd MilliSecs () SetBuffer FrontBuffer () Const cycles% = 10^7 Local x% = 0 Local i% Local start% Local FN_V1 Local FN_V2 Goto START .BM_GOSUB start = MilliSecs() For i = 1 To cycles FN_V1 = x FN_V2 = 1 Gosub FN_ADD Next Print "Gosub: " + (MilliSecs()-start) Return .BM_FUNCTION start = MilliSecs() For i = 1 To cycles add x , 1 Next Print "Function: " + (MilliSecs()-start) Return .START Gosub BM_GOSUB Gosub BM_FUNCTION WaitKey End Function add( src , val ) Return Sqr(-Sgn(val) * src^2) / val^(3*Abs(val-((val+1)*(src/3 - (1-Abs(val-src)) ))/2)) End Function .FN_ADD FN_RETURN = Sqr(-Sgn(FN_V2) * FN_V1^2) / FN_V2^(3*Abs(FN_V2-((FN_V2+1)*(FN_V1/3 - (1-Abs(FN_V2-FN_V1)) ))/2)) Return ; As for miraculous benchmarks; ; Did you know that TIMES itself is at least 10 times faster than doing a POWER? ; ;======================================================================================================================; ;= POWER Graphics 400,300,0,2 Const Cycles% = 10^7 Write "Bench One: " : Print Bench1 () Write "Bench Two: " : Print Bench2 () WaitKey End Function Bench2 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles X = X * X Next Return MilliSecs () - Start End Function Function Bench1 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles X = X ^ 2 Next Return MilliSecs () - Start End Function ; Bitshifting in general should be faster than multiplication in theory. ; However I found that on Intel CPUs the reversed was true (using Blitz). ; Perhaps results are different on AMD CPUs. ; ;======================================================================================================================; ;= BITSHIFTING Graphics 300 , 400 , 0 , 2 SetBuffer FrontBuffer () WaitKey Global Shift = 31 Global Multi = 2147483648 Const Cycles% = 10^9 Write "Bench Two (*) : " : Print Bench2 () Write "Bench One (SHL): " : Print Bench1 () WaitKey End Function Bench1 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles Result% = ( Int Iterator ) Shl ( Int Shift ) Next Return MilliSecs () - Start End Function Function Bench2 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles Result% = ( Int Iterator ) * ( Int Multi ) Next Return MilliSecs () - Start End Function ; Capping a value using IF has always been faster than using maths. ; Here's an elaborate comparison. ; ;======================================================================================================================; ;= CAPPING 1 Graphics 300 , 400 , 0 , 2 Const Cycles% = 10^7 Write "Bench One: " : Print Bench1 () Write "Bench Two: " : Print Bench2 () WaitKey End Function Bench1 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles Num = Iterator - Cycles / 2 If Num < 0 Num = -Num Inverted = True End If Result = Num Mod Cycles If Inverted Result = -Result Inverted = False End If ; Print Result Next Return MilliSecs () - Start End Function Function Bench2 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles Num = Iterator - Cycles / 2 Inverted = ( Num > 0 ) * 2 - 1 If Num < 0 Then Num = -Num Result = ( Num Mod Cycles ) * Inverted ; Print Result Next Return MilliSecs () - Start End Function ; Another example of capping a value, but with more elegance. ; This shows that on fast CPUs the difference gets really small. ; (Yes, IF -should- win :P) ; ;======================================================================================================================; ;= CAPPING 2 Graphics 300 , 400 , -1 , 2 Const Cycles% = 10^8 Global Strafe# = 0.999 Global Angle# = 358.99 Write "Bench One: " : Print Bench1 () Write "Bench Two: " : Print Bench2 () WaitKey End Function Bench1 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles StrafeAngle% = Angle + ( Strafe / Abs ( Strafe ) * 90 ) Next Return MilliSecs () - Start End Function Function Bench2 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles If Strafe < 0 Then StrafeAngle% = Angle - 90 If Strafe > 0 Then StrafeAngle% = Angle + 90 Next Return MilliSecs () - Start End Function ; Comparing NotEqual with UnEqual seems futile, but behold. ; Testing with integers on an Intel CPU seems to give -different- results, however insignificant the results may be. ; For Floats, however, it seems to be the same (as it should be for either anyway). ; ;======================================================================================================================; ;= NOT EQUAL Graphics 200 , 400 , -1 , 2 SetBuffer FrontBuffer () Const Cycles% = 10^8 Global V1# = 0 ; Change to Integer% Global V2# = 1 ; for different result Write "Bench One: " : Print Bench1 () Write "Bench Two: " : Print Bench2 () WaitKey End Function Bench1 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles If V1 <> V2 EndIf Next Return MilliSecs () - Start End Function Function Bench2 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles If Not V1 = V2 EndIf Next Return MilliSecs () - Start End Function ; Use Global and Local wisely. ; As using a call to First in conjunction with Locals can be even slower than Globals in general. ; ; E.g. Global wins ; ; Global ptr ; Fn ptr\field ; ; Over Local ; ; Local ptr ; ptr = First type ;<- Benchmark's significant slowdown ; Fn ptr\field ; ; Additional copies of pointers/benchmarks were added for additional insurance. ; Below are more benchmarks to display how hard it is to get any constructive and accurate results. ; ;======================================================================================================================; ;= LOCAL FIRST Graphics 300 , 400 , 0 , 2 Type x Field a Field b Field c End Type Global a.x,b.x,c.x Local x.x For i=1 To 100 x=New x x\a=Rand(-2147483648,2147483647) x\b=Rand(-2147483648,2147483647) x\c=Rand(-2147483648,2147483647) Next a=First x b=First x c=First x Const Cycles% = 10^7 Write "Bench1: " : Print Bench1 () Write "Bench2: " : Print Bench2 () Write "Bench3: " : Print Bench3 () Write "Bench4: " : Print Bench4 () Write "Bench5: " : Print Bench5 () Write "Bench6: " : Print Bench6 () Write "Bench7: " : Print Bench7 () Write "Bench8: " : Print Bench8 () Write "Bench9: " : Print Bench9 () WaitKey End Function Bench1 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles x.x = First x out x\a out x\b out x\c Next Return MilliSecs () - Start End Function Function Bench2 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles y.x = First x out y\a out y\b out y\c Next Return MilliSecs () - Start End Function Function Bench3 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles z.x = First x out z\a out z\b out z\c Next Return MilliSecs () - Start End Function Function Bench4 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles out a\a out a\b out a\c Next Return MilliSecs () - Start End Function Function Bench5 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles out b\a out b\b out b\c Next Return MilliSecs () - Start End Function Function Bench6 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles out c\a out c\b out c\c Next Return MilliSecs () - Start End Function Function Bench7 () Local Start% Local Iterator% Local x.x = First x Start = MilliSecs () For Iterator = 0 To Cycles out x\a out x\b out x\c Next Return MilliSecs () - Start End Function Function Bench8 () Local Start% Local Iterator% Local y.x = First x Start = MilliSecs () For Iterator = 0 To Cycles out y\a out y\b out y\c Next Return MilliSecs () - Start End Function Function Bench9 () Local Start% Local Iterator% Local z.x = First x Start = MilliSecs () For Iterator = 0 To Cycles out z\a out z\b out z\c Next Return MilliSecs () - Start End Function Function OUT ( value ) dummy = value * value End Function ; (Not Pointer.Type = Null) vs ( Pointer.Type <> Null ) ; ...seems to be identical in speed. You be the judge :) ; ;======================================================================================================================; ;= OBJECT COMPARISON Graphics 300 , 400 , 0 , 2 Const Cycles% = 10^7 Global NewPointer.Collection = New Collection Function Existing2% ( Pointer.Collection ) Return ( Not Pointer = Null ) End Function Function Existing1% ( Pointer.Collection ) Return ( Pointer <> Null ) End Function Function Action% () Return Sin ( Rnd ( 360 ) ) End Function Write "Bench One: " : Print Bench1 () Write "Bench Two: " : Print Bench2 () WaitKey End Type Collection Field Contents% End Type Function Bench2 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles If Existing2 ( NewPointer ) Then Action Next Return MilliSecs () - Start End Function Function Bench1 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles If Existing1 ( NewPointer ) Then Action Next Return MilliSecs () - Start End Function ; (For Each Next) vs (Repeat After Until) ; ...seems to be identical in speed as well. ; You can move some parts of the code around to see some quirks pop-up (see below). ; ;======================================================================================================================; ;= OBJECT ITERATION Graphics 640 , 480 , 0 , 2 SeedRnd MilliSecs () Const z = 100 Const d = 128 Type x Field values[ z ] Field MANACLE# Field Romanoid$ End Type Global Array[ z * z ] Global y.x Function test1 () For i = 1 To z y = New x Next i = Rnd ( z ) t = MilliSecs () For y = Each x Color Rnd ( 255 ) , Rnd ( 255 ) , Rnd ( 255 ) Text 0 , 0 , " " For j = 1 To z y\values[ j ] = CreateImage ( d , d ) FreeImage y\values[ j ] Next Color Rnd ( 255 ) , Rnd ( 255 ) , Rnd ( 255 ) Text 0 , 0 , " " Next t = MilliSecs () - t Delete Each x Return t End Function Function test2 () For i = 1 To z y = New x Next i = Rnd ( z ) t = MilliSecs () y = First x Repeat Color Rnd ( 255 ) , Rnd ( 255 ) , Rnd ( 255 ) Text 0 , 0 , " " For j = 1 To z y\values[ j ] = CreateImage ( d , d ) FreeImage y\values[ j ] Next Color Rnd ( 255 ) , Rnd ( 255 ) , Rnd ( 255 ) Text 0 , 0 , " " y = After y Until y = Null t = MilliSecs () - t Delete Each x Return t End Function ;= Try swapping test1 with test2 to see the inconsistency t = test2 () Color 255,255,255 Print "1: " + t t = test1 () Color 255,255,255 Print "2: " + t WaitKey End ; Testing the creation of, reading and writing to and deletion of Global, Local and Normal pointers. ; (Where Normal means an on-the-fly Local variable) ; ; It is quite clear that either all are equal in speed or it's just another -highly- inaccurate benchmark :o) ; Move the NORMAL, GLOBAL and LOCAL parts around for some neckbreaking results. ; ;======================================================================================================================; ;= GLOBAL.. LOCAL.. NORMAL Graphics 640 , 480 , 0 , 2 SeedRnd MilliSecs () SetBuffer FrontBuffer () MilliSecs () Delay 100 Const Ccycles = 3333333 Type x Field m End Type Global Gx.x Print "Cycles: " + Ccycles dummy.x = New x dummy\m = Rand ( -2147483748 , 2147483747 ) Delete dummy Delay 1000 ;** NORMAL **; Print Write "Normal Create: " s = MilliSecs () Ncreate e = MilliSecs () Print (e - s) + "ms" Function Ncreate () For i = 1 To Ccycles Nx.x = New x Nx\m = i Next End Function Write "Normal Read: " s = MilliSecs () Nread e = MilliSecs () Print (e - s) + "ms" Function Nread () For Nx.x = Each x i = Nx\m Next End Function Write "Normal Write: " s = MilliSecs () Nwrite e = MilliSecs () Print (e - s) + "ms" Function Nwrite () For Nx.x = Each x Nx\m = i Next End Function Write "Normal Delete: " s = MilliSecs () Ndelete e = MilliSecs () Print (e - s) + "ms" Function Ndelete () For Nx.x = Each x Delete Nx Next End Function ;** GLOBAL **; Print Write "Global Create: " s = MilliSecs () Gcreate e = MilliSecs () Print (e - s) + "ms" Function Gcreate () For i = 1 To Ccycles Gx = New x Gx\m = i Next End Function Write "Global Read: " s = MilliSecs () Gread e = MilliSecs () Print (e - s) + "ms" Function Gread () For Gx = Each x i = Gx\m Next End Function Write "Global Write: " s = MilliSecs () Gwrite e = MilliSecs () Print (e - s) + "ms" Function Gwrite () For Gx = Each x Gx\m = i Next End Function Write "Global Delete: " s = MilliSecs () Gdelete e = MilliSecs () Print (e - s) + "ms" Function Gdelete () For Gx = Each x Delete Gx Next End Function ;** LOCAL **; Print Write " Local Create: " s = MilliSecs () Lcreate e = MilliSecs () Print (e - s) + "ms" Function Lcreate () Local Lx.x For i = 1 To Ccycles Lx = New x Lx\m = i Next End Function Write " Local Read: " s = MilliSecs () Lread e = MilliSecs () Print (e - s) + "ms" Function Lread () Local Lx.x For Lx = Each x i = Lx\m Next End Function Write " Local Write: " s = MilliSecs () Lwrite e = MilliSecs () Print (e - s) + "ms" Function Lwrite () Local Lx.x For Lx = Each x Lx\m = i Next End Function Write " Local Delete: " s = MilliSecs () Ldelete e = MilliSecs () Print (e - s) + "ms" Function Ldelete () Local Lx.x For Lx = Each x Delete Lx Next End Function ;** END **; Delete Each x WaitKey EndGraphics End ; Just another benchy which ain't funny. ; Testing accessing object contents using Global, Local and Normal pointers. ; Either all are equal in speed or it's another inaccurate benchmark. ; Hint: Remark the global dummy lines and Global will seem 8 times slower (!). ; ;======================================================================================================================; ; OBJECT ACCESS Graphics 640 , 480 , 0 , 2 SeedRnd MilliSecs () SetBuffer FrontBuffer () Const Citems = 3333333 Type x Field m End Type Global xx.x ; dummy Global Gx.x Global xy.x ; dummy2 Print "Creating " + Citems + " items" Local x.x For i = 1 To Citems x = New x Next Delay 500 dummy.x = New x dummy\m = Rand ( -2147483748 , 2147483647 ) Delete dummy Delay 500 ;** LOCAL **; Print Write " Local Read: " s = MilliSecs () Lread e = MilliSecs () Print (e - s) + "ms" Function Lread () Local Lx.x For Lx = Each x i = Lx\m Next End Function Write " Local Write: " s = MilliSecs () Lwrite e = MilliSecs () Print (e - s) + "ms" Function Lwrite () Local Lx.x For Lx = Each x Lx\m = i Next End Function ;** NORMAL **; Print Write "Normal Read: " s = MilliSecs () Nread e = MilliSecs () Print (e - s) + "ms" Function Nread () For Nx.x = Each x i = Nx\m Next End Function Write "Normal Write: " s = MilliSecs () Nwrite e = MilliSecs () Print (e - s) + "ms" Function Nwrite () For Nx.x = Each x Nx\m = i Next End Function ;** GLOBAL **; Print Write "Global Read: " s = MilliSecs () Gread e = MilliSecs () Print (e - s) + "ms" Function Gread () For Gx = Each x i = Gx\m Next End Function Write "Global Write: " s = MilliSecs () Gwrite e = MilliSecs () Print (e - s) + "ms" Function Gwrite () For Gx = Each x Gx\m = i Next End Function ;** END **; Print Print "Deleting " + Citems + " items" Delete Each x Print Print "Press any key" WaitKey EndGraphics End ; Here's a silly benchmark, comparing SAR 1 with DIV 2. ; Just too fast to compare in Blitz. ; ;======================================================================================================================; ;= SAR vs DIV Graphics 300 , 400 , 0 , 2 Const Cycles% = 10^9 SetBuffer FrontBuffer () Delay ( 1000 ) Write "Bench Two: " : Print Bench2 () ; When swapping the calls (Bench1, Bench2) Write "Bench One: " : Print Bench1 () ; one seems faster than the other WaitKey End Function Bench1 () Local Start% Local Iterator% Local Result% Start = MilliSecs () For Iterator = 0 To Cycles Result = Iterator/2/2/2/2/2/2/2/2/2/2 Next Return MilliSecs () - Start End Function Function Bench2 () Local Start% Local Iterator% Local Result% Start = MilliSecs () For Iterator = 0 To Cycles Result = Iterator Sar 1 Sar 1 Sar 1 Sar 1 Sar 1 Sar 1 Sar 1 Sar 1 Sar 1 Sar 1 Next Return MilliSecs () - Start End Function ; What's faster? ; Doing a MOD manually or automatically? ; On the computers I've tested it on it seemed either equal or random (as usual). ; See below and try swapping those 2 lines to display different results - which shouldn't happen :P ; ;======================================================================================================================; ; MOD Graphics 300 , 800 , 0 , 2 font = LoadFont ( "Arial" ) SetFont font Const Cycles% = 10^8 Write "Bench Two: " : Print Bench2 () ; Swapping these two lines Write "Bench One: " : Print Bench1 () ; will give different results WaitKey End Const Cap = 6 ; Range (0..Cap-1) Function Bench1 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles Num = Iterator - Cycles / 2 ; If Num < 0 ; Num = -Num ; Inverted = True ; End If Result = Num - Num / Cap * Cap ; If Inverted ; Result = -Result ; Inverted = False ; End If ;Print Result Next Return MilliSecs () - Start End Function Function Bench2 () Local Start% Local Iterator% Start = MilliSecs () For Iterator = 0 To Cycles Num = Iterator - Cycles / 2 Result = Num Mod Cap ;Print Result Next Return MilliSecs () - Start End Function ;======================================================================================================================; ; If you find any weird things, bugs or anything you think is noteworthy, lemme know: TheChange@yahoo.com ; ; Have fun :D ;======================================================================================================================;
Copyright(c) 2000-2004, BlitzCoder. All Rights Reserved.
Code software created by Krylar's Kreations