When I test a program I usually use debuglog or my own ‘logprint’ function – that saves information in a txt file and so I can check it later, for errors or other things.
It works and the main advantage is to have a ‘storic’ of what the program did.
But sometimes I need a ‘real time’ check and something ‘more’ specific and automatic: I could fill my source-code of ‘LogPrint variabile’ in any point or any function and then read it later.
But surely, it’s not so handy.
So I started a little ‘profiler’ for BlitzMax.
Of course it’s very simple, no deep memory reading or other things you could usually find in professional IDE or compiler.
Basically it works in this way:
- register a variable you want to track, giving it a name – unique – the frequency of record (the delay between a record and the next one in millisecs) – and the kind of type (INT, FLOAT, DOUBLE etc)
- you can pause or resume or stop the ‘recorder’, show or read and save what you want.
At the moment I made a pre-alfa version (see the example below) and it seems to ‘works’: it registers the values (at the moment I recorded two variables – MOUSE_X and MOUSE_Y) and I can see them (pressing mouse botton 2).
I suspect there will be some time-error (all the things of recording ‘eats’ time) – but for the first step I think it’s quite good.
Next move: ‘recording’ objects – I presume I will use reflections to do this.
The ‘Draw’ function to show the data on screen is just a simple experiment: it needs more work to ‘scale’ and to represent different values and different variables.
Same for the other ‘Show’ functions: just to see if it works!
More to come.
Rem Profiler v.0.1 20 august 2017 End Rem SuperStrict Graphics 800,600 Global list_points:TList=New TList Type Tpoint Field x:Float,y:Float Function Add:Tpoint(xx:Int,yy:Int) Local p:Tpoint=New tpoint p.x=xx p.y=yy list_points.addlast p Tmonitor.AddObject("Tpoint",p) Return p End Function Function Show:Int() If list_points.count()=0 Return -1 Local ox:Int,oy:Int Local tp:Tpoint=Tpoint(list_points.First()) ox=tp.x oy=tp.y For Local p:Tpoint=EachIn list_points SetColor 200,200,200 DrawLine p.x,p.y,ox,oy SetColor 200,100,100 DrawRect p.x-2,p.y-2,4,4 ox=p.x oy=p.y Next SetColor 255,255,255 Return 0 End Function End Type Local px:Int,py:Int Repeat Cls 'WaitEvent() PollEvent Select EventID() Case EVENT_APPTERMINATE, EVENT_WINDOWCLOSE End End Select If MouseHit(2) TmonitorEvent.Pause() TmonitorEvent.ShowSpecific("MOUSE_Y") TmonitorEvent.Resume() End If px=MouseX() py=MouseY() If MouseHit(1) Tpoint.Add(px,py) Tmonitor.AddVar("MOUSE_X",px,100) Tmonitor.AddVar("MOUSE_Y",py,10) Tpoint.Show() TmonitorEvent.Draw("MOUSE_Y",255,50,50) TmonitorEvent.Draw("MOUSE_X",0,200,200) Flip Forever Type TmonitorEvent Global list_events:TList=New TList Global monitor_state:Int=0 Global time_internal:Int Global time_delay:Int=1000 Rem 0 = running 1 = pause End Rem Field var_name$ Field var_value_int:Int Field var_value_float:Float Field var_value_double:Double Field var_value_string:String Field var_type:Int Field event_time:Int Field ctime$ Function StartTime:Int() time_internal=MilliSecs() Return 0 End Function Function TimePassed:Int(t:Tmonitor) If MilliSecs()>(t.time_internal+t.time_delay) t.time_internal=MilliSecs() Return 1 End If Return 0 End Function Function Pause:Int() monitor_state=1 Return 0 End Function Function Resume:Int() monitor_state=0 StartTime() Return 0 End Function Function Start:Int() monitor_state=0 StartTime() Return 0 End Function Function Draw:Int(par$="",rr:Int=255,gg:Int=50,bb:Int=50) SetColor rr,gg,bb SetBlend ALPHABLEND SetAlpha .75 Local xx:Int For Local oo:TmonitorEvent=EachIn list_events If oo If oo.var_name.toupper()=par.toupper() DrawLine xx,0,xx,oo.var_value_int xx:+1 If xx>GraphicsWidth() xx=0 End If End If Next SetAlpha 1 SetBlend SOLIDBLEND SetColor 255,255,255 End Function Function ShowSpecific:Int(par$="") Local os$ Print "--------------------------------------------" For Local oo:TmonitorEvent=EachIn list_events If oo If oo.var_name.toupper()=par.toupper() os=oo.ctime+":"+oo.event_time+" '"+oo.var_name+"' = '" Select oo.var_type Case 0 os:+oo.var_value_int+"' (Int)" Case 1 os:+oo.var_value_float+"' (Float)" Case 2 os:+oo.var_value_double+"' (Double)" Case 3 os:+oo.var_value_string+"' (String)" End Select Print os os="" End If End If Next Print "--------------------------------------------" Print " " Return 0 End Function Function Show:Int() Local os$ Print "--------------------------------------------" For Local oo:TmonitorEvent=EachIn list_events If oo os=oo.ctime+":"+oo.event_time+" '"+oo.var_name+"' = '" Select oo.var_type Case 0 os:+oo.var_value_int+"' (Int)" Case 1 os:+oo.var_value_float+"' (Float)" Case 2 os:+oo.var_value_double+"' (Double)" Case 3 os:+oo.var_value_string+"' (String)" End Select Print os os="" End If Next Print "--------------------------------------------" Print " " Return 0 End Function Function Register:Int(t:Tmonitor) If monitor_state=1 Return 1 If t=Null Return 0 If TimePassed(t)=0 Return 0 Local tme:TmonitorEvent=New TmonitorEvent tme.ctime=CurrentTime() tme.event_time=MilliSecs() tme.var_name=t.var_name Select t.type_value Case 0 tme.var_value_int=t.var_int Case 1 tme.var_value_float=t.var_float Case 2 tme.var_value_double=t.var_double Case 3 tme.var_value_string=t.var_string End Select tme.var_type=t.type_value list_events.addlast tme Return 0 End Function End Type Type Tmonitor Field type_value:Int=0 Field var_name$ Field var_obj:Object Field var_int:Int Field var_float:Float Field var_double:Double Field var_string:String Field time_internal:Int Field time_delay:Int=1000 Global map_monitor:Tmap=CreateMap() Function ShowMonitored:Int() Local tm:Tmonitor For Local k$=EachIn MapKeys(map_monitor) tm=Tmonitor(MapValueForKey(map_monitor,k)) If tm Print tm.var_name End If Next Return 0 End Function Function AddVar:Tmonitor(nome$,_var:Int,_delay:Int=1000) Local tm:Tmonitor ' Print "Check for '"+nome+"'" Local tmp:Tmonitor=Tmonitor(MapValueForKey(map_monitor,nome.toupper())) If tmp=Null tm=New Tmonitor tm.var_name=nome.toupper() tm.var_int=_var tm.type_value=0 tm.time_internal=MilliSecs() tm.time_delay=_delay MapInsert map_monitor,nome.toupper(),tm Print "Register ("+nome+")" Else 'print "Update ("+nome+") ("+_Var+")" tm=tmp tm.var_int=_var 'tm.time_internal=MilliSecs() TmonitorEvent.Register(tm) End If Return tm End Function Function AddObject:Tmonitor(_NAME$,_obj:Object) Local tm:Tmonitor Local tmp:Tmonitor=Tmonitor(MapValueForKey(map_monitor,_NAME.toupper())) If tmp=Null tm=New Tmonitor tm.var_name=_NAME tm.var_obj=_obj tm.type_value=99 MapInsert map_monitor,_NAME.toupper(),tm 'registra Else End If Return tm End Function End Type