Merge pull request #64610 from reduz/startup-benchmark-support
This commit is contained in:
commit
1fbf7b1ba5
|
@ -33,7 +33,9 @@
|
||||||
#include "core/authors.gen.h"
|
#include "core/authors.gen.h"
|
||||||
#include "core/config/project_settings.h"
|
#include "core/config/project_settings.h"
|
||||||
#include "core/donors.gen.h"
|
#include "core/donors.gen.h"
|
||||||
|
#include "core/io/json.h"
|
||||||
#include "core/license.gen.h"
|
#include "core/license.gen.h"
|
||||||
|
#include "core/os/os.h"
|
||||||
#include "core/version.h"
|
#include "core/version.h"
|
||||||
|
|
||||||
void Engine::set_physics_ticks_per_second(int p_ips) {
|
void Engine::set_physics_ticks_per_second(int p_ips) {
|
||||||
|
@ -307,6 +309,43 @@ Engine::Engine() {
|
||||||
singleton = this;
|
singleton = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::startup_begin() {
|
||||||
|
startup_benchmark_total_from = OS::get_singleton()->get_ticks_usec();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::startup_benchmark_begin_measure(const String &p_what) {
|
||||||
|
startup_benchmark_section = p_what;
|
||||||
|
startup_benchmark_from = OS::get_singleton()->get_ticks_usec();
|
||||||
|
}
|
||||||
|
void Engine::startup_benchmark_end_measure() {
|
||||||
|
uint64_t total = OS::get_singleton()->get_ticks_usec() - startup_benchmark_from;
|
||||||
|
double total_f = double(total) / double(1000000);
|
||||||
|
|
||||||
|
startup_benchmark_json[startup_benchmark_section] = total_f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::startup_dump(const String &p_to_file) {
|
||||||
|
uint64_t total = OS::get_singleton()->get_ticks_usec() - startup_benchmark_total_from;
|
||||||
|
double total_f = double(total) / double(1000000);
|
||||||
|
startup_benchmark_json["total_time"] = total_f;
|
||||||
|
|
||||||
|
if (!p_to_file.is_empty()) {
|
||||||
|
Ref<FileAccess> f = FileAccess::open(p_to_file, FileAccess::WRITE);
|
||||||
|
if (f.is_valid()) {
|
||||||
|
Ref<JSON> json;
|
||||||
|
json.instantiate();
|
||||||
|
f->store_string(json->stringify(startup_benchmark_json, "\t", false, true));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
List<Variant> keys;
|
||||||
|
startup_benchmark_json.get_key_list(&keys);
|
||||||
|
print_line("STARTUP BENCHMARK:");
|
||||||
|
for (const Variant &K : keys) {
|
||||||
|
print_line("\t-", K, ": ", startup_benchmark_json[K], +" sec.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr, const StringName &p_class_name) :
|
Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr, const StringName &p_class_name) :
|
||||||
name(p_name),
|
name(p_name),
|
||||||
ptr(p_ptr),
|
ptr(p_ptr),
|
||||||
|
|
|
@ -79,6 +79,11 @@ private:
|
||||||
String write_movie_path;
|
String write_movie_path;
|
||||||
String shader_cache_path;
|
String shader_cache_path;
|
||||||
|
|
||||||
|
Dictionary startup_benchmark_json;
|
||||||
|
String startup_benchmark_section;
|
||||||
|
uint64_t startup_benchmark_from = 0;
|
||||||
|
uint64_t startup_benchmark_total_from = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Engine *get_singleton();
|
static Engine *get_singleton();
|
||||||
|
|
||||||
|
@ -151,6 +156,11 @@ public:
|
||||||
bool is_validation_layers_enabled() const;
|
bool is_validation_layers_enabled() const;
|
||||||
int32_t get_gpu_index() const;
|
int32_t get_gpu_index() const;
|
||||||
|
|
||||||
|
void startup_begin();
|
||||||
|
void startup_benchmark_begin_measure(const String &p_what);
|
||||||
|
void startup_benchmark_end_measure();
|
||||||
|
void startup_dump(const String &p_to_file);
|
||||||
|
|
||||||
Engine();
|
Engine();
|
||||||
virtual ~Engine() {}
|
virtual ~Engine() {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1192,11 +1192,6 @@ void EditorFileSystem::scan_changes() {
|
||||||
|
|
||||||
void EditorFileSystem::_notification(int p_what) {
|
void EditorFileSystem::_notification(int p_what) {
|
||||||
switch (p_what) {
|
switch (p_what) {
|
||||||
case NOTIFICATION_ENTER_TREE: {
|
|
||||||
call_deferred(SNAME("scan")); //this should happen after every editor node entered the tree
|
|
||||||
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NOTIFICATION_EXIT_TREE: {
|
case NOTIFICATION_EXIT_TREE: {
|
||||||
Thread &active_thread = thread.is_started() ? thread : thread_sources;
|
Thread &active_thread = thread.is_started() ? thread : thread_sources;
|
||||||
if (use_threads && active_thread.is_started()) {
|
if (use_threads && active_thread.is_started()) {
|
||||||
|
|
|
@ -661,6 +661,7 @@ void EditorNode::_notification(int p_what) {
|
||||||
|
|
||||||
command_palette->register_shortcuts_as_command();
|
command_palette->register_shortcuts_as_command();
|
||||||
|
|
||||||
|
MessageQueue::get_singleton()->push_callable(callable_mp(this, &EditorNode::_begin_first_scan));
|
||||||
/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
|
/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -1043,6 +1044,8 @@ void EditorNode::_sources_changed(bool p_exist) {
|
||||||
if (waiting_for_first_scan) {
|
if (waiting_for_first_scan) {
|
||||||
waiting_for_first_scan = false;
|
waiting_for_first_scan = false;
|
||||||
|
|
||||||
|
Engine::get_singleton()->startup_benchmark_end_measure(); // editor_scan_and_reimport
|
||||||
|
|
||||||
// Reload the global shader variables, but this time
|
// Reload the global shader variables, but this time
|
||||||
// loading textures, as they are now properly imported.
|
// loading textures, as they are now properly imported.
|
||||||
RenderingServer::get_singleton()->global_shader_uniforms_load_settings(true);
|
RenderingServer::get_singleton()->global_shader_uniforms_load_settings(true);
|
||||||
|
@ -1055,8 +1058,16 @@ void EditorNode::_sources_changed(bool p_exist) {
|
||||||
_load_docks();
|
_load_docks();
|
||||||
|
|
||||||
if (!defer_load_scene.is_empty()) {
|
if (!defer_load_scene.is_empty()) {
|
||||||
|
Engine::get_singleton()->startup_benchmark_begin_measure("editor_load_scene");
|
||||||
load_scene(defer_load_scene);
|
load_scene(defer_load_scene);
|
||||||
defer_load_scene = "";
|
defer_load_scene = "";
|
||||||
|
Engine::get_singleton()->startup_benchmark_end_measure();
|
||||||
|
|
||||||
|
if (use_startup_benchmark) {
|
||||||
|
Engine::get_singleton()->startup_dump(startup_benchmark_file);
|
||||||
|
startup_benchmark_file = String();
|
||||||
|
use_startup_benchmark = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4318,6 +4329,15 @@ void EditorNode::_editor_file_dialog_unregister(EditorFileDialog *p_dialog) {
|
||||||
|
|
||||||
Vector<EditorNodeInitCallback> EditorNode::_init_callbacks;
|
Vector<EditorNodeInitCallback> EditorNode::_init_callbacks;
|
||||||
|
|
||||||
|
void EditorNode::_begin_first_scan() {
|
||||||
|
Engine::get_singleton()->startup_benchmark_begin_measure("editor_scan_and_import");
|
||||||
|
EditorFileSystem::get_singleton()->scan();
|
||||||
|
}
|
||||||
|
void EditorNode::set_use_startup_benchmark(bool p_use_startup_benchmark, const String &p_startup_benchmark_file) {
|
||||||
|
use_startup_benchmark = p_use_startup_benchmark;
|
||||||
|
startup_benchmark_file = p_startup_benchmark_file;
|
||||||
|
}
|
||||||
|
|
||||||
Error EditorNode::export_preset(const String &p_preset, const String &p_path, bool p_debug, bool p_pack_only) {
|
Error EditorNode::export_preset(const String &p_preset, const String &p_path, bool p_debug, bool p_pack_only) {
|
||||||
export_defer.preset = p_preset;
|
export_defer.preset = p_preset;
|
||||||
export_defer.path = p_path;
|
export_defer.path = p_path;
|
||||||
|
|
|
@ -682,6 +682,10 @@ private:
|
||||||
void _bottom_panel_switch(bool p_enable, int p_idx);
|
void _bottom_panel_switch(bool p_enable, int p_idx);
|
||||||
void _bottom_panel_raise_toggled(bool);
|
void _bottom_panel_raise_toggled(bool);
|
||||||
|
|
||||||
|
void _begin_first_scan();
|
||||||
|
bool use_startup_benchmark = false;
|
||||||
|
String startup_benchmark_file;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class FileSystemDock;
|
friend class FileSystemDock;
|
||||||
|
|
||||||
|
@ -816,6 +820,7 @@ public:
|
||||||
|
|
||||||
void _copy_warning(const String &p_str);
|
void _copy_warning(const String &p_str);
|
||||||
|
|
||||||
|
void set_use_startup_benchmark(bool p_use_startup_benchmark, const String &p_startup_benchmark_file);
|
||||||
Error export_preset(const String &p_preset, const String &p_path, bool p_debug, bool p_pack_only);
|
Error export_preset(const String &p_preset, const String &p_path, bool p_debug, bool p_pack_only);
|
||||||
|
|
||||||
Control *get_gui_base() { return gui_base; }
|
Control *get_gui_base() { return gui_base; }
|
||||||
|
|
|
@ -154,6 +154,8 @@ static OS::ProcessID editor_pid = 0;
|
||||||
static bool auto_build_solutions = false;
|
static bool auto_build_solutions = false;
|
||||||
static String debug_server_uri;
|
static String debug_server_uri;
|
||||||
#endif
|
#endif
|
||||||
|
bool use_startup_benchmark = false;
|
||||||
|
String startup_benchmark_file;
|
||||||
|
|
||||||
// Display
|
// Display
|
||||||
|
|
||||||
|
@ -386,6 +388,8 @@ void Main::print_help(const char *p_binary) {
|
||||||
OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n");
|
OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n");
|
||||||
OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n");
|
OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n");
|
||||||
OS::get_singleton()->print(" --dump-extension-api Generate JSON dump of the Godot API for GDExtension bindings named 'extension_api.json' in the current folder.\n");
|
OS::get_singleton()->print(" --dump-extension-api Generate JSON dump of the Godot API for GDExtension bindings named 'extension_api.json' in the current folder.\n");
|
||||||
|
OS::get_singleton()->print(" --startup-benchmark Benchmark the startup time and print it to console.\n");
|
||||||
|
OS::get_singleton()->print(" --startup-benchmark-file <path> Benchmark the startup time and save it to a given file in JSON format.\n");
|
||||||
#ifdef TESTS_ENABLED
|
#ifdef TESTS_ENABLED
|
||||||
OS::get_singleton()->print(" --test [--help] Run unit tests. Use --test --help for more information.\n");
|
OS::get_singleton()->print(" --test [--help] Run unit tests. Use --test --help for more information.\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -594,6 +598,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
||||||
engine = memnew(Engine);
|
engine = memnew(Engine);
|
||||||
|
|
||||||
MAIN_PRINT("Main: Initialize CORE");
|
MAIN_PRINT("Main: Initialize CORE");
|
||||||
|
engine->startup_begin();
|
||||||
|
engine->startup_benchmark_begin_measure("core");
|
||||||
|
|
||||||
register_core_types();
|
register_core_types();
|
||||||
register_core_driver_types();
|
register_core_driver_types();
|
||||||
|
@ -1208,6 +1214,19 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
||||||
OS::get_singleton()->print("Missing --xr-mode argument, aborting.\n");
|
OS::get_singleton()->print("Missing --xr-mode argument, aborting.\n");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (I->get() == "--startup-benchmark") {
|
||||||
|
use_startup_benchmark = true;
|
||||||
|
} else if (I->get() == "--startup-benchmark-file") {
|
||||||
|
if (I->next()) {
|
||||||
|
use_startup_benchmark = true;
|
||||||
|
startup_benchmark_file = I->next()->get();
|
||||||
|
N = I->next()->next();
|
||||||
|
} else {
|
||||||
|
OS::get_singleton()->print("Missing <path> argument for --startup-benchmark-file <path>.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (I->get() == "--") {
|
} else if (I->get() == "--") {
|
||||||
adding_user_args = true;
|
adding_user_args = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1624,6 +1643,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
||||||
|
|
||||||
message_queue = memnew(MessageQueue);
|
message_queue = memnew(MessageQueue);
|
||||||
|
|
||||||
|
engine->startup_benchmark_end_measure(); // core
|
||||||
|
|
||||||
if (p_second_phase) {
|
if (p_second_phase) {
|
||||||
return setup2();
|
return setup2();
|
||||||
}
|
}
|
||||||
|
@ -1690,6 +1711,8 @@ error:
|
||||||
}
|
}
|
||||||
|
|
||||||
Error Main::setup2(Thread::ID p_main_tid_override) {
|
Error Main::setup2(Thread::ID p_main_tid_override) {
|
||||||
|
engine->startup_benchmark_begin_measure("servers");
|
||||||
|
|
||||||
tsman = memnew(TextServerManager);
|
tsman = memnew(TextServerManager);
|
||||||
|
|
||||||
if (tsman) {
|
if (tsman) {
|
||||||
|
@ -2047,8 +2070,12 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
||||||
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "TextServer: Unable to create TextServer interface.");
|
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "TextServer: Unable to create TextServer interface.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
engine->startup_benchmark_end_measure(); // servers
|
||||||
|
|
||||||
MAIN_PRINT("Main: Load Scene Types");
|
MAIN_PRINT("Main: Load Scene Types");
|
||||||
|
|
||||||
|
engine->startup_benchmark_begin_measure("scene");
|
||||||
|
|
||||||
register_scene_types();
|
register_scene_types();
|
||||||
register_driver_types();
|
register_driver_types();
|
||||||
|
|
||||||
|
@ -2124,6 +2151,8 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
||||||
print_verbose("EDITOR API HASH: " + uitos(ClassDB::get_api_hash(ClassDB::API_EDITOR)));
|
print_verbose("EDITOR API HASH: " + uitos(ClassDB::get_api_hash(ClassDB::API_EDITOR)));
|
||||||
MAIN_PRINT("Main: Done");
|
MAIN_PRINT("Main: Done");
|
||||||
|
|
||||||
|
engine->startup_benchmark_end_measure(); // scene
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2450,6 +2479,7 @@ bool Main::start() {
|
||||||
if (!project_manager && !editor) { // game
|
if (!project_manager && !editor) { // game
|
||||||
if (!game_path.is_empty() || !script.is_empty()) {
|
if (!game_path.is_empty() || !script.is_empty()) {
|
||||||
//autoload
|
//autoload
|
||||||
|
Engine::get_singleton()->startup_benchmark_begin_measure("load_autoloads");
|
||||||
HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
|
HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
|
||||||
|
|
||||||
//first pass, add the constants so they exist before any script is loaded
|
//first pass, add the constants so they exist before any script is loaded
|
||||||
|
@ -2504,12 +2534,14 @@ bool Main::start() {
|
||||||
for (Node *E : to_add) {
|
for (Node *E : to_add) {
|
||||||
sml->get_root()->add_child(E);
|
sml->get_root()->add_child(E);
|
||||||
}
|
}
|
||||||
|
Engine::get_singleton()->startup_benchmark_end_measure(); // load autoloads
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
EditorNode *editor_node = nullptr;
|
EditorNode *editor_node = nullptr;
|
||||||
if (editor) {
|
if (editor) {
|
||||||
|
Engine::get_singleton()->startup_benchmark_begin_measure("editor");
|
||||||
editor_node = memnew(EditorNode);
|
editor_node = memnew(EditorNode);
|
||||||
sml->get_root()->add_child(editor_node);
|
sml->get_root()->add_child(editor_node);
|
||||||
|
|
||||||
|
@ -2517,6 +2549,13 @@ bool Main::start() {
|
||||||
editor_node->export_preset(_export_preset, positional_arg, export_debug, export_pack_only);
|
editor_node->export_preset(_export_preset, positional_arg, export_debug, export_pack_only);
|
||||||
game_path = ""; // Do not load anything.
|
game_path = ""; // Do not load anything.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Engine::get_singleton()->startup_benchmark_end_measure();
|
||||||
|
|
||||||
|
editor_node->set_use_startup_benchmark(use_startup_benchmark, startup_benchmark_file);
|
||||||
|
// Editor takes over
|
||||||
|
use_startup_benchmark = false;
|
||||||
|
startup_benchmark_file = String();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2681,6 +2720,8 @@ bool Main::start() {
|
||||||
|
|
||||||
if (!project_manager && !editor) { // game
|
if (!project_manager && !editor) { // game
|
||||||
|
|
||||||
|
Engine::get_singleton()->startup_benchmark_begin_measure("game_load");
|
||||||
|
|
||||||
// Load SSL Certificates from Project Settings (or builtin).
|
// Load SSL Certificates from Project Settings (or builtin).
|
||||||
Crypto::load_default_certificates(GLOBAL_DEF("network/ssl/certificate_bundle_override", ""));
|
Crypto::load_default_certificates(GLOBAL_DEF("network/ssl/certificate_bundle_override", ""));
|
||||||
|
|
||||||
|
@ -2720,16 +2761,20 @@ bool Main::start() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Engine::get_singleton()->startup_benchmark_end_measure(); // game_load
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
if (project_manager) {
|
if (project_manager) {
|
||||||
|
Engine::get_singleton()->startup_benchmark_begin_measure("project_manager");
|
||||||
Engine::get_singleton()->set_editor_hint(true);
|
Engine::get_singleton()->set_editor_hint(true);
|
||||||
ProjectManager *pmanager = memnew(ProjectManager);
|
ProjectManager *pmanager = memnew(ProjectManager);
|
||||||
ProgressDialog *progress_dialog = memnew(ProgressDialog);
|
ProgressDialog *progress_dialog = memnew(ProgressDialog);
|
||||||
pmanager->add_child(progress_dialog);
|
pmanager->add_child(progress_dialog);
|
||||||
sml->get_root()->add_child(pmanager);
|
sml->get_root()->add_child(pmanager);
|
||||||
DisplayServer::get_singleton()->set_context(DisplayServer::CONTEXT_PROJECTMAN);
|
DisplayServer::get_singleton()->set_context(DisplayServer::CONTEXT_PROJECTMAN);
|
||||||
|
Engine::get_singleton()->startup_benchmark_end_measure();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (project_manager || editor) {
|
if (project_manager || editor) {
|
||||||
|
@ -2759,6 +2804,11 @@ bool Main::start() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (use_startup_benchmark) {
|
||||||
|
Engine::get_singleton()->startup_dump(startup_benchmark_file);
|
||||||
|
startup_benchmark_file = String();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue