Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Custom Performance Monitor #39302

Merged
merged 1 commit into from
Jun 29, 2020
Merged

Conversation

simpuid
Copy link
Contributor

@simpuid simpuid commented Jun 4, 2020

Task 1 & 2 of GSoC project

Custom monitors can be added/removed/check using Performance.add_custom_monitor/Performance.remove_custom_monitor/Performance.has_custom_monitor

The value can be viewed in the Custom section of Monitor tab of Debugger.
Basically...

func _enter_tree():
	var self_var = self
	Performance.add_custom_monitor("Hello/There", Callable(self_var, "monitor_call"), [1, 2])
	Performance.add_custom_monitor("", Callable(self_var, "monitor_call"), [1, 2])
	Performance.add_custom_monitor("General/Kenobi", Callable(self_var, "monitor_call"), [2, 3])
	Performance.add_custom_monitor("Multiple/First", Callable(self_var, "monitor_call"), [3, 4])
	Performance.add_custom_monitor("Multiple/Second", Callable(self_var, "monitor_call"), [4, 5])
	Performance.add_custom_monitor("Audio/BuiltinCategory", Callable(self_var, "monitor_call"), [5, 6])
	Performance.add_custom_monitor("Too/Much/Slashes/So it's in Custom", Callable(self_var, "monitor_call"), [6, 7])
	Performance.add_custom_monitor("No slash so it's in Custom", Callable(self_var, "monitor_call"), [7, 8])

func _exit_tree():
	Performance.remove_custom_monitor("Hello/There")
	Performance.remove_custom_monitor("")
	Performance.remove_custom_monitor("General/Kenobi")
	Performance.remove_custom_monitor("Multiple/First")
	Performance.remove_custom_monitor("Multiple/Second")
	Performance.remove_custom_monitor("Audio/BuiltinCategory")
	Performance.remove_custom_monitor("Too/Much/Slashes/So it's in Custom")
	Performance.remove_custom_monitor("No slash so it's in Custom")

func monitor_call(from, to) -> float:
	return rand_range(from, to)

Above code causes

sample

Edit: Monitor list is now cleared when debugging is started.
Edit: Updated with categorized monitors.
Edit: This implements godotengine/godot-proposals#1014 too

Bugsquad edit: This closes godotengine/godot-proposals#229.

@Calinou Calinou added this to the 4.0 milestone Jun 4, 2020
@simpuid simpuid force-pushed the custom-monitors branch from 828edef to 7853c97 Compare June 4, 2020 22:16
@samdze
Copy link
Contributor

samdze commented Jun 4, 2020

Nice!
Would it be possible to add the capability to define monitors inside any category in the monitors tree? (Not only in the arbitrary "Custom" one)

Like this:

func _enter_tree():
	var self_var = self

        // This one goes under "Ammo"
	Performance.add_custom_monitor("Ammo/Gun", ..., ...)
        Performance.add_custom_monitor("Ammo/Rifle", ..., ...)

        // These one go under another category "Enemies"
	Performance.add_custom_monitor("Enemies/Bats", ..., ...)
        Performance.add_custom_monitor("Enemies/Spiders", ..., ...)

        // And you could also add a monitor to an already existing category
	Performance.add_custom_monitor("Physics 3d/Bouncing", ..., ...)

        // The method call could be changed this way if preferred:
        Performance.add_custom_monitor(category, name, callable, params)

I think the user would be able to organize his monitors much better.

Maybe I'd also drop the "_custom" from the method names, there's no need to specify those are "custom" monitors that you're adding/removing.

@simpuid
Copy link
Contributor Author

simpuid commented Jun 5, 2020

add_monitor("category/name" , callable...., params....) seems the best option.

add_monitor("category", "name", callable..., params....) will cause problems because internally the ids used for those monitors would be something like category/name(That slash could be any ASCII symbol). Method calls like Performance.add_monitor("a/b", "c", callable..., params...) would cause confusion among users.

I think something like this will work

  • / is present => use the supplied category
  • / is absent => use the Custom category.

Adding monitors to built-in categories seems difficult but I think I can do it. However keep in mind that there is no Physics 3d . The Performance class uses snake_case internally i.e. physics_3d is converted to Physics 3d, so something like physics_3d/bouncing will use the builtin category. This opens the issue of name collisions with monitors like Physics 3d/bouncing with physics_3d/bouncing
@Faless @mhilbrunner What are your opinions about categorizing custom monitors?

@simpuid simpuid closed this Jun 5, 2020
@simpuid simpuid reopened this Jun 5, 2020
@simpuid
Copy link
Contributor Author

simpuid commented Jun 5, 2020

Accidently clicked the Close and comment button

@simpuid simpuid force-pushed the custom-monitors branch from 7853c97 to d610e01 Compare June 5, 2020 06:11
@simpuid
Copy link
Contributor Author

simpuid commented Jun 5, 2020

@samdze Went ahead with Capitalized category names. (Physics 3d/something will work now).
The only limitation is that Custom/something and something both will be displayed in Custom category.

@simpuid simpuid force-pushed the custom-monitors branch from d610e01 to 0ed3765 Compare June 5, 2020 06:50
@samdze
Copy link
Contributor

samdze commented Jun 5, 2020

@simpuid Seems good!

I also saw that renaming the methods to add_monitor(...), get_monitor(...) and has_monitor(...) would collide with the already existing get_monitor(Monitor p_monitor), used for built-in monitors.
So while I'd prefer not having that "_custom" in the method names, it's probably necessary if a more extensive refactor is unwanted.

@samdze
Copy link
Contributor

