Merge pull request #75623 from reach-satori/profiler_for_builtins
Fix missing script time for some functions in profiler
This commit is contained in:
commit
549cb966f8
16 changed files with 191 additions and 57 deletions
|
@ -384,10 +384,12 @@ public:
|
||||||
uint64_t call_count;
|
uint64_t call_count;
|
||||||
uint64_t total_time;
|
uint64_t total_time;
|
||||||
uint64_t self_time;
|
uint64_t self_time;
|
||||||
|
uint64_t internal_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void profiling_start() = 0;
|
virtual void profiling_start() = 0;
|
||||||
virtual void profiling_stop() = 0;
|
virtual void profiling_stop() = 0;
|
||||||
|
virtual void profiling_set_save_native_calls(bool p_enable) = 0;
|
||||||
|
|
||||||
virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) = 0;
|
virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) = 0;
|
||||||
virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) = 0;
|
virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) = 0;
|
||||||
|
|
|
@ -145,6 +145,7 @@ void ScriptLanguageExtension::_bind_methods() {
|
||||||
|
|
||||||
GDVIRTUAL_BIND(_profiling_start);
|
GDVIRTUAL_BIND(_profiling_start);
|
||||||
GDVIRTUAL_BIND(_profiling_stop);
|
GDVIRTUAL_BIND(_profiling_stop);
|
||||||
|
GDVIRTUAL_BIND(_profiling_set_save_native_calls, "enable");
|
||||||
|
|
||||||
GDVIRTUAL_BIND(_profiling_get_accumulated_data, "info_array", "info_max");
|
GDVIRTUAL_BIND(_profiling_get_accumulated_data, "info_array", "info_max");
|
||||||
GDVIRTUAL_BIND(_profiling_get_frame_data, "info_array", "info_max");
|
GDVIRTUAL_BIND(_profiling_get_frame_data, "info_array", "info_max");
|
||||||
|
|
|
@ -607,6 +607,7 @@ public:
|
||||||
|
|
||||||
EXBIND0(profiling_start)
|
EXBIND0(profiling_start)
|
||||||
EXBIND0(profiling_stop)
|
EXBIND0(profiling_stop)
|
||||||
|
EXBIND1(profiling_set_save_native_calls, bool)
|
||||||
|
|
||||||
GDVIRTUAL2R(int, _profiling_get_accumulated_data, GDExtensionPtr<ScriptLanguageExtensionProfilingInfo>, int)
|
GDVIRTUAL2R(int, _profiling_get_accumulated_data, GDExtensionPtr<ScriptLanguageExtensionProfilingInfo>, int)
|
||||||
|
|
||||||
|
|
|
@ -185,6 +185,9 @@
|
||||||
<member name="debugger/auto_switch_to_remote_scene_tree" type="bool" setter="" getter="">
|
<member name="debugger/auto_switch_to_remote_scene_tree" type="bool" setter="" getter="">
|
||||||
If [code]true[/code], automatically switches to the [b]Remote[/b] scene tree when running the project from the editor. If [code]false[/code], stays on the [b]Local[/b] scene tree when running the project from the editor.
|
If [code]true[/code], automatically switches to the [b]Remote[/b] scene tree when running the project from the editor. If [code]false[/code], stays on the [b]Local[/b] scene tree when running the project from the editor.
|
||||||
</member>
|
</member>
|
||||||
|
<member name="debugger/profile_native_calls" type="bool" setter="" getter="">
|
||||||
|
If [code]true[/code], enables collection of profiling data from non-GDScript Godot functions, such as engine class methods. Enabling this slows execution while profiling further.
|
||||||
|
</member>
|
||||||
<member name="debugger/profiler_frame_history_size" type="int" setter="" getter="">
|
<member name="debugger/profiler_frame_history_size" type="int" setter="" getter="">
|
||||||
The size of the profiler's frame history. The default value (3600) allows seeing up to 60 seconds of profiling if the project renders at a constant 60 FPS. Higher values allow viewing longer periods of profiling in the graphs, especially when the project is running at high framerates.
|
The size of the profiler's frame history. The default value (3600) allows seeing up to 60 seconds of profiling if the project renders at a constant 60 FPS. Higher values allow viewing longer periods of profiling in the graphs, especially when the project is running at high framerates.
|
||||||
</member>
|
</member>
|
||||||
|
|
|
@ -276,6 +276,12 @@
|
||||||
<description>
|
<description>
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="_profiling_set_save_native_calls" qualifiers="virtual">
|
||||||
|
<return type="void" />
|
||||||
|
<param index="0" name="enable" type="bool" />
|
||||||
|
<description>
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="_profiling_start" qualifiers="virtual">
|
<method name="_profiling_start" qualifiers="virtual">
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<description>
|
<description>
|
||||||
|
|
|
@ -97,6 +97,7 @@ void EditorProfiler::clear() {
|
||||||
plot_sigs.clear();
|
plot_sigs.clear();
|
||||||
plot_sigs.insert("physics_frame_time");
|
plot_sigs.insert("physics_frame_time");
|
||||||
plot_sigs.insert("category_frame_time");
|
plot_sigs.insert("category_frame_time");
|
||||||
|
display_internal_profiles->set_visible(EDITOR_GET("debugger/profile_native_calls"));
|
||||||
|
|
||||||
updating_frame = true;
|
updating_frame = true;
|
||||||
cursor_metric_edit->set_min(0);
|
cursor_metric_edit->set_min(0);
|
||||||
|
@ -352,6 +353,9 @@ void EditorProfiler::_update_frame() {
|
||||||
for (int j = m.categories[i].items.size() - 1; j >= 0; j--) {
|
for (int j = m.categories[i].items.size() - 1; j >= 0; j--) {
|
||||||
const Metric::Category::Item &it = m.categories[i].items[j];
|
const Metric::Category::Item &it = m.categories[i].items[j];
|
||||||
|
|
||||||
|
if (it.internal == it.total && !display_internal_profiles->is_pressed() && m.categories[i].name == "Script Functions") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
TreeItem *item = variables->create_item(category);
|
TreeItem *item = variables->create_item(category);
|
||||||
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
|
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
|
||||||
item->set_editable(0, true);
|
item->set_editable(0, true);
|
||||||
|
@ -363,6 +367,9 @@ void EditorProfiler::_update_frame() {
|
||||||
item->set_tooltip_text(0, it.name + "\n" + it.script + ":" + itos(it.line));
|
item->set_tooltip_text(0, it.name + "\n" + it.script + ":" + itos(it.line));
|
||||||
|
|
||||||
float time = dtime == DISPLAY_SELF_TIME ? it.self : it.total;
|
float time = dtime == DISPLAY_SELF_TIME ? it.self : it.total;
|
||||||
|
if (dtime == DISPLAY_SELF_TIME && !display_internal_profiles->is_pressed()) {
|
||||||
|
time += it.internal;
|
||||||
|
}
|
||||||
|
|
||||||
item->set_text(1, _get_time_as_text(m, time, it.calls));
|
item->set_text(1, _get_time_as_text(m, time, it.calls));
|
||||||
|
|
||||||
|
@ -404,6 +411,10 @@ void EditorProfiler::_clear_pressed() {
|
||||||
_update_plot();
|
_update_plot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorProfiler::_internal_profiles_pressed() {
|
||||||
|
_combo_changed(0);
|
||||||
|
}
|
||||||
|
|
||||||
void EditorProfiler::_notification(int p_what) {
|
void EditorProfiler::_notification(int p_what) {
|
||||||
switch (p_what) {
|
switch (p_what) {
|
||||||
case NOTIFICATION_ENTER_TREE:
|
case NOTIFICATION_ENTER_TREE:
|
||||||
|
@ -635,6 +646,11 @@ EditorProfiler::EditorProfiler() {
|
||||||
|
|
||||||
hb->add_child(display_time);
|
hb->add_child(display_time);
|
||||||
|
|
||||||
|
display_internal_profiles = memnew(CheckButton(TTR("Display internal functions")));
|
||||||
|
display_internal_profiles->set_pressed(false);
|
||||||
|
display_internal_profiles->connect("pressed", callable_mp(this, &EditorProfiler::_internal_profiles_pressed));
|
||||||
|
hb->add_child(display_internal_profiles);
|
||||||
|
|
||||||
hb->add_spacer();
|
hb->add_spacer();
|
||||||
|
|
||||||
hb->add_child(memnew(Label(TTR("Frame #:"))));
|
hb->add_child(memnew(Label(TTR("Frame #:"))));
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#include "scene/gui/box_container.h"
|
#include "scene/gui/box_container.h"
|
||||||
#include "scene/gui/button.h"
|
#include "scene/gui/button.h"
|
||||||
|
#include "scene/gui/check_button.h"
|
||||||
#include "scene/gui/label.h"
|
#include "scene/gui/label.h"
|
||||||
#include "scene/gui/option_button.h"
|
#include "scene/gui/option_button.h"
|
||||||
#include "scene/gui/spin_box.h"
|
#include "scene/gui/spin_box.h"
|
||||||
|
@ -67,6 +68,7 @@ public:
|
||||||
int line = 0;
|
int line = 0;
|
||||||
float self = 0;
|
float self = 0;
|
||||||
float total = 0;
|
float total = 0;
|
||||||
|
float internal = 0;
|
||||||
int calls = 0;
|
int calls = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -105,6 +107,8 @@ private:
|
||||||
OptionButton *display_mode = nullptr;
|
OptionButton *display_mode = nullptr;
|
||||||
OptionButton *display_time = nullptr;
|
OptionButton *display_time = nullptr;
|
||||||
|
|
||||||
|
CheckButton *display_internal_profiles = nullptr;
|
||||||
|
|
||||||
SpinBox *cursor_metric_edit = nullptr;
|
SpinBox *cursor_metric_edit = nullptr;
|
||||||
|
|
||||||
Vector<Metric> frame_metrics;
|
Vector<Metric> frame_metrics;
|
||||||
|
@ -130,6 +134,8 @@ private:
|
||||||
void _activate_pressed();
|
void _activate_pressed();
|
||||||
void _clear_pressed();
|
void _clear_pressed();
|
||||||
|
|
||||||
|
void _internal_profiles_pressed();
|
||||||
|
|
||||||
String _get_time_as_text(const Metric &m, float p_time, int p_calls);
|
String _get_time_as_text(const Metric &m, float p_time, int p_calls);
|
||||||
|
|
||||||
void _make_metric_ptrs(Metric &m);
|
void _make_metric_ptrs(Metric &m);
|
||||||
|
|
|
@ -758,6 +758,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, uint64_t p_thread
|
||||||
int calls = frame.script_functions[i].call_count;
|
int calls = frame.script_functions[i].call_count;
|
||||||
float total = frame.script_functions[i].total_time;
|
float total = frame.script_functions[i].total_time;
|
||||||
float self = frame.script_functions[i].self_time;
|
float self = frame.script_functions[i].self_time;
|
||||||
|
float internal = frame.script_functions[i].internal_time;
|
||||||
|
|
||||||
EditorProfiler::Metric::Category::Item item;
|
EditorProfiler::Metric::Category::Item item;
|
||||||
if (profiler_signature.has(signature)) {
|
if (profiler_signature.has(signature)) {
|
||||||
|
@ -782,6 +783,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, uint64_t p_thread
|
||||||
item.calls = calls;
|
item.calls = calls;
|
||||||
item.self = self;
|
item.self = self;
|
||||||
item.total = total;
|
item.total = total;
|
||||||
|
item.internal = internal;
|
||||||
funcs.items.write[i] = item;
|
funcs.items.write[i] = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1097,7 +1099,9 @@ void ScriptEditorDebugger::_profiler_activate(bool p_enable, int p_type) {
|
||||||
// Add max funcs options to request.
|
// Add max funcs options to request.
|
||||||
Array opts;
|
Array opts;
|
||||||
int max_funcs = EDITOR_GET("debugger/profiler_frame_max_functions");
|
int max_funcs = EDITOR_GET("debugger/profiler_frame_max_functions");
|
||||||
|
bool include_native = EDITOR_GET("debugger/profile_native_calls");
|
||||||
opts.push_back(CLAMP(max_funcs, 16, 512));
|
opts.push_back(CLAMP(max_funcs, 16, 512));
|
||||||
|
opts.push_back(include_native);
|
||||||
msg_data.push_back(opts);
|
msg_data.push_back(opts);
|
||||||
}
|
}
|
||||||
_put_msg("profiler:servers", msg_data);
|
_put_msg("profiler:servers", msg_data);
|
||||||
|
|
|
@ -776,6 +776,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
|
||||||
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "debugger/profiler_frame_max_functions", 64, "16,512,1")
|
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "debugger/profiler_frame_max_functions", 64, "16,512,1")
|
||||||
EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "debugger/remote_scene_tree_refresh_interval", 1.0, "0.1,10,0.01,or_greater")
|
EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "debugger/remote_scene_tree_refresh_interval", 1.0, "0.1,10,0.01,or_greater")
|
||||||
EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "debugger/remote_inspect_refresh_interval", 0.2, "0.02,10,0.01,or_greater")
|
EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "debugger/remote_inspect_refresh_interval", 0.2, "0.02,10,0.01,or_greater")
|
||||||
|
EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "debugger/profile_native_calls", false, "")
|
||||||
|
|
||||||
// HTTP Proxy
|
// HTTP Proxy
|
||||||
_initial_set("network/http_proxy/host", "");
|
_initial_set("network/http_proxy/host", "");
|
||||||
|
|
|
@ -2220,6 +2220,8 @@ void GDScriptLanguage::profiling_start() {
|
||||||
elem->self()->profile.last_frame_call_count = 0;
|
elem->self()->profile.last_frame_call_count = 0;
|
||||||
elem->self()->profile.last_frame_self_time = 0;
|
elem->self()->profile.last_frame_self_time = 0;
|
||||||
elem->self()->profile.last_frame_total_time = 0;
|
elem->self()->profile.last_frame_total_time = 0;
|
||||||
|
elem->self()->profile.native_calls.clear();
|
||||||
|
elem->self()->profile.last_native_calls.clear();
|
||||||
elem = elem->next();
|
elem = elem->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2227,6 +2229,13 @@ void GDScriptLanguage::profiling_start() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GDScriptLanguage::profiling_set_save_native_calls(bool p_enable) {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
MutexLock lock(mutex);
|
||||||
|
profile_native_calls = p_enable;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void GDScriptLanguage::profiling_stop() {
|
void GDScriptLanguage::profiling_stop() {
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
MutexLock lock(this->mutex);
|
MutexLock lock(this->mutex);
|
||||||
|
@ -2241,17 +2250,32 @@ int GDScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr,
|
||||||
|
|
||||||
MutexLock lock(this->mutex);
|
MutexLock lock(this->mutex);
|
||||||
|
|
||||||
|
profiling_collate_native_call_data(true);
|
||||||
SelfList<GDScriptFunction> *elem = function_list.first();
|
SelfList<GDScriptFunction> *elem = function_list.first();
|
||||||
while (elem) {
|
while (elem) {
|
||||||
if (current >= p_info_max) {
|
if (current >= p_info_max) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
int last_non_internal = current;
|
||||||
p_info_arr[current].call_count = elem->self()->profile.call_count.get();
|
p_info_arr[current].call_count = elem->self()->profile.call_count.get();
|
||||||
p_info_arr[current].self_time = elem->self()->profile.self_time.get();
|
p_info_arr[current].self_time = elem->self()->profile.self_time.get();
|
||||||
p_info_arr[current].total_time = elem->self()->profile.total_time.get();
|
p_info_arr[current].total_time = elem->self()->profile.total_time.get();
|
||||||
p_info_arr[current].signature = elem->self()->profile.signature;
|
p_info_arr[current].signature = elem->self()->profile.signature;
|
||||||
elem = elem->next();
|
|
||||||
current++;
|
current++;
|
||||||
|
|
||||||
|
int nat_time = 0;
|
||||||
|
HashMap<String, GDScriptFunction::Profile::NativeProfile>::ConstIterator nat_calls = elem->self()->profile.native_calls.begin();
|
||||||
|
while (nat_calls) {
|
||||||
|
p_info_arr[current].call_count = nat_calls->value.call_count;
|
||||||
|
p_info_arr[current].total_time = nat_calls->value.total_time;
|
||||||
|
p_info_arr[current].self_time = nat_calls->value.total_time;
|
||||||
|
p_info_arr[current].signature = nat_calls->value.signature;
|
||||||
|
nat_time += nat_calls->value.total_time;
|
||||||
|
current++;
|
||||||
|
++nat_calls;
|
||||||
|
}
|
||||||
|
p_info_arr[last_non_internal].internal_time = nat_time;
|
||||||
|
elem = elem->next();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2264,17 +2288,33 @@ int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
MutexLock lock(this->mutex);
|
MutexLock lock(this->mutex);
|
||||||
|
|
||||||
|
profiling_collate_native_call_data(false);
|
||||||
SelfList<GDScriptFunction> *elem = function_list.first();
|
SelfList<GDScriptFunction> *elem = function_list.first();
|
||||||
while (elem) {
|
while (elem) {
|
||||||
if (current >= p_info_max) {
|
if (current >= p_info_max) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (elem->self()->profile.last_frame_call_count > 0) {
|
if (elem->self()->profile.last_frame_call_count > 0) {
|
||||||
|
int last_non_internal = current;
|
||||||
p_info_arr[current].call_count = elem->self()->profile.last_frame_call_count;
|
p_info_arr[current].call_count = elem->self()->profile.last_frame_call_count;
|
||||||
p_info_arr[current].self_time = elem->self()->profile.last_frame_self_time;
|
p_info_arr[current].self_time = elem->self()->profile.last_frame_self_time;
|
||||||
p_info_arr[current].total_time = elem->self()->profile.last_frame_total_time;
|
p_info_arr[current].total_time = elem->self()->profile.last_frame_total_time;
|
||||||
p_info_arr[current].signature = elem->self()->profile.signature;
|
p_info_arr[current].signature = elem->self()->profile.signature;
|
||||||
current++;
|
current++;
|
||||||
|
|
||||||
|
int nat_time = 0;
|
||||||
|
HashMap<String, GDScriptFunction::Profile::NativeProfile>::ConstIterator nat_calls = elem->self()->profile.last_native_calls.begin();
|
||||||
|
while (nat_calls) {
|
||||||
|
p_info_arr[current].call_count = nat_calls->value.call_count;
|
||||||
|
p_info_arr[current].total_time = nat_calls->value.total_time;
|
||||||
|
p_info_arr[current].self_time = nat_calls->value.total_time;
|
||||||
|
p_info_arr[current].internal_time = nat_calls->value.total_time;
|
||||||
|
p_info_arr[current].signature = nat_calls->value.signature;
|
||||||
|
nat_time += nat_calls->value.total_time;
|
||||||
|
current++;
|
||||||
|
++nat_calls;
|
||||||
|
}
|
||||||
|
p_info_arr[last_non_internal].internal_time = nat_time;
|
||||||
}
|
}
|
||||||
elem = elem->next();
|
elem = elem->next();
|
||||||
}
|
}
|
||||||
|
@ -2283,6 +2323,33 @@ int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GDScriptLanguage::profiling_collate_native_call_data(bool p_accumulated) {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
// The same native call can be called from multiple functions, so join them together here.
|
||||||
|
// Only use the name of the function (ie signature.split[2]).
|
||||||
|
HashMap<String, GDScriptFunction::Profile::NativeProfile *> seen_nat_calls;
|
||||||
|
SelfList<GDScriptFunction> *elem = function_list.first();
|
||||||
|
while (elem) {
|
||||||
|
HashMap<String, GDScriptFunction::Profile::NativeProfile> *nat_calls = p_accumulated ? &elem->self()->profile.native_calls : &elem->self()->profile.last_native_calls;
|
||||||
|
HashMap<String, GDScriptFunction::Profile::NativeProfile>::Iterator it = nat_calls->begin();
|
||||||
|
|
||||||
|
while (it != nat_calls->end()) {
|
||||||
|
Vector<String> sig = it->value.signature.split("::");
|
||||||
|
HashMap<String, GDScriptFunction::Profile::NativeProfile *>::ConstIterator already_found = seen_nat_calls.find(sig[2]);
|
||||||
|
if (already_found) {
|
||||||
|
already_found->value->total_time += it->value.total_time;
|
||||||
|
already_found->value->call_count += it->value.call_count;
|
||||||
|
elem->self()->profile.last_native_calls.remove(it);
|
||||||
|
} else {
|
||||||
|
seen_nat_calls.insert(sig[2], &it->value);
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
elem = elem->next();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
struct GDScriptDepSort {
|
struct GDScriptDepSort {
|
||||||
//must support sorting so inheritance works properly (parent must be reloaded first)
|
//must support sorting so inheritance works properly (parent must be reloaded first)
|
||||||
bool operator()(const Ref<GDScript> &A, const Ref<GDScript> &B) const {
|
bool operator()(const Ref<GDScript> &A, const Ref<GDScript> &B) const {
|
||||||
|
@ -2482,9 +2549,11 @@ void GDScriptLanguage::frame() {
|
||||||
elem->self()->profile.last_frame_call_count = elem->self()->profile.frame_call_count.get();
|
elem->self()->profile.last_frame_call_count = elem->self()->profile.frame_call_count.get();
|
||||||
elem->self()->profile.last_frame_self_time = elem->self()->profile.frame_self_time.get();
|
elem->self()->profile.last_frame_self_time = elem->self()->profile.frame_self_time.get();
|
||||||
elem->self()->profile.last_frame_total_time = elem->self()->profile.frame_total_time.get();
|
elem->self()->profile.last_frame_total_time = elem->self()->profile.frame_total_time.get();
|
||||||
|
elem->self()->profile.last_native_calls = elem->self()->profile.native_calls;
|
||||||
elem->self()->profile.frame_call_count.set(0);
|
elem->self()->profile.frame_call_count.set(0);
|
||||||
elem->self()->profile.frame_self_time.set(0);
|
elem->self()->profile.frame_self_time.set(0);
|
||||||
elem->self()->profile.frame_total_time.set(0);
|
elem->self()->profile.frame_total_time.set(0);
|
||||||
|
elem->self()->profile.native_calls.clear();
|
||||||
elem = elem->next();
|
elem = elem->next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -439,6 +439,7 @@ class GDScriptLanguage : public ScriptLanguage {
|
||||||
|
|
||||||
SelfList<GDScriptFunction>::List function_list;
|
SelfList<GDScriptFunction>::List function_list;
|
||||||
bool profiling;
|
bool profiling;
|
||||||
|
bool profile_native_calls;
|
||||||
uint64_t script_frame_time;
|
uint64_t script_frame_time;
|
||||||
|
|
||||||
HashMap<String, ObjectID> orphan_subclasses;
|
HashMap<String, ObjectID> orphan_subclasses;
|
||||||
|
@ -590,6 +591,8 @@ public:
|
||||||
|
|
||||||
virtual void profiling_start() override;
|
virtual void profiling_start() override;
|
||||||
virtual void profiling_stop() override;
|
virtual void profiling_stop() override;
|
||||||
|
virtual void profiling_set_save_native_calls(bool p_enable) override;
|
||||||
|
void profiling_collate_native_call_data(bool p_accumulated);
|
||||||
|
|
||||||
virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) override;
|
virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) override;
|
||||||
virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) override;
|
virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) override;
|
||||||
|
|
|
@ -474,6 +474,13 @@ private:
|
||||||
uint64_t last_frame_call_count = 0;
|
uint64_t last_frame_call_count = 0;
|
||||||
uint64_t last_frame_self_time = 0;
|
uint64_t last_frame_self_time = 0;
|
||||||
uint64_t last_frame_total_time = 0;
|
uint64_t last_frame_total_time = 0;
|
||||||
|
typedef struct NativeProfile {
|
||||||
|
uint64_t call_count;
|
||||||
|
uint64_t total_time;
|
||||||
|
String signature;
|
||||||
|
} NativeProfile;
|
||||||
|
HashMap<String, NativeProfile> native_calls;
|
||||||
|
HashMap<String, NativeProfile> last_native_calls;
|
||||||
} profile;
|
} profile;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -514,6 +521,7 @@ public:
|
||||||
void debug_get_stack_member_state(int p_line, List<Pair<StringName, int>> *r_stackvars) const;
|
void debug_get_stack_member_state(int p_line, List<Pair<StringName, int>> *r_stackvars) const;
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
void _profile_native_call(uint64_t p_t_taken, const String &p_function_name, const String &p_instance_class_name = String());
|
||||||
void disassemble(const Vector<String> &p_code_lines) const;
|
void disassemble(const Vector<String> &p_code_lines) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,18 @@
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
|
||||||
|
static bool _profile_count_as_native(const Object *p_base_obj, const StringName &p_methodname) {
|
||||||
|
if (!p_base_obj) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
StringName cname = p_base_obj->get_class_name();
|
||||||
|
if ((p_methodname == "new" && cname == "GDScript") || p_methodname == "call") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return ClassDB::class_exists(cname) && ClassDB::has_method(cname, p_methodname, false);
|
||||||
|
}
|
||||||
|
|
||||||
static String _get_element_type(Variant::Type builtin_type, const StringName &native_type, const Ref<Script> &script_type) {
|
static String _get_element_type(Variant::Type builtin_type, const StringName &native_type, const Ref<Script> &script_type) {
|
||||||
if (script_type.is_valid() && script_type->is_valid()) {
|
if (script_type.is_valid() && script_type->is_valid()) {
|
||||||
return GDScript::debug_get_script_name(script_type);
|
return GDScript::debug_get_script_name(script_type);
|
||||||
|
@ -84,6 +96,18 @@ static String _get_var_type(const Variant *p_var) {
|
||||||
|
|
||||||
return basestr;
|
return basestr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GDScriptFunction::_profile_native_call(uint64_t p_t_taken, const String &p_func_name, const String &p_instance_class_name) {
|
||||||
|
HashMap<String, Profile::NativeProfile>::Iterator inner_prof = profile.native_calls.find(p_func_name);
|
||||||
|
if (inner_prof) {
|
||||||
|
inner_prof->value.call_count += 1;
|
||||||
|
} else {
|
||||||
|
String sig = vformat("%s::0::%s%s%s", get_script()->get_script_path(), p_instance_class_name, p_instance_class_name.is_empty() ? "" : ".", p_func_name);
|
||||||
|
inner_prof = profile.native_calls.insert(p_func_name, Profile::NativeProfile{ 1, 0, sig });
|
||||||
|
}
|
||||||
|
inner_prof->value.total_time += p_t_taken;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // DEBUG_ENABLED
|
#endif // DEBUG_ENABLED
|
||||||
|
|
||||||
Variant GDScriptFunction::_get_default_variant_for_data_type(const GDScriptDataType &p_data_type) {
|
Variant GDScriptFunction::_get_default_variant_for_data_type(const GDScriptDataType &p_data_type) {
|
||||||
|
@ -631,9 +655,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
}
|
}
|
||||||
bool exit_ok = false;
|
bool exit_ok = false;
|
||||||
bool awaited = false;
|
bool awaited = false;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
int variant_address_limits[ADDR_TYPE_MAX] = { _stack_size, _constant_count, p_instance ? p_instance->members.size() : 0 };
|
int variant_address_limits[ADDR_TYPE_MAX] = { _stack_size, _constant_count, p_instance ? p_instance->members.size() : 0 };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1661,16 +1682,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
if (GDScriptLanguage::get_singleton()->profiling) {
|
if (GDScriptLanguage::get_singleton()->profiling) {
|
||||||
call_time = OS::get_singleton()->get_ticks_usec();
|
call_time = OS::get_singleton()->get_ticks_usec();
|
||||||
}
|
}
|
||||||
|
Variant::Type base_type = base->get_type();
|
||||||
|
Object *base_obj = base->get_validated_object();
|
||||||
|
StringName base_class = base_obj ? base_obj->get_class_name() : StringName();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Callable::CallError err;
|
Callable::CallError err;
|
||||||
if (call_ret) {
|
if (call_ret) {
|
||||||
GET_INSTRUCTION_ARG(ret, argc + 1);
|
GET_INSTRUCTION_ARG(ret, argc + 1);
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
Variant::Type base_type = base->get_type();
|
|
||||||
Object *base_obj = base->get_validated_object();
|
|
||||||
StringName base_class = base_obj ? base_obj->get_class_name() : StringName();
|
|
||||||
#endif
|
|
||||||
base->callp(*methodname, (const Variant **)argptrs, argc, *ret, err);
|
base->callp(*methodname, (const Variant **)argptrs, argc, *ret, err);
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (ret->get_type() == Variant::NIL) {
|
if (ret->get_type() == Variant::NIL) {
|
||||||
|
@ -1704,8 +1723,13 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
base->callp(*methodname, (const Variant **)argptrs, argc, ret, err);
|
base->callp(*methodname, (const Variant **)argptrs, argc, ret, err);
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
|
||||||
if (GDScriptLanguage::get_singleton()->profiling) {
|
if (GDScriptLanguage::get_singleton()->profiling) {
|
||||||
function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
|
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
|
||||||
|
if (GDScriptLanguage::get_singleton()->profile_native_calls && _profile_count_as_native(base_obj, *methodname)) {
|
||||||
|
_profile_native_call(t_taken, *methodname, base_class);
|
||||||
|
}
|
||||||
|
function_call_time += t_taken;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err.error != Callable::CallError::CALL_OK) {
|
if (err.error != Callable::CallError::CALL_OK) {
|
||||||
|
@ -1782,8 +1806,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
uint64_t call_time = 0;
|
uint64_t call_time = 0;
|
||||||
|
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
|
||||||
if (GDScriptLanguage::get_singleton()->profiling) {
|
|
||||||
call_time = OS::get_singleton()->get_ticks_usec();
|
call_time = OS::get_singleton()->get_ticks_usec();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1797,8 +1820,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (GDScriptLanguage::get_singleton()->profiling) {
|
|
||||||
function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
|
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
|
||||||
|
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
|
||||||
|
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
|
||||||
|
function_call_time += t_taken;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err.error != Callable::CallError::CALL_OK) {
|
if (err.error != Callable::CallError::CALL_OK) {
|
||||||
|
@ -1851,22 +1877,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
|
|
||||||
const Variant **argptrs = const_cast<const Variant **>(instruction_args);
|
const Variant **argptrs = const_cast<const Variant **>(instruction_args);
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
uint64_t call_time = 0;
|
|
||||||
|
|
||||||
if (GDScriptLanguage::get_singleton()->profiling) {
|
|
||||||
call_time = OS::get_singleton()->get_ticks_usec();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Callable::CallError err;
|
Callable::CallError err;
|
||||||
Variant::call_static(builtin_type, *methodname, argptrs, argc, *ret, err);
|
Variant::call_static(builtin_type, *methodname, argptrs, argc, *ret, err);
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (GDScriptLanguage::get_singleton()->profiling) {
|
|
||||||
function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err.error != Callable::CallError::CALL_OK) {
|
if (err.error != Callable::CallError::CALL_OK) {
|
||||||
err_text = _get_call_error(err, "static function '" + methodname->operator String() + "' in type '" + Variant::get_type_name(builtin_type) + "'", argptrs);
|
err_text = _get_call_error(err, "static function '" + methodname->operator String() + "' in type '" + Variant::get_type_name(builtin_type) + "'", argptrs);
|
||||||
OPCODE_BREAK;
|
OPCODE_BREAK;
|
||||||
|
@ -1895,8 +1909,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
uint64_t call_time = 0;
|
uint64_t call_time = 0;
|
||||||
|
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
|
||||||
if (GDScriptLanguage::get_singleton()->profiling) {
|
|
||||||
call_time = OS::get_singleton()->get_ticks_usec();
|
call_time = OS::get_singleton()->get_ticks_usec();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1905,15 +1918,17 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
*ret = method->call(nullptr, argptrs, argc, err);
|
*ret = method->call(nullptr, argptrs, argc, err);
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (GDScriptLanguage::get_singleton()->profiling) {
|
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
|
||||||
function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
|
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
|
||||||
|
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
|
||||||
|
function_call_time += t_taken;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (err.error != Callable::CallError::CALL_OK) {
|
if (err.error != Callable::CallError::CALL_OK) {
|
||||||
err_text = _get_call_error(err, "static function '" + method->get_name().operator String() + "' in type '" + method->get_instance_class().operator String() + "'", argptrs);
|
err_text = _get_call_error(err, "static function '" + method->get_name().operator String() + "' in type '" + method->get_instance_class().operator String() + "'", argptrs);
|
||||||
OPCODE_BREAK;
|
OPCODE_BREAK;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
ip += 3;
|
ip += 3;
|
||||||
}
|
}
|
||||||
|
@ -1951,8 +1966,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
uint64_t call_time = 0;
|
uint64_t call_time = 0;
|
||||||
|
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
|
||||||
if (GDScriptLanguage::get_singleton()->profiling) {
|
|
||||||
call_time = OS::get_singleton()->get_ticks_usec();
|
call_time = OS::get_singleton()->get_ticks_usec();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1961,10 +1975,13 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
method->validated_call(base_obj, (const Variant **)argptrs, ret);
|
method->validated_call(base_obj, (const Variant **)argptrs, ret);
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (GDScriptLanguage::get_singleton()->profiling) {
|
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
|
||||||
function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
|
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
|
||||||
|
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
|
||||||
|
function_call_time += t_taken;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ip += 3;
|
ip += 3;
|
||||||
}
|
}
|
||||||
DISPATCH_OPCODE;
|
DISPATCH_OPCODE;
|
||||||
|
@ -1998,8 +2015,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
Variant **argptrs = instruction_args;
|
Variant **argptrs = instruction_args;
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
uint64_t call_time = 0;
|
uint64_t call_time = 0;
|
||||||
|
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
|
||||||
if (GDScriptLanguage::get_singleton()->profiling) {
|
|
||||||
call_time = OS::get_singleton()->get_ticks_usec();
|
call_time = OS::get_singleton()->get_ticks_usec();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2009,10 +2025,13 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
method->validated_call(base_obj, (const Variant **)argptrs, nullptr);
|
method->validated_call(base_obj, (const Variant **)argptrs, nullptr);
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (GDScriptLanguage::get_singleton()->profiling) {
|
if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
|
||||||
function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
|
uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
|
||||||
|
_profile_native_call(t_taken, method->get_name(), method->get_instance_class());
|
||||||
|
function_call_time += t_taken;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ip += 3;
|
ip += 3;
|
||||||
}
|
}
|
||||||
DISPATCH_OPCODE;
|
DISPATCH_OPCODE;
|
||||||
|
@ -2033,22 +2052,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
Variant::ValidatedBuiltInMethod method = _builtin_methods_ptr[_code_ptr[ip + 2]];
|
Variant::ValidatedBuiltInMethod method = _builtin_methods_ptr[_code_ptr[ip + 2]];
|
||||||
Variant **argptrs = instruction_args;
|
Variant **argptrs = instruction_args;
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
uint64_t call_time = 0;
|
|
||||||
if (GDScriptLanguage::get_singleton()->profiling) {
|
|
||||||
call_time = OS::get_singleton()->get_ticks_usec();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GET_INSTRUCTION_ARG(ret, argc + 1);
|
GET_INSTRUCTION_ARG(ret, argc + 1);
|
||||||
method(base, (const Variant **)argptrs, argc, ret);
|
method(base, (const Variant **)argptrs, argc, ret);
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
if (GDScriptLanguage::get_singleton()->profiling) {
|
|
||||||
function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ip += 3;
|
ip += 3;
|
||||||
}
|
}
|
||||||
DISPATCH_OPCODE;
|
DISPATCH_OPCODE;
|
||||||
|
|
|
@ -463,6 +463,7 @@ public:
|
||||||
/* PROFILING FUNCTIONS */
|
/* PROFILING FUNCTIONS */
|
||||||
/* TODO */ void profiling_start() override {}
|
/* TODO */ void profiling_start() override {}
|
||||||
/* TODO */ void profiling_stop() override {}
|
/* TODO */ void profiling_stop() override {}
|
||||||
|
/* TODO */ void profiling_set_save_native_calls(bool p_enable) override {}
|
||||||
/* TODO */ int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) override {
|
/* TODO */ int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,12 +108,13 @@ Array ServersDebugger::ServersProfilerFrame::serialize() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arr.push_back(script_functions.size() * 4);
|
arr.push_back(script_functions.size() * 5);
|
||||||
for (int i = 0; i < script_functions.size(); i++) {
|
for (int i = 0; i < script_functions.size(); i++) {
|
||||||
arr.push_back(script_functions[i].sig_id);
|
arr.push_back(script_functions[i].sig_id);
|
||||||
arr.push_back(script_functions[i].call_count);
|
arr.push_back(script_functions[i].call_count);
|
||||||
arr.push_back(script_functions[i].self_time);
|
arr.push_back(script_functions[i].self_time);
|
||||||
arr.push_back(script_functions[i].total_time);
|
arr.push_back(script_functions[i].total_time);
|
||||||
|
arr.push_back(script_functions[i].internal_time);
|
||||||
}
|
}
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
@ -149,14 +150,15 @@ bool ServersDebugger::ServersProfilerFrame::deserialize(const Array &p_arr) {
|
||||||
int func_size = p_arr[idx];
|
int func_size = p_arr[idx];
|
||||||
idx += 1;
|
idx += 1;
|
||||||
CHECK_SIZE(p_arr, idx + func_size, "ServersProfilerFrame");
|
CHECK_SIZE(p_arr, idx + func_size, "ServersProfilerFrame");
|
||||||
for (int i = 0; i < func_size / 4; i++) {
|
for (int i = 0; i < func_size / 5; i++) {
|
||||||
ScriptFunctionInfo fi;
|
ScriptFunctionInfo fi;
|
||||||
fi.sig_id = p_arr[idx];
|
fi.sig_id = p_arr[idx];
|
||||||
fi.call_count = p_arr[idx + 1];
|
fi.call_count = p_arr[idx + 1];
|
||||||
fi.self_time = p_arr[idx + 2];
|
fi.self_time = p_arr[idx + 2];
|
||||||
fi.total_time = p_arr[idx + 3];
|
fi.total_time = p_arr[idx + 3];
|
||||||
|
fi.internal_time = p_arr[idx + 4];
|
||||||
script_functions.push_back(fi);
|
script_functions.push_back(fi);
|
||||||
idx += 4;
|
idx += 5;
|
||||||
}
|
}
|
||||||
CHECK_END(p_arr, idx, "ServersProfilerFrame");
|
CHECK_END(p_arr, idx, "ServersProfilerFrame");
|
||||||
return true;
|
return true;
|
||||||
|
@ -210,8 +212,11 @@ public:
|
||||||
sig_map.clear();
|
sig_map.clear();
|
||||||
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
|
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
|
||||||
ScriptServer::get_language(i)->profiling_start();
|
ScriptServer::get_language(i)->profiling_start();
|
||||||
|
if (p_opts.size() == 2 && p_opts[1].get_type() == Variant::BOOL) {
|
||||||
|
ScriptServer::get_language(i)->profiling_set_save_native_calls(p_opts[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (p_opts.size() == 1 && p_opts[0].get_type() == Variant::INT) {
|
if (p_opts.size() > 0 && p_opts[0].get_type() == Variant::INT) {
|
||||||
max_frame_functions = MAX(0, int(p_opts[0]));
|
max_frame_functions = MAX(0, int(p_opts[0]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -265,6 +270,7 @@ public:
|
||||||
w[i].call_count = ptrs[i]->call_count;
|
w[i].call_count = ptrs[i]->call_count;
|
||||||
w[i].total_time = ptrs[i]->total_time / 1000000.0;
|
w[i].total_time = ptrs[i]->total_time / 1000000.0;
|
||||||
w[i].self_time = ptrs[i]->self_time / 1000000.0;
|
w[i].self_time = ptrs[i]->self_time / 1000000.0;
|
||||||
|
w[i].internal_time = ptrs[i]->internal_time / 1000000.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ public:
|
||||||
int call_count = 0;
|
int call_count = 0;
|
||||||
double self_time = 0;
|
double self_time = 0;
|
||||||
double total_time = 0;
|
double total_time = 0;
|
||||||
|
double internal_time = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Servers profiler
|
// Servers profiler
|
||||||
|
|
Loading…
Reference in a new issue