Here's a little benchmark using VBL sync and raster lines.
[Edit 1]Here's a little explanation (please forgive my bad english and shortcuts to simplify explanations).
You'll see on the screen a visual fx (circles going from left to right, like a starfield), and two lines. These two lines are showing visually how long is during our fx , using the display as time base. It's an old demomaker tip to have a clue on how much time a fx is taking without frame drop. A frame drop is occuring if the green line is going below the downside of the screen
The space between the two lines is the time taken by our code.To understand the general idea, you have to remember how CRT screens are working. A cathodic screen is a phosphorous surface, a material that emits light when receiving electrons. The monitor has an electron beam, that covers the whole screen, from from left to right, and from top to bottom. For a 60 imgs/secs, it does it 60 times/sec (easy, no?). It's what you see in display parameters (60Hz).
What this program does is to synchronize code on the beam's position. It starts code after the clearscreen and draws the first line. Then it computes and draws our sprites and draws the second line. Then you visually see how much time our FX has taken ! More computing, more sprites, and the second line will go down.
If it's going to the bottom, you'll encounter what we call a "frame drop": your display is no more sync at 60hz, but needs two frames, and is now at 30 fps... It gives an ugly visual slowdown that real demomakers hate !
If your screen is at 60Hz, that you have less than a screen between the two lines, the FX routine took less than 16 ms, and we have our 60 imgs/secs and the best fluidity!
Next effect : overscan

