Profiler
Monkey Forums/Monkey Code/Profiler
| ||
This is the profiler code I use myself.'============================= 'profiler.monkey by Belimoth 'uncomment the commented code to have the profiler profile itself :P '============================= Import mojo '============================= Class cProfilerMap Extends StringMap<cProfiler> End '============================= Class Profiler Const NUMBER_OF_CALLS_TO_AVERAGE:Int = 100 Global profilers := New cProfilerMap Global running := New List<cProfiler> 'Global startProfiler := New cProfiler("Profiler Start", NUMBER_OF_CALLS_TO_AVERAGE, False) 'Global stopProfiler := New cProfiler("Profiler Stop", NUMBER_OF_CALLS_TO_AVERAGE, False) Function Start:Void(profilerName:String, callsMax:Int = NUMBER_OF_CALLS_TO_AVERAGE) 'startProfiler.Start() If profilers.Contains(profilerName) profilers.Get(profilerName).Start() Else Local parent:cProfiler If running.IsEmpty() parent = Null Else parent = running.Last() Endif If parent = Null Local profilerNew := New cProfiler(profilerName, callsMax, True) profilers.Add(profilerName, profilerNew) profilerNew.Start() Elseif parent.children.Contains(profilerName) parent.children.Get(profilerName).Start() Else Local profilerNew := New cProfiler(profilerName, callsMax, True) parent.children.Add(profilerName, profilerNew) profilerNew.Start() Endif Endif 'startProfiler.Stop() End Function Stop:Void(profilerName:String = "this doesn't really matter") 'stopProfiler.Start() running.Last().Stop() 'stopProfiler.Stop() End Function Output:Void() Print "" Print "PROFILER RESULTS" Print "" 'Print startProfiler 'Print stopProfiler Local profilerTemp:cProfiler For profilerTemp = Eachin profilers.Values() PrintProfiler(profilerTemp) Next Print "" End Function PrintProfiler:Void(profiler:cProfiler, indent:String = "") Print indent + profiler If profiler.HasChildren() Local profilerTemp:cProfiler For profilerTemp = Eachin profiler.children.Values() PrintProfiler(profilerTemp, indent + " ") Next Endif End End '============================= Class cProfiler Field name:String Field timeStart:Int Field calls:Int Field callsMax:Int Field total:Float Field result:Float Field doneCounting:Bool Field children:cProfilerMap Field nest:Bool Method New(name:String, callsMax:Int, nest:Bool = False) Self.name = name Self.callsMax = callsMax Self.nest = nest If nest = True Self.children = New cProfilerMap Endif End Method New(callsMax:Int) Self.name = "Profiler" Self.callsMax = callsMax Self.nest = False End Method GetResult:Float() Return result End Method HasChildren:Bool() Return Not( children.IsEmpty() ) End Method Start:Void() If nest Then Profiler.running.AddLast(Self) timeStart = Millisecs() If calls >= callsMax calls = 0 total = 0.0 Endif End Method Stop:Void() If nest Then Profiler.running.RemoveLast() 'should be self Local timePassed:Int = Millisecs() - timeStart total += timePassed calls += 1 If calls >= callsMax doneCounting = True result = total / calls Endif End Method ToString:String() If doneCounting Return name + ": " + result Else Return name + " is not done counting" Endif End End '============================= |
| ||
Here is how it would be used:'============================= 'example.monkey '============================= Strict Import mojo Import profiler '============================= '============MAIN============= Function Main:Int() New MyApp() Return 1 End '============================= '=============APP============= Class MyApp Extends App Field fpsProfiler:cProfiler '============================= Method OnCreate:Int() fpsProfiler = New cProfiler(10) Profiler.Start("OnCreate", 1) 'initializing stuff SetUpdateRate(60) Profiler.Stop("OnCreate") Return 1 End '============================= Method OnUpdate:Int() Profiler.Start("OnUpdate") 'doing stuff Profiler.Stop("OnUpdate") If KeyHit(KEY_ENTER) Profiler.Output() Endif Return 1 End '============================= Method OnRender:Int() Profiler.Start("OnRender") Profiler.Start("Drawing Stuff") 'drawing stuff Profiler.Stop("Drawing Stuff") 'drawing other stuff Profiler.Stop("OnRender") fpsProfiler.Stop() fpsProfiler.Start() DrawText("FPS: " + Int(1000 / fpsProfiler.GetResult()), 1, 1) Return 1 End '============================= End '============================= As you can see there are two ways to use it: a) Standalone profilers that you manage yourself, as in fpsProfiler above. b) Automatically managed profilers that are named and will show all of their results together when Profiler.Output() is called. It is nifty :) |
| ||
The syntaxes are:myProfiler = New cProfiler(numberOfCallsToAverage:Int) myProfiler.Start() myProfiler.Stop() myProfiler.GetResult() Profiler.Start("My Profile", numberOfCallsToAverage:Int = 100) Profiler.Stop("My Profile") Profiler.Output() One caveat, don't do this with the named profilers: Profiler.Start("Profile A") Profiler.Start("Profile B") Profiler.Stop("Profile A") Profiler.Stop("Profile B") I'm not sure why you would do that, but just so you are aware, it will expect named profilers to be nested properly. |
| ||
You can see it in action in this demo. |
| ||
Excellent. Thank you for sharing. |
| ||
Great work I am going to use this on my current project that has a bottle neck. |
| ||
I know this could be a stupid question, but what do I use this for? |
| ||
You use it to see how long each part of your program takes on average, so if things are going slow you can find out where the problem is :) |
| ||
Okay thanks! |
| ||
EDIT: Double post :( |
| ||
Been putting some more work into this for my framework. The new version doesn't do any averaging yet, but it DOES have the ability to graph its results. The DrawLine and DrawRect commands look like absolute garbage on HTML5, so I ended up using an image-based approach with WritePixels. I haven't used Monkey's WritePixels before so I'm sure there are plenty of optimizations to be made. A basic usage would look like this: Class MyApp Extends App Method OnUpdate() Profiler.Update() Profiler.Start("OnUpdate", [255, 0, 0]) ... Profiler.Stop("OnUpdate") End Method OnRender() Profiler.Start("OnRender", [0, 128, 255]) ... Profiler.Stop("OnRender") Profiler.Draw(0, 0) End End Still a work in progress. EDIT: Also there is a "dummy" profiler that gets substituted for release mode. That way you don't have to go through and remove all the function calls. EDIT: Fixed a small error with the rendering. EDIT: More small fixes. |