Improve engine startup/shutdown benchmarks
- Add contexts to give a better sense of benchmarked areas. - Add missing benchmarks and adjust some begin/end points. - Clean up names. - Improve Android's internal benchmarks in a similar manner. Co-authored-by: Fredia Huya-Kouadio <fhuya@meta.com>
This commit is contained in:
@@ -184,7 +184,7 @@ class Godot(private val context: Context) : SensorEventListener {
|
||||
return
|
||||
}
|
||||
|
||||
beginBenchmarkMeasure("Godot::onCreate")
|
||||
beginBenchmarkMeasure("Startup", "Godot::onCreate")
|
||||
try {
|
||||
this.primaryHost = primaryHost
|
||||
val activity = requireActivity()
|
||||
@@ -286,7 +286,7 @@ class Godot(private val context: Context) : SensorEventListener {
|
||||
initializationStarted = false
|
||||
throw e
|
||||
} finally {
|
||||
endBenchmarkMeasure("Godot::onCreate");
|
||||
endBenchmarkMeasure("Startup", "Godot::onCreate");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1016,13 +1016,13 @@ class Godot(private val context: Context) : SensorEventListener {
|
||||
}
|
||||
|
||||
@Keep
|
||||
private fun nativeBeginBenchmarkMeasure(label: String) {
|
||||
beginBenchmarkMeasure(label)
|
||||
private fun nativeBeginBenchmarkMeasure(scope: String, label: String) {
|
||||
beginBenchmarkMeasure(scope, label)
|
||||
}
|
||||
|
||||
@Keep
|
||||
private fun nativeEndBenchmarkMeasure(label: String) {
|
||||
endBenchmarkMeasure(label)
|
||||
private fun nativeEndBenchmarkMeasure(scope: String, label: String) {
|
||||
endBenchmarkMeasure(scope, label)
|
||||
}
|
||||
|
||||
@Keep
|
||||
|
||||
@@ -172,7 +172,7 @@ public class GodotFragment extends Fragment implements IDownloaderClient, GodotH
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
BenchmarkUtils.beginBenchmarkMeasure("GodotFragment::onCreate");
|
||||
BenchmarkUtils.beginBenchmarkMeasure("Startup", "GodotFragment::onCreate");
|
||||
super.onCreate(icicle);
|
||||
|
||||
final Activity activity = getActivity();
|
||||
@@ -180,7 +180,7 @@ public class GodotFragment extends Fragment implements IDownloaderClient, GodotH
|
||||
|
||||
godot = new Godot(requireContext());
|
||||
performEngineInitialization();
|
||||
BenchmarkUtils.endBenchmarkMeasure("GodotFragment::onCreate");
|
||||
BenchmarkUtils.endBenchmarkMeasure("Startup", "GodotFragment::onCreate");
|
||||
}
|
||||
|
||||
private void performEngineInitialization() {
|
||||
|
||||
@@ -41,7 +41,7 @@ import org.godotengine.godot.io.file.FileAccessFlags
|
||||
import org.godotengine.godot.io.file.FileAccessHandler
|
||||
import org.json.JSONObject
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.concurrent.ConcurrentSkipListMap
|
||||
import java.util.Collections
|
||||
|
||||
/**
|
||||
* Contains benchmark related utilities methods
|
||||
@@ -51,44 +51,47 @@ private const val TAG = "GodotBenchmark"
|
||||
var useBenchmark = false
|
||||
var benchmarkFile = ""
|
||||
|
||||
private val startBenchmarkFrom = ConcurrentSkipListMap<String, Long>()
|
||||
private val benchmarkTracker = ConcurrentSkipListMap<String, Double>()
|
||||
private val startBenchmarkFrom = Collections.synchronizedMap(LinkedHashMap<Pair<String, String>, Long>())
|
||||
private val benchmarkTracker = Collections.synchronizedMap(LinkedHashMap<Pair<String, String>, Double>())
|
||||
|
||||
/**
|
||||
* Start measuring and tracing the execution of a given section of code using the given label.
|
||||
* Start measuring and tracing the execution of a given section of code using the given label
|
||||
* within the given scope.
|
||||
*
|
||||
* Must be followed by a call to [endBenchmarkMeasure].
|
||||
*
|
||||
* Note: Only enabled on 'editorDev' build variant.
|
||||
*/
|
||||
fun beginBenchmarkMeasure(label: String) {
|
||||
fun beginBenchmarkMeasure(scope: String, label: String) {
|
||||
if (BuildConfig.FLAVOR != "editor" || BuildConfig.BUILD_TYPE != "dev") {
|
||||
return
|
||||
}
|
||||
startBenchmarkFrom[label] = SystemClock.elapsedRealtime()
|
||||
val key = Pair(scope, label)
|
||||
startBenchmarkFrom[key] = SystemClock.elapsedRealtime()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
Trace.beginAsyncSection(label, 0)
|
||||
Trace.beginAsyncSection("[$scope] $label", 0)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* End measuring and tracing of the section of code with the given label.
|
||||
* End measuring and tracing of the section of code with the given label within the given scope.
|
||||
*
|
||||
* Must be preceded by a call [beginBenchmarkMeasure]
|
||||
*
|
||||
* * Note: Only enabled on 'editorDev' build variant.
|
||||
*/
|
||||
fun endBenchmarkMeasure(label: String) {
|
||||
fun endBenchmarkMeasure(scope: String, label: String) {
|
||||
if (BuildConfig.FLAVOR != "editor" || BuildConfig.BUILD_TYPE != "dev") {
|
||||
return
|
||||
}
|
||||
val startTime = startBenchmarkFrom[label] ?: return
|
||||
val key = Pair(scope, label)
|
||||
val startTime = startBenchmarkFrom[key] ?: return
|
||||
val total = SystemClock.elapsedRealtime() - startTime
|
||||
benchmarkTracker[label] = total / 1000.0
|
||||
benchmarkTracker[key] = total / 1_000.0
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
Trace.endAsyncSection(label, 0)
|
||||
Trace.endAsyncSection("[$scope] $label", 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,8 +110,16 @@ fun dumpBenchmark(fileAccessHandler: FileAccessHandler?, filepath: String? = ben
|
||||
return
|
||||
}
|
||||
|
||||
val results = LinkedHashMap<String, String>()
|
||||
for (entry in benchmarkTracker) {
|
||||
if (!results.containsKey(entry.key.first)) {
|
||||
results[entry.key.first] = ""
|
||||
}
|
||||
results[entry.key.first] += "\t\t- ${entry.key.second}: ${entry.value * 1_000.0} msec.\n"
|
||||
}
|
||||
|
||||
val printOut =
|
||||
benchmarkTracker.map { "\t- ${it.key} : ${it.value} sec." }.joinToString("\n")
|
||||
results.map { "\t- [${it.key}]\n ${it.value}" }.joinToString("\n")
|
||||
Log.i(TAG, "BENCHMARK:\n$printOut")
|
||||
|
||||
if (fileAccessHandler != null && !filepath.isNullOrBlank()) {
|
||||
|
||||
@@ -78,8 +78,8 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_
|
||||
_on_godot_main_loop_started = p_env->GetMethodID(godot_class, "onGodotMainLoopStarted", "()V");
|
||||
_create_new_godot_instance = p_env->GetMethodID(godot_class, "createNewGodotInstance", "([Ljava/lang/String;)I");
|
||||
_get_render_view = p_env->GetMethodID(godot_class, "getRenderView", "()Lorg/godotengine/godot/GodotRenderView;");
|
||||
_begin_benchmark_measure = p_env->GetMethodID(godot_class, "nativeBeginBenchmarkMeasure", "(Ljava/lang/String;)V");
|
||||
_end_benchmark_measure = p_env->GetMethodID(godot_class, "nativeEndBenchmarkMeasure", "(Ljava/lang/String;)V");
|
||||
_begin_benchmark_measure = p_env->GetMethodID(godot_class, "nativeBeginBenchmarkMeasure", "(Ljava/lang/String;Ljava/lang/String;)V");
|
||||
_end_benchmark_measure = p_env->GetMethodID(godot_class, "nativeEndBenchmarkMeasure", "(Ljava/lang/String;Ljava/lang/String;)V");
|
||||
_dump_benchmark = p_env->GetMethodID(godot_class, "nativeDumpBenchmark", "(Ljava/lang/String;)V");
|
||||
_get_gdextension_list_config_file = p_env->GetMethodID(godot_class, "getGDExtensionConfigFiles", "()[Ljava/lang/String;");
|
||||
_has_feature = p_env->GetMethodID(godot_class, "hasFeature", "(Ljava/lang/String;)Z");
|
||||
@@ -348,21 +348,23 @@ int GodotJavaWrapper::create_new_godot_instance(List<String> args) {
|
||||
}
|
||||
}
|
||||
|
||||
void GodotJavaWrapper::begin_benchmark_measure(const String &p_label) {
|
||||
void GodotJavaWrapper::begin_benchmark_measure(const String &p_context, const String &p_label) {
|
||||
if (_begin_benchmark_measure) {
|
||||
JNIEnv *env = get_jni_env();
|
||||
ERR_FAIL_NULL(env);
|
||||
jstring j_context = env->NewStringUTF(p_context.utf8().get_data());
|
||||
jstring j_label = env->NewStringUTF(p_label.utf8().get_data());
|
||||
env->CallVoidMethod(godot_instance, _begin_benchmark_measure, j_label);
|
||||
env->CallVoidMethod(godot_instance, _begin_benchmark_measure, j_context, j_label);
|
||||
}
|
||||
}
|
||||
|
||||
void GodotJavaWrapper::end_benchmark_measure(const String &p_label) {
|
||||
void GodotJavaWrapper::end_benchmark_measure(const String &p_context, const String &p_label) {
|
||||
if (_end_benchmark_measure) {
|
||||
JNIEnv *env = get_jni_env();
|
||||
ERR_FAIL_NULL(env);
|
||||
jstring j_context = env->NewStringUTF(p_context.utf8().get_data());
|
||||
jstring j_label = env->NewStringUTF(p_label.utf8().get_data());
|
||||
env->CallVoidMethod(godot_instance, _end_benchmark_measure, j_label);
|
||||
env->CallVoidMethod(godot_instance, _end_benchmark_measure, j_context, j_label);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,8 +105,8 @@ public:
|
||||
void vibrate(int p_duration_ms);
|
||||
String get_input_fallback_mapping();
|
||||
int create_new_godot_instance(List<String> args);
|
||||
void begin_benchmark_measure(const String &p_label);
|
||||
void end_benchmark_measure(const String &p_label);
|
||||
void begin_benchmark_measure(const String &p_context, const String &p_label);
|
||||
void end_benchmark_measure(const String &p_context, const String &p_label);
|
||||
void dump_benchmark(const String &benchmark_file);
|
||||
|
||||
// Return the list of gdextensions config file.
|
||||
|
||||
@@ -708,15 +708,15 @@ String OS_Android::get_config_path() const {
|
||||
return get_user_data_dir().path_join("config");
|
||||
}
|
||||
|
||||
void OS_Android::benchmark_begin_measure(const String &p_what) {
|
||||
void OS_Android::benchmark_begin_measure(const String &p_context, const String &p_what) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
godot_java->begin_benchmark_measure(p_what);
|
||||
godot_java->begin_benchmark_measure(p_context, p_what);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OS_Android::benchmark_end_measure(const String &p_what) {
|
||||
void OS_Android::benchmark_end_measure(const String &p_context, const String &p_what) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
godot_java->end_benchmark_measure(p_what);
|
||||
godot_java->end_benchmark_measure(p_context, p_what);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -165,8 +165,8 @@ public:
|
||||
|
||||
virtual Error setup_remote_filesystem(const String &p_server_host, int p_port, const String &p_password, String &r_project_path) override;
|
||||
|
||||
virtual void benchmark_begin_measure(const String &p_what) override;
|
||||
virtual void benchmark_end_measure(const String &p_what) override;
|
||||
virtual void benchmark_begin_measure(const String &p_context, const String &p_what) override;
|
||||
virtual void benchmark_end_measure(const String &p_context, const String &p_what) override;
|
||||
virtual void benchmark_dump() override;
|
||||
|
||||
virtual void load_platform_gdextensions() const override;
|
||||
|
||||
Reference in New Issue
Block a user