[Edit 2] Changed title to be more adequate to english users. (original title originated from a french thread)
[Edit 3] Cleanup and 4.60 fix
Code:
;*****************************************************************************
;* RasterLine and vertical blank (VBL) benchmark
;* Realtime visual benchmark. Press space to add "stars". The time is given
;* by the space between blue and green line.
;* By djes (djes@free.fr) 03/24/2009
;* Thanx to Stefan Moebius for VBL sync examples
;* Note : I do not check functions return values : I know it's bad!!!
;* 02/28/2012 : PB 4.60 fix
;*****************************************************************************
Structure D3DRaster_STATUS
InVBlank.l
ScanLine.l
EndStructure
Structure Pos
x.l
y.l
Speed.l
EndStructure
;*****************************************************************************
Define.D3DRaster_STATUS Raster
Define.IDirect3DDevice9 D3DDeviceInterface
Global NewList Stars.Pos()
;*****************************************************************************
;wait for the vblank to start - takes all the cpu
;attend le début de la synchro vbl
Procedure VBLWait()
Shared D3DDeviceInterface, Raster, Exit
Repeat
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Escape)
Exit=#True
EndIf
D3DDeviceInterface\GetRasterStatus(0, @Raster)
Until Raster\InVBlank=#True Or Exit
EndProcedure
;*****************************
;wait for the vblank to finish - takes all the cpu
;attend la fin de la synchro vbl
Procedure VBLEndWait()
Shared D3DDeviceInterface, Raster, Exit
Repeat
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Escape)
Exit=#True
EndIf
D3DDeviceInterface\GetRasterStatus(0, @Raster)
Until Raster\InVBlank=#False Or Exit
EndProcedure
;*****************************
;look for the Raster pos and draw a coloured line
;récupère la position du Raster et y affiche une ligne de la couleur indiquée
Procedure RasterLine(Color.l)
Shared Raster, D3DDeviceInterface
StartDrawing(ScreenOutput())
D3DDeviceInterface\GetRasterStatus(0, @Raster)
LineXY(0, Raster\ScanLine, 1023, Raster\ScanLine, Color)
StopDrawing()
EndProcedure
;**************************
Procedure CreateSprites()
CreateSprite(0, 64, 64)
StartDrawing(SpriteOutput(0))
Circle(32, 32, 31, RGB($FF, $FF, $FF))
StopDrawing()
EndProcedure
;************************
;Open screen and get the device - Ouvre l'écran et récupère le device
Procedure InitDisplay()
Shared D3DDeviceInterface
OpenScreen(1024, 768, 32, "", #PB_Screen_NoSynchronization, 60)
!extrn _PB_Screen_Direct3DDevice
!MOV dword EAX, [_PB_Screen_Direct3DDevice]
!MOV dword [v_D3DDeviceInterface],EAX
EndProcedure
;************************
;Check if the user has switched (and that we have lost focus) (ALT-TAB)
;Vérifie si l'utilisateur n'a pas changé d'appli (en nous faisant donc perdre le focus) (ALT-TAB)
Procedure FullScreenCheck()
;we're lowering our priority - on baisse notre priorité
SetPriorityClass_( GetCurrentProcess_(), #NORMAL_PRIORITY_CLASS)
SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_NORMAL)
ReleaseMouse(1)
CloseScreen()
OpenWindow(0, 0, 0, 256, 256, "RasterLines", #PB_Window_Minimize)
;Wait til our window is coming back to foreground - Attend que notre fenêtre repasse au premier plan
Repeat
;now our events are to be processed with WaitWindowEvent, else IsScreenActive() will never say that our window has the focus again
;it should be written in the doc!
;maintenant les événements sont à gérer avec WaitWindowEvent, sinon IsScreenActive() ne dit jamais que notre fenêtre a à nouveau le focus
;il faudrait mettre ça dans la doc!!!!
Event = WaitWindowEvent()
Until Event = #PB_Event_ActivateWindow
CloseWindow(0)
ReleaseMouse(0)
;Better recreate the screen - il vaut mieux recréer l'écran
InitDisplay()
;and the sprites too (have to!) - et les sprites aussi (indispensable)
CreateSprites()
;give to the system some time to rest - laisse un peu le temps au système de récupérer
;Delay(2000)
;We're waiting for the synchro a new time - On réattend la synchro
VBLWait()
SetPriorityClass_( GetCurrentProcess_(), #HIGH_PRIORITY_CLASS)
SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_ABOVE_NORMAL) ;warning : keyboard lock
EndProcedure
Procedure NewStar()
AddElement(Stars())
Stars()\x = Random(1024 + 128) - 64
Stars()\y = Random(768 + 128) - 64
Stars()\Speed = Random(16) + 1
EndProcedure
;*****************************************************************************
;- START
;*****************************************************************************
InitSprite()
InitKeyboard()
InitMouse()
InitDisplay()
CreateSprites()
For i = 1 To 5
NewStar()
Next i
Exit=#False
;we're giving max priority to our process - on donne une priorité maximale à notre processus
SetPriorityClass_( GetCurrentProcess_(), #REALTIME_PRIORITY_CLASS)
SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_TIME_CRITICAL) ;warning : keyboard lock
;*****************************************************************************
;- MAIN LOOP
;*****************************************************************************
Repeat
;wait for the sync - attends la synchro
VBLWait()
;flip buffers without the PB's sync - flippe le buffer sans utiliser la synchro PB
FlipBuffers()
;during VBL, lower a bit our priority to give time to OS (especially to handle the keyboard)
;pendant la VBL, baisse un peu notre priorité pour donner un peu de temps au système (pour gérer le clavier surtout)
SetPriorityClass_( GetCurrentProcess_(), #HIGH_PRIORITY_CLASS)
SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_NORMAL)
ExamineKeyboard()
ExamineMouse()
If KeyboardPushed(#PB_Key_Escape)
Exit=#True
EndIf
If KeyboardPushed(#PB_Key_Space)
NewStar()
EndIf
If Not IsScreenActive()
FullScreenCheck()
EndIf
;we're waiting for the VBL end (could be better!!!)
;on attend la fin de la VBL (à améliorer) pour être sûr de ne pas sauter une frame
VBLEndWait()
;we're giving max priority to our process - on donne une priorité maximale à notre processus
SetPriorityClass_( GetCurrentProcess_(), #REALTIME_PRIORITY_CLASS)
SetThreadPriority_( GetCurrentThread_() , #THREAD_PRIORITY_TIME_CRITICAL) ;warning : keyboard lock
ClearScreen(0)
;--- BENCHMARK
;draw the first Raster line (base of our benchmark)
RasterLine($FF0000)
;compute an effect
ForEach Stars()
Stars()\x + Stars()\Speed
If Stars()\x > 1023
Stars()\x - 1088
EndIf
Next
;display it
ForEach Stars()
DisplayTranslucentSprite(0, Stars()\x, Stars()\y, Stars()\Speed<<4)
Next
;draw the second RasterLine to see (visually) how much time our fx is taking
;the less space between the two lines, the fastest our effect
;affiche une RasterLine pour visualiser combien de temps prend notre effet
RasterLine($FF00)
;---- BENCHMARK END
StartDrawing(ScreenOutput())
DrawingMode(#PB_2DDrawing_Transparent)
Text.s = "Press SPACE to add stars ; ESC to quit"
DrawText(512 - TextWidth(Text)/2, 300, Text, #Blue)
Text.s = "Stars Nb : " + Str(ListSize(Stars()))
DrawText(512 - TextWidth(Text)/2, 320, Text, #Red)
StopDrawing()
Until Exit
CloseScreen()
End