فهرست منبع

Implemented profiling functions for NativeScript

Marcelo Fernandez 7 سال پیش
والد
کامیت
a323b7a1ba

+ 8 - 0
modules/gdnative/gdnative_api.json

@@ -5876,6 +5876,14 @@
               ["int", "p_idx"],
 	      ["godot_object *", "p_object"]
             ]
+          },
+          {
+            "name": "godot_nativescript_profiling_add_data",
+            "return_type": "void",
+            "arguments": [
+              ["const char *", "p_signature"],
+              ["uint64_t", "p_line"]
+            ]
           }
 	]
       },

+ 2 - 0
modules/gdnative/include/nativescript/godot_nativescript.h

@@ -238,6 +238,8 @@ void GDAPI godot_nativescript_unregister_instance_binding_data_functions(int p_i
 
 void GDAPI *godot_nativescript_get_instance_binding_data(int p_idx, godot_object *p_object);
 
+void GDAPI godot_nativescript_profiling_add_data(const char *p_signature, uint64_t p_time);
+
 #ifdef __cplusplus
 }
 #endif

+ 4 - 0
modules/gdnative/nativescript/godot_nativescript.cpp

@@ -365,6 +365,10 @@ void GDAPI *godot_nativescript_get_instance_binding_data(int p_idx, godot_object
 	return NativeScriptLanguage::get_singleton()->get_instance_binding_data(p_idx, (Object *)p_object);
 }
 
+void GDAPI godot_nativescript_profiling_add_data(const char *p_signature, uint64_t p_time) {
+	NativeScriptLanguage::get_singleton()->profiling_add_data(StringName(p_signature), p_time);
+}
+
 #ifdef __cplusplus
 }
 #endif

+ 110 - 0
modules/gdnative/nativescript/nativescript.cpp

@@ -1010,6 +1010,10 @@ NativeScriptLanguage::NativeScriptLanguage() {
 	has_objects_to_register = false;
 	mutex = Mutex::create();
 #endif
+
+#ifdef DEBUG_ENABLED
+	profiling = false;
+#endif
 }
 
 NativeScriptLanguage::~NativeScriptLanguage() {
@@ -1152,17 +1156,105 @@ void NativeScriptLanguage::get_public_constants(List<Pair<String, Variant> > *p_
 }
 
 void NativeScriptLanguage::profiling_start() {
+#ifdef DEBUG_ENABLED
+#ifndef NO_THREADS
+	MutexLock lock(mutex);
+#endif
+
+	profile_data.clear();
+	profiling = true;
+#endif
 }
 
 void NativeScriptLanguage::profiling_stop() {
+#ifdef DEBUG_ENABLED
+#ifndef NO_THREADS
+	MutexLock lock(mutex);
+#endif
+
+	profiling = false;
+#endif
 }
 
 int NativeScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) {
+#ifdef DEBUG_ENABLED
+#ifndef NO_THREADS
+	MutexLock lock(mutex);
+#endif
+	int current = 0;
+
+	for (Map<StringName, ProfileData>::Element *d = profile_data.front(); d; d = d->next()) {
+		if (current >= p_info_max)
+			break;
+
+		p_info_arr[current].call_count = d->get().call_count;
+		p_info_arr[current].self_time = d->get().self_time;
+		p_info_arr[current].total_time = d->get().total_time;
+		p_info_arr[current].signature = d->get().signature;
+		current++;
+	}
+
+	return current;
+#else
 	return 0;
+#endif
 }
 
 int NativeScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) {
+#ifdef DEBUG_ENABLED
+#ifndef NO_THREADS
+	MutexLock lock(mutex);
+#endif
+	int current = 0;
+
+	for (Map<StringName, ProfileData>::Element *d = profile_data.front(); d; d = d->next()) {
+		if (current >= p_info_max)
+			break;
+
+		if (d->get().last_frame_call_count) {
+			p_info_arr[current].call_count = d->get().last_frame_call_count;
+			p_info_arr[current].self_time = d->get().last_frame_self_time;
+			p_info_arr[current].total_time = d->get().last_frame_total_time;
+			p_info_arr[current].signature = d->get().signature;
+			current++;
+		}
+	}
+
+	return current;
+#else
 	return 0;
+#endif
+}
+
+void NativeScriptLanguage::profiling_add_data(StringName p_signature, uint64_t p_time) {
+#ifdef DEBUG_ENABLED
+#ifndef NO_THREADS
+	MutexLock lock(mutex);
+#endif
+
+	Map<StringName, ProfileData>::Element *d = profile_data.find(p_signature);
+	if (d) {
+		d->get().call_count += 1;
+		d->get().total_time += p_time;
+		d->get().frame_call_count += 1;
+		d->get().frame_total_time += p_time;
+	} else {
+		ProfileData data;
+
+		data.signature = p_signature;
+		data.call_count = 1;
+		data.self_time = 0;
+		data.total_time = p_time;
+		data.frame_call_count = 1;
+		data.frame_self_time = 0;
+		data.frame_total_time = p_time;
+		data.last_frame_call_count = 0;
+		data.last_frame_self_time = 0;
+		data.last_frame_total_time = 0;
+
+		profile_data.insert(p_signature, data);
+	}
+#endif
 }
 
 int NativeScriptLanguage::register_binding_functions(godot_instance_binding_functions p_binding_functions) {
@@ -1405,6 +1497,24 @@ void NativeScriptLanguage::frame() {
 		has_objects_to_register = false;
 	}
 #endif
+
+#ifdef DEBUG_ENABLED
+	{
+#ifndef NO_THREADS
+		MutexLock lock(mutex);
+#endif
+
+		for (Map<StringName, ProfileData>::Element *d = profile_data.front(); d; d = d->next()) {
+			d->get().last_frame_call_count = d->get().frame_call_count;
+			d->get().last_frame_self_time = d->get().frame_self_time;
+			d->get().last_frame_total_time = d->get().frame_total_time;
+			d->get().frame_call_count = 0;
+			d->get().frame_self_time = 0;
+			d->get().frame_total_time = 0;
+		}
+	}
+#endif
+
 	call_libraries_cb(_frame_call_name);
 }
 

+ 18 - 0
modules/gdnative/nativescript/nativescript.h

@@ -254,6 +254,22 @@ private:
 
 	Map<int, HashMap<StringName, const void *> > global_type_tags;
 
+	struct ProfileData {
+		StringName signature;
+		uint64_t call_count;
+		uint64_t self_time;
+		uint64_t total_time;
+		uint64_t frame_call_count;
+		uint64_t frame_self_time;
+		uint64_t frame_total_time;
+		uint64_t last_frame_call_count;
+		uint64_t last_frame_self_time;
+		uint64_t last_frame_total_time;
+	};
+
+	Map<StringName, ProfileData> profile_data;
+	bool profiling;
+
 public:
 	// These two maps must only be touched on the main thread
 	Map<String, Map<StringName, NativeScriptDesc> > library_classes;
@@ -343,6 +359,8 @@ public:
 
 	virtual bool handles_global_class_type(const String &p_type) const;
 	virtual String get_global_class_name(const String &p_path, String *r_base_type, String *r_icon_path) const;
+
+	void profiling_add_data(StringName p_signature, uint64_t p_time);
 };
 
 inline NativeScriptDesc *NativeScript::get_script_desc() const {