Skip to content

Commit 78f1543

Browse files
AleksLitynskimihe
authored andcommitted
Add an ObjectDB Profiling Tool
A new tab is added to the debugger that can help profile a game's memory usage. Specifically, this lets you save a snapshot of all the objects in a running game's ObjectDB to disk. It then lets you view the snapshot and diff two snapshots against each other. This is meant to work similarly to Chrome's heap snapshot tool or Unity's memory profiler.
1 parent 4d1f26e commit 78f1543

40 files changed

+4262
-109
lines changed

core/object/object.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2334,12 +2334,11 @@ void postinitialize_handler(Object *p_object) {
23342334
p_object->_postinitialize();
23352335
}
23362336

2337-
void ObjectDB::debug_objects(DebugFunc p_func) {
2337+
void ObjectDB::debug_objects(DebugFunc p_func, void *p_user_data) {
23382338
spin_lock.lock();
2339-
23402339
for (uint32_t i = 0, count = slot_count; i < slot_max && count != 0; i++) {
23412340
if (object_slots[i].validator) {
2342-
p_func(object_slots[i].object);
2341+
p_func(object_slots[i].object, p_user_data);
23432342
count--;
23442343
}
23452344
}
@@ -2507,6 +2506,9 @@ void ObjectDB::cleanup() {
25072506
if (obj->is_class("Resource")) {
25082507
extra_info = " - Resource path: " + String(resource_get_path->call(obj, nullptr, 0, call_error));
25092508
}
2509+
if (obj->is_class("RefCounted")) {
2510+
extra_info = " - RefCount: " + itos(((RefCounted *)obj)->get_reference_count());
2511+
}
25102512

25112513
uint64_t id = uint64_t(i) | (uint64_t(object_slots[i].validator) << OBJECTDB_SLOT_MAX_COUNT_BITS) | (object_slots[i].is_ref_counted ? OBJECTDB_REFERENCE_BIT : 0);
25122514
DEV_ASSERT(id == (uint64_t)obj->get_instance_id()); // We could just use the id from the object, but this check may help catching memory corruption catastrophes.

core/object/object.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,7 +1046,7 @@ class ObjectDB {
10461046
static void setup();
10471047

10481048
public:
1049-
typedef void (*DebugFunc)(Object *p_obj);
1049+
typedef void (*DebugFunc)(Object *p_obj, void *p_user_data);
10501050

10511051
_ALWAYS_INLINE_ static Object *get_instance(ObjectID p_instance_id) {
10521052
uint64_t id = p_instance_id;
@@ -1078,6 +1078,6 @@ class ObjectDB {
10781078
template <typename T>
10791079
_ALWAYS_INLINE_ static Ref<T> get_ref(ObjectID p_instance_id); // Defined in ref_counted.h
10801080

1081-
static void debug_objects(DebugFunc p_func);
1081+
static void debug_objects(DebugFunc p_func, void *p_user_data);
10821082
static int get_object_count();
10831083
};

doc/classes/Tree.xml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,13 @@
124124
Returns column title language code.
125125
</description>
126126
</method>
127+
<method name="get_column_title_tooltip_text" qualifiers="const">
128+
<return type="String" />
129+
<param index="0" name="column" type="int" />
130+
<description>
131+
Returns the column title's tooltip text.
132+
</description>
133+
</method>
127134
<method name="get_column_width" qualifiers="const">
128135
<return type="int" />
129136
<param index="0" name="column" type="int" />
@@ -322,6 +329,14 @@
322329
Sets language code of column title used for line-breaking and text shaping algorithms, if left empty current locale is used instead.
323330
</description>
324331
</method>
332+
<method name="set_column_title_tooltip_text">
333+
<return type="void" />
334+
<param index="0" name="column" type="int" />
335+
<param index="1" name="tooltip_text" type="String" />
336+
<description>
337+
Sets the column title's tooltip text.
338+
</description>
339+
</method>
325340
<method name="set_selected">
326341
<return type="void" />
327342
<param index="0" name="item" type="TreeItem" />

editor/editor_json_visualizer.cpp

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/**************************************************************************/
2+
/* editor_json_visualizer.cpp */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#include "editor_json_visualizer.h"
32+
33+
#include "editor/editor_settings.h"
34+
#include "editor/editor_string_names.h"
35+
#include "editor/themes/editor_scale.h"
36+
#include "scene/gui/text_edit.h"
37+
#include "servers/rendering/shader_language.h"
38+
39+
EditorJsonVisualizerSyntaxHighlighter::EditorJsonVisualizerSyntaxHighlighter(const List<String> &p_keywords) {
40+
set_number_color(EDITOR_GET("text_editor/theme/highlighting/number_color"));
41+
set_symbol_color(EDITOR_GET("text_editor/theme/highlighting/symbol_color"));
42+
set_function_color(EDITOR_GET("text_editor/theme/highlighting/function_color"));
43+
set_member_variable_color(EDITOR_GET("text_editor/theme/highlighting/member_variable_color"));
44+
45+
clear_keyword_colors();
46+
const Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color");
47+
const Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color");
48+
49+
for (const String &keyword : p_keywords) {
50+
if (ShaderLanguage::is_control_flow_keyword(keyword)) {
51+
add_keyword_color(keyword, control_flow_keyword_color);
52+
} else {
53+
add_keyword_color(keyword, keyword_color);
54+
}
55+
}
56+
57+
// Colorize comments.
58+
const Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color");
59+
clear_color_regions();
60+
add_color_region("/*", "*/", comment_color, false);
61+
add_color_region("//", "", comment_color, true);
62+
63+
// Colorize preprocessor statements.
64+
const Color user_type_color = EDITOR_GET("text_editor/theme/highlighting/user_type_color");
65+
add_color_region("#", "", user_type_color, true);
66+
67+
set_uint_suffix_enabled(true);
68+
}
69+
70+
void EditorJsonVisualizer::load_theme(Ref<EditorJsonVisualizerSyntaxHighlighter> p_syntax_highlighter) {
71+
set_editable(false);
72+
set_syntax_highlighter(p_syntax_highlighter);
73+
add_theme_font_override(SceneStringName(font), get_theme_font("source", EditorStringName(EditorFonts)));
74+
add_theme_font_size_override(SceneStringName(font_size), get_theme_font_size("source_size", EditorStringName(EditorFonts)));
75+
add_theme_constant_override("line_spacing", EDITOR_GET("text_editor/appearance/whitespace/line_spacing"));
76+
77+
// Appearance: Caret
78+
set_caret_type((TextEdit::CaretType)EDITOR_GET("text_editor/appearance/caret/type").operator int());
79+
set_caret_blink_enabled(EDITOR_GET("text_editor/appearance/caret/caret_blink"));
80+
set_caret_blink_interval(EDITOR_GET("text_editor/appearance/caret/caret_blink_interval"));
81+
set_highlight_current_line(EDITOR_GET("text_editor/appearance/caret/highlight_current_line"));
82+
set_highlight_all_occurrences(EDITOR_GET("text_editor/appearance/caret/highlight_all_occurrences"));
83+
84+
// Appearance: Gutters
85+
set_draw_line_numbers(EDITOR_GET("text_editor/appearance/gutters/show_line_numbers"));
86+
set_line_numbers_zero_padded(EDITOR_GET("text_editor/appearance/gutters/line_numbers_zero_padded"));
87+
88+
// Appearance: Minimap
89+
set_draw_minimap(EDITOR_GET("text_editor/appearance/minimap/show_minimap"));
90+
set_minimap_width((int)EDITOR_GET("text_editor/appearance/minimap/minimap_width") * EDSCALE);
91+
92+
// Appearance: Lines
93+
set_line_folding_enabled(EDITOR_GET("text_editor/appearance/lines/code_folding"));
94+
set_draw_fold_gutter(EDITOR_GET("text_editor/appearance/lines/code_folding"));
95+
set_line_wrapping_mode((TextEdit::LineWrappingMode)EDITOR_GET("text_editor/appearance/lines/word_wrap").operator int());
96+
set_autowrap_mode((TextServer::AutowrapMode)EDITOR_GET("text_editor/appearance/lines/autowrap_mode").operator int());
97+
98+
// Appearance: Whitespace
99+
set_draw_tabs(EDITOR_GET("text_editor/appearance/whitespace/draw_tabs"));
100+
set_draw_spaces(EDITOR_GET("text_editor/appearance/whitespace/draw_spaces"));
101+
add_theme_constant_override("line_spacing", EDITOR_GET("text_editor/appearance/whitespace/line_spacing"));
102+
103+
// Behavior: Navigation
104+
set_scroll_past_end_of_file_enabled(EDITOR_GET("text_editor/behavior/navigation/scroll_past_end_of_file"));
105+
set_smooth_scroll_enabled(EDITOR_GET("text_editor/behavior/navigation/smooth_scrolling"));
106+
set_v_scroll_speed(EDITOR_GET("text_editor/behavior/navigation/v_scroll_speed"));
107+
set_drag_and_drop_selection_enabled(EDITOR_GET("text_editor/behavior/navigation/drag_and_drop_selection"));
108+
109+
// Behavior: Indent
110+
set_indent_size(EDITOR_GET("text_editor/behavior/indent/size"));
111+
set_auto_indent_enabled(EDITOR_GET("text_editor/behavior/indent/auto_indent"));
112+
set_indent_wrapped_lines(EDITOR_GET("text_editor/behavior/indent/indent_wrapped_lines"));
113+
}
114+
115+
void EditorJsonVisualizer::_notification(int p_what) {
116+
if (p_what == NOTIFICATION_THEME_CHANGED) {
117+
Ref<Font> source_font = get_theme_font("source", EditorStringName(EditorFonts));
118+
int source_font_size = get_theme_font_size("source_size", EditorStringName(EditorFonts));
119+
int line_spacing = EDITOR_GET("text_editor/theme/line_spacing");
120+
if (get_theme_font(SceneStringName(font)) != source_font) {
121+
add_theme_font_override(SceneStringName(font), source_font);
122+
}
123+
if (get_theme_font_size(SceneStringName(font_size)) != source_font_size) {
124+
add_theme_font_size_override(SceneStringName(font_size), source_font_size);
125+
}
126+
if (get_theme_constant("line_spacing") != line_spacing) {
127+
add_theme_constant_override("line_spacing", line_spacing);
128+
}
129+
}
130+
}

editor/editor_json_visualizer.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**************************************************************************/
2+
/* editor_json_visualizer.h */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#pragma once
32+
33+
#include "scene/gui/code_edit.h"
34+
#include "scene/resources/syntax_highlighter.h"
35+
36+
class EditorJsonVisualizerSyntaxHighlighter : public CodeHighlighter {
37+
GDCLASS(EditorJsonVisualizerSyntaxHighlighter, CodeHighlighter)
38+
39+
public:
40+
EditorJsonVisualizerSyntaxHighlighter(const List<String> &p_keywords);
41+
};
42+
43+
class EditorJsonVisualizer : public CodeEdit {
44+
GDCLASS(EditorJsonVisualizer, CodeEdit)
45+
46+
protected:
47+
void _notification(int p_what);
48+
49+
public:
50+
void load_theme(Ref<EditorJsonVisualizerSyntaxHighlighter> p_syntax_highlighter);
51+
};

editor/shader/editor_native_shader_source_visualizer.cpp

Lines changed: 6 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -37,40 +37,6 @@
3737
#include "scene/gui/text_edit.h"
3838
#include "servers/rendering/shader_language.h"
3939

40-
void EditorNativeShaderSourceVisualizer::_load_theme_settings() {
41-
syntax_highlighter->set_number_color(EDITOR_GET("text_editor/theme/highlighting/number_color"));
42-
syntax_highlighter->set_symbol_color(EDITOR_GET("text_editor/theme/highlighting/symbol_color"));
43-
syntax_highlighter->set_function_color(EDITOR_GET("text_editor/theme/highlighting/function_color"));
44-
syntax_highlighter->set_member_variable_color(EDITOR_GET("text_editor/theme/highlighting/member_variable_color"));
45-
46-
syntax_highlighter->clear_keyword_colors();
47-
48-
List<String> keywords;
49-
ShaderLanguage::get_keyword_list(&keywords);
50-
const Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color");
51-
const Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color");
52-
53-
for (const String &keyword : keywords) {
54-
if (ShaderLanguage::is_control_flow_keyword(keyword)) {
55-
syntax_highlighter->add_keyword_color(keyword, control_flow_keyword_color);
56-
} else {
57-
syntax_highlighter->add_keyword_color(keyword, keyword_color);
58-
}
59-
}
60-
61-
// Colorize comments.
62-
const Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color");
63-
syntax_highlighter->clear_color_regions();
64-
syntax_highlighter->add_color_region("/*", "*/", comment_color, false);
65-
syntax_highlighter->add_color_region("//", "", comment_color, true);
66-
67-
// Colorize preprocessor statements.
68-
const Color user_type_color = EDITOR_GET("text_editor/theme/highlighting/user_type_color");
69-
syntax_highlighter->add_color_region("#", "", user_type_color, true);
70-
71-
syntax_highlighter->set_uint_suffix_enabled(true);
72-
}
73-
7440
void EditorNativeShaderSourceVisualizer::_inspect_shader(RID p_shader) {
7541
if (versions) {
7642
memdelete(versions);
@@ -79,7 +45,10 @@ void EditorNativeShaderSourceVisualizer::_inspect_shader(RID p_shader) {
7945

8046
RS::ShaderNativeSourceCode nsc = RS::get_singleton()->shader_get_native_source_code(p_shader);
8147

82-
_load_theme_settings();
48+
List<String> keywords;
49+
ShaderLanguage::get_keyword_list(&keywords);
50+
Ref<EditorJsonVisualizerSyntaxHighlighter> syntax_highlighter;
51+
syntax_highlighter.instantiate(keywords);
8352

8453
versions = memnew(TabContainer);
8554
versions->set_tab_alignment(TabBar::ALIGNMENT_CENTER);
@@ -93,50 +62,8 @@ void EditorNativeShaderSourceVisualizer::_inspect_shader(RID p_shader) {
9362
vtab->set_h_size_flags(Control::SIZE_EXPAND_FILL);
9463
versions->add_child(vtab);
9564
for (int j = 0; j < nsc.versions[i].stages.size(); j++) {
96-
CodeEdit *code_edit = memnew(CodeEdit);
97-
code_edit->set_editable(false);
98-
code_edit->set_syntax_highlighter(syntax_highlighter);
99-
code_edit->add_theme_font_override(SceneStringName(font), get_theme_font("source", EditorStringName(EditorFonts)));
100-
code_edit->add_theme_font_size_override(SceneStringName(font_size), get_theme_font_size("source_size", EditorStringName(EditorFonts)));
101-
code_edit->add_theme_constant_override("line_spacing", EDITOR_GET("text_editor/appearance/whitespace/line_spacing"));
102-
103-
// Appearance: Caret
104-
code_edit->set_caret_type((TextEdit::CaretType)EDITOR_GET("text_editor/appearance/caret/type").operator int());
105-
code_edit->set_caret_blink_enabled(EDITOR_GET("text_editor/appearance/caret/caret_blink"));
106-
code_edit->set_caret_blink_interval(EDITOR_GET("text_editor/appearance/caret/caret_blink_interval"));
107-
code_edit->set_highlight_current_line(EDITOR_GET("text_editor/appearance/caret/highlight_current_line"));
108-
code_edit->set_highlight_all_occurrences(EDITOR_GET("text_editor/appearance/caret/highlight_all_occurrences"));
109-
110-
// Appearance: Gutters
111-
code_edit->set_draw_line_numbers(EDITOR_GET("text_editor/appearance/gutters/show_line_numbers"));
112-
code_edit->set_line_numbers_zero_padded(EDITOR_GET("text_editor/appearance/gutters/line_numbers_zero_padded"));
113-
114-
// Appearance: Minimap
115-
code_edit->set_draw_minimap(EDITOR_GET("text_editor/appearance/minimap/show_minimap"));
116-
code_edit->set_minimap_width((int)EDITOR_GET("text_editor/appearance/minimap/minimap_width") * EDSCALE);
117-
118-
// Appearance: Lines
119-
code_edit->set_line_folding_enabled(EDITOR_GET("text_editor/appearance/lines/code_folding"));
120-
code_edit->set_draw_fold_gutter(EDITOR_GET("text_editor/appearance/lines/code_folding"));
121-
code_edit->set_line_wrapping_mode((TextEdit::LineWrappingMode)EDITOR_GET("text_editor/appearance/lines/word_wrap").operator int());
122-
code_edit->set_autowrap_mode((TextServer::AutowrapMode)EDITOR_GET("text_editor/appearance/lines/autowrap_mode").operator int());
123-
124-
// Appearance: Whitespace
125-
code_edit->set_draw_tabs(EDITOR_GET("text_editor/appearance/whitespace/draw_tabs"));
126-
code_edit->set_draw_spaces(EDITOR_GET("text_editor/appearance/whitespace/draw_spaces"));
127-
code_edit->add_theme_constant_override("line_spacing", EDITOR_GET("text_editor/appearance/whitespace/line_spacing"));
128-
129-
// Behavior: Navigation
130-
code_edit->set_scroll_past_end_of_file_enabled(EDITOR_GET("text_editor/behavior/navigation/scroll_past_end_of_file"));
131-
code_edit->set_smooth_scroll_enabled(EDITOR_GET("text_editor/behavior/navigation/smooth_scrolling"));
132-
code_edit->set_v_scroll_speed(EDITOR_GET("text_editor/behavior/navigation/v_scroll_speed"));
133-
code_edit->set_drag_and_drop_selection_enabled(EDITOR_GET("text_editor/behavior/navigation/drag_and_drop_selection"));
134-
135-
// Behavior: Indent
136-
code_edit->set_indent_size(EDITOR_GET("text_editor/behavior/indent/size"));
137-
code_edit->set_auto_indent_enabled(EDITOR_GET("text_editor/behavior/indent/auto_indent"));
138-
code_edit->set_indent_wrapped_lines(EDITOR_GET("text_editor/behavior/indent/indent_wrapped_lines"));
139-
65+
EditorJsonVisualizer *code_edit = memnew(EditorJsonVisualizer);
66+
code_edit->load_theme(syntax_highlighter);
14067
code_edit->set_name(nsc.versions[i].stages[j].name);
14168
code_edit->set_text(nsc.versions[i].stages[j].code);
14269
code_edit->set_v_size_flags(Control::SIZE_EXPAND_FILL);
@@ -153,8 +80,6 @@ void EditorNativeShaderSourceVisualizer::_bind_methods() {
15380
}
15481

15582
EditorNativeShaderSourceVisualizer::EditorNativeShaderSourceVisualizer() {
156-
syntax_highlighter.instantiate();
157-
15883
add_to_group("_native_shader_source_visualizer");
15984
set_title(TTR("Native Shader Source Inspector"));
16085
}

editor/shader/editor_native_shader_source_visualizer.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,14 @@
3030

3131
#pragma once
3232

33+
#include "editor/editor_json_visualizer.h"
3334
#include "scene/gui/dialogs.h"
3435
#include "scene/gui/tab_container.h"
35-
#include "scene/resources/syntax_highlighter.h"
3636

3737
class EditorNativeShaderSourceVisualizer : public AcceptDialog {
3838
GDCLASS(EditorNativeShaderSourceVisualizer, AcceptDialog)
3939
TabContainer *versions = nullptr;
40-
Ref<CodeHighlighter> syntax_highlighter;
4140

42-
void _load_theme_settings();
4341
void _inspect_shader(RID p_shader);
4442

4543
protected:

0 commit comments

Comments
 (0)