samdze commented Jun 5, 2020

I also opened this proposal, you may be interested.
godotengine/godot-proposals#1014

Copy link
Collaborator

@Faless Faless left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! Excellent work 🏅 . I'm wondering if we should move the performance drawing functions (setup and parsing) to its own EditorDebuggerPerformance class. What do you think @simpuid ?

EDIT: That would also help keeping things clean if we implement godotengine/godot-proposals#1014 in the future (which I think it's a good idea).

@simpuid
Copy link
Contributor Author

simpuid commented Jun 16, 2020

This looks great! Excellent work medal_sports . I'm wondering if we should move the performance drawing functions (setup and parsing) to its own EditorDebuggerPerformance class. What do you think @simpuid ?

EDIT: That would also help keeping things clean if we implement godotengine/godot-proposals#1014 in the future (which I think it's a good idea).

Yes, we can do that (just like EditorProfiler, EditorVisualProfiler and EditorNetworkProfiler). I can also take help from their implementations.

Shouldn't we name it EditorPerformance / EditorPerformanceProfiler? (there is no "debugger" word in EditorProfiler, EditorVisualProfiler and EditorNetworkProfiler)

@Faless
Copy link
Collaborator

Faless commented Jun 16, 2020

Shouldn't we name it EditorPerformance / EditorPerformanceProfiler?

Yeah, I agree, both sounds good.
Maybe the latter is more in line with RemoteDebugger::PerformanceProfiler in remote_debugger.cpp

@simpuid simpuid requested a review from Faless June 21, 2020 09:26
@simpuid
Copy link
Contributor Author

simpuid commented Jun 22, 2020

Yeah, I agree, both sounds good.
Maybe the latter is more in line with RemoteDebugger::PerformanceProfiler in remote_debugger.cpp

@Faless I rewrote the parsing and drawing logic to a separate class EditorPerformanceProfiler
The implementation deviates from the proposal but it's better.
Changes:

  • Built-in performance monitors' data are stored the same way as custom monitor.
  • There is only one drawing function EditorPerformanceProfiler::_monitor_draw, Improve readability and data exploring capabilities of monitors and profiler godot-proposals#1014 could be implemented there for both type of monitors.
  • There are only 2 types of messages instead of three
    1. 'performance:profile_frame' : contains the data of all (builtin + custom) monitors.
    2. 'performance:profile_names' : contains the name of custom monitors.

@simpuid
Copy link
Contributor Author

simpuid commented Jun 27, 2020

@samdze Added horizontal guide lines and a vertical marker line that can be placed by clicking LMB.
I think that should be enough for godotengine/godot-proposals#1014

Does text of horizontal guide lines look too cumbersome?

sample

@Calinou
Copy link
Member

Calinou commented Jun 27, 2020

@simpuid There seems to be a lot of horizontal lines on your graph. My PR made it so the number of lines depends on the monitor's height (and never exceeds 5).

@simpuid
Copy link
Contributor Author

simpuid commented Jun 27, 2020

@simpuid There seems to be a lot of horizontal lines on your graph. My PR made it so the number of lines depends on the monitor's height (and never exceeds 5).

I am calculating the number of horizontal lines depending on the graph height and text height (So they can be rendered easily)

int line_count = rect.size.height / (graph_font->get_height() * 2);

@Calinou should I limit it to max 5?

@Calinou
Copy link
Member

Calinou commented Jun 27, 2020

@Calinou should I limit it to max 5?

Yes, there's not much benefit to having more than 5.

…ues of Monitor

Custom monitors can be added/removed/checked using `Performance.add_custom_monitor`/`Performance.remove_custom_monitor`/`Performance.has_custom_monitor`

The value can be viewed in the `Monitor` tab of Debugger.

Text before `/` is used to categorize the custom monitor.

`EditorPerformanceProfiler` class is created to separate logic from `ScriptEditorDebugger`

User can click on the graph of monitors to read the value at that point.

Graph includes intermediate base lines.
@simpuid simpuid requested a review from a team as a code owner June 29, 2020 12:45
@simpuid
Copy link
Contributor Author

simpuid commented Jun 29, 2020

Added documentation

Copy link
Collaborator

@Faless Faless left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Amazing job 🏆 !

Copy link
Collaborator

@Faless Faless left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I think you accidentally committed ProjectSetting.xml, could you revert that? Thanks

@simpuid
Copy link
Contributor Author

simpuid commented Jun 29, 2020

Actually, I think you accidentally committed ProjectSetting.xml, could you revert that? Thanks

Sorry! Reverted.

doc/classes/Performance.xml Outdated Show resolved Hide resolved
editor/debugger/editor_performance_profiler.cpp Outdated Show resolved Hide resolved
editor/debugger/editor_performance_profiler.h Outdated Show resolved Hide resolved
@akien-mga akien-mga merged commit d41e8d8 into godotengine:master Jun 29, 2020
@akien-mga
Copy link
Member

Thanks!

@neikeq
Copy link
Contributor

neikeq commented Jun 29, 2020

Your custom monitors will make a fine addition to our collection.

@williamd1k0
Copy link
Contributor

Sorry, but is this portable for 3.2 branch? :P

@simpuid
Copy link
Contributor Author

simpuid commented Jun 29, 2020

Sorry, but is this portable for 3.2 branch? :P

I don't think so! Callables are not available in 3.2 branch :(

@Faless
Copy link
Collaborator

Faless commented Jun 30, 2020

Sorry, but is this portable for 3.2 branch?

Not really, the whole debugger was heavily refactored in the master branch, backporting is unlikely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for defining custom perfomance monitors
7 participants