mirror of
https://github.com/godotengine/godot-benchmarks.git
synced 2025-12-31 09:49:13 +03:00
Port GDScript benchmarks to C++ (#86)
Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
This commit is contained in:
committed by
GitHub
parent
bfd8458b7a
commit
460494848a
2
.gitignore
vendored
2
.gitignore
vendored
@@ -32,7 +32,7 @@ __pycache__/
|
||||
venv
|
||||
|
||||
# Godot Git repository clone (run-benchmarks.sh)
|
||||
godot/
|
||||
/godot/
|
||||
|
||||
# Output HTML files
|
||||
web/public/
|
||||
|
||||
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[submodule "gdextension/godot-cpp"]
|
||||
path = gdextension/godot-cpp
|
||||
url = https://github.com/godotengine/godot-cpp.git
|
||||
branch = master
|
||||
22
README.md
22
README.md
@@ -8,6 +8,26 @@ such as rendering and scripting.
|
||||
|
||||
## Running benchmarks
|
||||
|
||||
### Setup
|
||||
|
||||
To be able to run C# benchmarks, you need to use a .NET build of Godot. If not
|
||||
using a .NET build, the project will still be able to run GDScript and C++
|
||||
benchmarks (if compiled), but C# benchmarks won't run.
|
||||
|
||||
To be able to run C++ benchmarks, you need to compile the GDExtension for your
|
||||
platform in the [`gdextension/`](gdextension/) folder. To do so, run the
|
||||
following commands in that folder:
|
||||
|
||||
```bash
|
||||
cd gdextension/
|
||||
git submodule update --init --recursive
|
||||
scons
|
||||
scons target=template_release
|
||||
```
|
||||
|
||||
Remember to recompile the extension after any changes to the C++ code have been
|
||||
made, so that the changes are reflected when running benchmarks.
|
||||
|
||||
### Using a graphical interface
|
||||
|
||||
Open the project in the editor, then run it from the editor or from an export
|
||||
@@ -17,7 +37,7 @@ in the bottom-right corner.
|
||||
Once benchmarks are run, you can copy the results JSON using the
|
||||
**Copy JSON to Clipboard** button at the bottom. The results JSON is also printed to
|
||||
standard output, which you can see if you're running the project from a terminal.
|
||||
|
||||
v
|
||||
### Using the command line
|
||||
|
||||
After opening the project in the editor (required so that resources can be imported),
|
||||
|
||||
19
gdextension/.gitignore
vendored
Normal file
19
gdextension/.gitignore
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# Compiled binaries from the GDExtension used for C++ benchmarks
|
||||
*.o
|
||||
*.os
|
||||
*.so
|
||||
*.dll
|
||||
*.framework
|
||||
*.dylib
|
||||
*.obj
|
||||
*.bc
|
||||
*.pyc
|
||||
*.dblite
|
||||
*.pdb
|
||||
*.lib
|
||||
*.config
|
||||
*.creator
|
||||
*.creator.user
|
||||
*.files
|
||||
*.includes
|
||||
*.idb
|
||||
33
gdextension/SConstruct
Normal file
33
gdextension/SConstruct
Normal file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
env = SConscript("godot-cpp/SConstruct")
|
||||
|
||||
# For reference:
|
||||
# - CCFLAGS are compilation flags shared between C and C++
|
||||
# - CFLAGS are for C-specific compilation flags
|
||||
# - CXXFLAGS are for C++-specific compilation flags
|
||||
# - CPPFLAGS are for pre-processor flags
|
||||
# - CPPDEFINES are for pre-processor defines
|
||||
# - LINKFLAGS are for linking flags
|
||||
|
||||
# tweak this if you want to use different folders, or more folders, to store your source code in.
|
||||
env.Append(CPPPATH=["src/"])
|
||||
sources = Glob("src/*.cpp")
|
||||
sources.extend(Glob("src/benchmarks/*.cpp"))
|
||||
|
||||
if env["platform"] == "macos":
|
||||
library = env.SharedLibrary(
|
||||
"bin/libcppbenchmarks.{}.{}.framework/libcppbenchmarks.{}.{}".format(
|
||||
env["platform"], env["target"], env["platform"], env["target"]
|
||||
),
|
||||
source=sources,
|
||||
)
|
||||
else:
|
||||
library = env.SharedLibrary(
|
||||
"bin/libcppbenchmarks{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
|
||||
source=sources,
|
||||
)
|
||||
|
||||
Default(library)
|
||||
23
gdextension/bin/cppbenchmarks.gdextension
Normal file
23
gdextension/bin/cppbenchmarks.gdextension
Normal file
@@ -0,0 +1,23 @@
|
||||
[configuration]
|
||||
|
||||
entry_symbol = "benchmark_library_init"
|
||||
compatibility_minimum = "4.3"
|
||||
|
||||
[libraries]
|
||||
|
||||
macos.debug = "res://gdextension/bin/libcppbenchmarks.macos.template_debug.framework"
|
||||
macos.release = "res://gdextension/bin/libcppbenchmarks.macos.template_release.framework"
|
||||
windows.debug.x86_32 = "res://gdextension/bin/libcppbenchmarks.windows.template_debug.x86_32.dll"
|
||||
windows.release.x86_32 = "res://gdextension/bin/libcppbenchmarks.windows.template_release.x86_32.dll"
|
||||
windows.debug.x86_64 = "res://gdextension/bin/libcppbenchmarks.windows.template_debug.x86_64.dll"
|
||||
windows.release.x86_64 = "res://gdextension/bin/libcppbenchmarks.windows.template_release.x86_64.dll"
|
||||
linux.debug.x86_64 = "res://gdextension/bin/libcppbenchmarks.linux.template_debug.x86_64.so"
|
||||
linux.release.x86_64 = "res://gdextension/bin/libcppbenchmarks.linux.template_release.x86_64.so"
|
||||
linux.debug.arm64 = "res://gdextension/bin/libcppbenchmarks.linux.template_debug.arm64.so"
|
||||
linux.release.arm64 = "res://gdextension/bin/libcppbenchmarks.linux.template_release.arm64.so"
|
||||
linux.debug.rv64 = "res://gdextension/bin/libcppbenchmarks.linux.template_debug.rv64.so"
|
||||
linux.release.rv64 = "res://gdextension/bin/libcppbenchmarks.linux.template_release.rv64.so"
|
||||
android.debug.x86_64 = "res://gdextension/bin/libcppbenchmarks.android.template_debug.x86_64.so"
|
||||
android.release.x86_64 = "res://gdextension/bin/libcppbenchmarks.android.template_release.x86_64.so"
|
||||
android.debug.arm64 = "res://gdextension/bin/libcppbenchmarks.android.template_debug.arm64.so"
|
||||
android.release.arm64 = "res://gdextension/bin/libcppbenchmarks.android.template_release.arm64.so"
|
||||
304091
gdextension/extension_api.json
Normal file
304091
gdextension/extension_api.json
Normal file
File diff suppressed because it is too large
Load Diff
1
gdextension/godot-cpp
Submodule
1
gdextension/godot-cpp
Submodule
Submodule gdextension/godot-cpp added at 99926d8e20
79
gdextension/src/benchmarks/alloc.cpp
Normal file
79
gdextension/src/benchmarks/alloc.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#include "alloc.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/classes/node.hpp>
|
||||
#include <godot_cpp/classes/random_number_generator.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void CPPBenchmarkAlloc::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("benchmark_deep_tree"), &CPPBenchmarkAlloc::benchmark_deep_tree);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_wide_tree"), &CPPBenchmarkAlloc::benchmark_wide_tree);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_fragmentation"), &CPPBenchmarkAlloc::benchmark_fragmentation);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_duplicate"), &CPPBenchmarkAlloc::benchmark_duplicate);
|
||||
}
|
||||
|
||||
void CPPBenchmarkAlloc::benchmark_deep_tree() {
|
||||
Node *rt = memnew(Node);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
Node *n = memnew(Node);
|
||||
n->add_child(rt);
|
||||
rt = n;
|
||||
}
|
||||
// Avoid triggering a stack overflow with memdelete(rt)
|
||||
while (rt->get_child_count() != 0) {
|
||||
Node *n = rt->get_child(0);
|
||||
rt->remove_child(n);
|
||||
memdelete(rt);
|
||||
rt = n;
|
||||
}
|
||||
memdelete(rt);
|
||||
}
|
||||
|
||||
void CPPBenchmarkAlloc::benchmark_wide_tree() {
|
||||
Node *rt = memnew(Node);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
rt->add_child(memnew(Node));
|
||||
}
|
||||
memdelete(rt);
|
||||
}
|
||||
|
||||
void CPPBenchmarkAlloc::benchmark_fragmentation() {
|
||||
Node *top = memnew(Node);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
top->add_child(memnew(Node));
|
||||
}
|
||||
Ref<RandomNumberGenerator> rand;
|
||||
rand.instantiate();
|
||||
for (int k = 0; k < 10; k++) {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
// Attempt to scatter children in memory by assigning newly created nodes to a random parent
|
||||
int idx = rand->randi() % top->get_child_count();
|
||||
top->get_child(idx)->add_child(memnew(Node));
|
||||
}
|
||||
|
||||
Node *tmp = top->get_child(0);
|
||||
top->remove_child(tmp);
|
||||
// Since nodes in the tree are scattered in memory,
|
||||
// freeing subtrees this way should maximize fragmentation.
|
||||
memdelete(tmp);
|
||||
top->add_child(memnew(Node));
|
||||
}
|
||||
|
||||
memdelete(top);
|
||||
}
|
||||
|
||||
void CPPBenchmarkAlloc::benchmark_duplicate() {
|
||||
Node *rt = memnew(Node);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
Node *n = memnew(Node);
|
||||
n->add_child(rt->duplicate());
|
||||
n->add_child(rt->duplicate());
|
||||
memdelete(rt);
|
||||
rt = n;
|
||||
}
|
||||
memdelete(rt);
|
||||
}
|
||||
|
||||
CPPBenchmarkAlloc::CPPBenchmarkAlloc() {}
|
||||
|
||||
CPPBenchmarkAlloc::~CPPBenchmarkAlloc() {}
|
||||
22
gdextension/src/benchmarks/alloc.h
Normal file
22
gdextension/src/benchmarks/alloc.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef CPP_BENCHMARK_ALLOC_H
|
||||
#define CPP_BENCHMARK_ALLOC_H
|
||||
|
||||
#include "../cppbenchmark.h"
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmarkAlloc : public CPPBenchmark {
|
||||
GDCLASS(CPPBenchmarkAlloc, CPPBenchmark)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
unsigned int iterations = 100000;
|
||||
void benchmark_deep_tree();
|
||||
void benchmark_wide_tree();
|
||||
void benchmark_fragmentation();
|
||||
void benchmark_duplicate();
|
||||
CPPBenchmarkAlloc();
|
||||
~CPPBenchmarkAlloc();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
146
gdextension/src/benchmarks/array.cpp
Normal file
146
gdextension/src/benchmarks/array.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
#include "array.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void CPPBenchmarkArray::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("benchmark_fill_loop"), &CPPBenchmarkArray::benchmark_fill_loop);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_int32_array"), &CPPBenchmarkArray::benchmark_int32_array);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_int64_array"), &CPPBenchmarkArray::benchmark_int64_array);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_float32_array"), &CPPBenchmarkArray::benchmark_float32_array);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_float64_array"), &CPPBenchmarkArray::benchmark_float64_array);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_vector2_array"), &CPPBenchmarkArray::benchmark_vector2_array);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_vector3_array"), &CPPBenchmarkArray::benchmark_vector3_array);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_vector4_array"), &CPPBenchmarkArray::benchmark_vector4_array);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_color_array"), &CPPBenchmarkArray::benchmark_color_array);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_string_array"), &CPPBenchmarkArray::benchmark_string_array);
|
||||
}
|
||||
|
||||
void CPPBenchmarkArray::benchmark_fill_loop() {
|
||||
int length = 10000000;
|
||||
int array[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
array[i] = 1234;
|
||||
}
|
||||
}
|
||||
|
||||
void CPPBenchmarkArray::benchmark_int32_array() {
|
||||
TypedArray<int> array;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.push_back(i);
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array[i] = 0;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.remove_at(array.size() - 1);
|
||||
}
|
||||
|
||||
void CPPBenchmarkArray::benchmark_int64_array() {
|
||||
TypedArray<long> array;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.push_back(i);
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array[i] = 0;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.remove_at(array.size() - 1);
|
||||
}
|
||||
|
||||
void CPPBenchmarkArray::benchmark_float32_array() {
|
||||
TypedArray<float> array;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.push_back(i);
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array[i] = 0.0;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.remove_at(array.size() - 1);
|
||||
}
|
||||
|
||||
void CPPBenchmarkArray::benchmark_float64_array() {
|
||||
TypedArray<double> array;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.push_back(i);
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array[i] = 0.0;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.remove_at(array.size() - 1);
|
||||
}
|
||||
|
||||
void CPPBenchmarkArray::benchmark_vector2_array() {
|
||||
TypedArray<Vector2> array;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.push_back(Vector2(i, i));
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array[i] = Vector2(0, 0);
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.remove_at(array.size() - 1);
|
||||
}
|
||||
|
||||
void CPPBenchmarkArray::benchmark_vector3_array() {
|
||||
TypedArray<Vector3> array;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.push_back(Vector3(i, i, i));
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array[i] = Vector3(0, 0, 0);
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.remove_at(array.size() - 1);
|
||||
}
|
||||
|
||||
void CPPBenchmarkArray::benchmark_vector4_array() {
|
||||
TypedArray<Vector4> array;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.push_back(Vector4(i, i, i, i));
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array[i] = Vector4(0, 0, 0, 0);
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.remove_at(array.size() - 1);
|
||||
}
|
||||
|
||||
void CPPBenchmarkArray::benchmark_color_array() {
|
||||
TypedArray<Color> array;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.push_back(Color(i, i, i, 1.0));
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array[i] = Color(0, 0, 0, 0);
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.remove_at(array.size() - 1);
|
||||
}
|
||||
|
||||
void CPPBenchmarkArray::benchmark_string_array() {
|
||||
TypedArray<String> array;
|
||||
|
||||
for(int64_t i = 0; i < iterations; i++) // i needs to be int64_t for string formatting to work, as the String::% operator is not overloaded for int
|
||||
array.push_back(String("Godot %d") % i);
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array[i] = "";
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
array.remove_at(array.size() - 1);
|
||||
}
|
||||
|
||||
CPPBenchmarkArray::CPPBenchmarkArray() {}
|
||||
|
||||
CPPBenchmarkArray::~CPPBenchmarkArray() {}
|
||||
28
gdextension/src/benchmarks/array.h
Normal file
28
gdextension/src/benchmarks/array.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef CPP_BENCHMARK_ARRAY_H
|
||||
#define CPP_BENCHMARK_ARRAY_H
|
||||
|
||||
#include "../cppbenchmark.h"
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmarkArray : public CPPBenchmark {
|
||||
GDCLASS(CPPBenchmarkArray, CPPBenchmark)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
unsigned int iterations = 2000000;
|
||||
void benchmark_fill_loop();
|
||||
void benchmark_int32_array();
|
||||
void benchmark_int64_array();
|
||||
void benchmark_float32_array();
|
||||
void benchmark_float64_array();
|
||||
void benchmark_vector2_array();
|
||||
void benchmark_vector3_array();
|
||||
void benchmark_vector4_array();
|
||||
void benchmark_color_array();
|
||||
void benchmark_string_array();
|
||||
CPPBenchmarkArray();
|
||||
~CPPBenchmarkArray();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
54
gdextension/src/benchmarks/binary_trees.cpp
Normal file
54
gdextension/src/benchmarks/binary_trees.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "binary_trees.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void CPPBenchmarkBinaryTrees::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("benchmark_binary_trees_13"), &CPPBenchmarkBinaryTrees::benchmark_binary_trees_13);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_binary_trees_15"), &CPPBenchmarkBinaryTrees::benchmark_binary_trees_15);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_binary_trees_18"), &CPPBenchmarkBinaryTrees::benchmark_binary_trees_18);
|
||||
}
|
||||
|
||||
void CPPBenchmarkBinaryTrees::calculate_binary_trees(int input) {
|
||||
int max_depth = godot::Math::max(min_depth + 2, input);
|
||||
|
||||
int stretch_depth = max_depth + 1;
|
||||
TreeNode* stretch_tree = TreeNode::create(stretch_depth);
|
||||
godot::UtilityFunctions::print("stretch tree of depth ", stretch_depth, "\t check: ", stretch_tree->check());
|
||||
delete stretch_tree;
|
||||
|
||||
TreeNode* long_lived_tree = TreeNode::create(max_depth);
|
||||
int max_plus_min_depth = max_depth + min_depth;
|
||||
for (int depth = min_depth; depth < max_depth; depth += 2) {
|
||||
int iterations = 1 << (max_plus_min_depth - depth);
|
||||
int check = 0;
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
TreeNode* check_tree = TreeNode::create(depth);
|
||||
check += check_tree->check();
|
||||
delete check_tree;
|
||||
}
|
||||
|
||||
godot::UtilityFunctions::print(iterations, "\t trees of depth ", depth, "\t check: ", check);
|
||||
}
|
||||
|
||||
godot::UtilityFunctions::print("long lived tree of depth ", max_depth, "\t check: ", long_lived_tree->check());
|
||||
delete long_lived_tree;
|
||||
}
|
||||
|
||||
void CPPBenchmarkBinaryTrees::benchmark_binary_trees_13() {
|
||||
calculate_binary_trees(13);
|
||||
}
|
||||
|
||||
void CPPBenchmarkBinaryTrees::benchmark_binary_trees_15() {
|
||||
calculate_binary_trees(15);
|
||||
}
|
||||
|
||||
void CPPBenchmarkBinaryTrees::benchmark_binary_trees_18() {
|
||||
calculate_binary_trees(18);
|
||||
}
|
||||
|
||||
CPPBenchmarkBinaryTrees::CPPBenchmarkBinaryTrees() {}
|
||||
|
||||
CPPBenchmarkBinaryTrees::~CPPBenchmarkBinaryTrees() {}
|
||||
59
gdextension/src/benchmarks/binary_trees.h
Normal file
59
gdextension/src/benchmarks/binary_trees.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef CPP_BENCHMARK_BINARY_TREES_H
|
||||
#define CPP_BENCHMARK_BINARY_TREES_H
|
||||
|
||||
#include "../cppbenchmark.h"
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmarkBinaryTrees : public CPPBenchmark {
|
||||
GDCLASS(CPPBenchmarkBinaryTrees, CPPBenchmark)
|
||||
|
||||
private:
|
||||
class TreeNode {
|
||||
private:
|
||||
TreeNode* left;
|
||||
TreeNode* right;
|
||||
public:
|
||||
TreeNode() {
|
||||
left = nullptr;
|
||||
right = nullptr;
|
||||
};
|
||||
TreeNode(TreeNode* p_left, TreeNode* p_right) {
|
||||
left = p_left;
|
||||
right = p_right;
|
||||
};
|
||||
~TreeNode() {
|
||||
delete left;
|
||||
delete right;
|
||||
};
|
||||
static TreeNode* create(int d){
|
||||
if (d == 0)
|
||||
return new TreeNode();
|
||||
return new TreeNode(create(d - 1), create(d - 1));
|
||||
};
|
||||
int check() {
|
||||
int c = 1;
|
||||
if (right != nullptr)
|
||||
{
|
||||
c += right->check();
|
||||
}
|
||||
if (left != nullptr)
|
||||
{
|
||||
c += left->check();
|
||||
}
|
||||
return c;
|
||||
};
|
||||
};
|
||||
|
||||
const int min_depth = 4;
|
||||
void calculate_binary_trees(int input);
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
void benchmark_binary_trees_13();
|
||||
void benchmark_binary_trees_15();
|
||||
void benchmark_binary_trees_18();
|
||||
CPPBenchmarkBinaryTrees();
|
||||
~CPPBenchmarkBinaryTrees();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
16
gdextension/src/benchmarks/control.cpp
Normal file
16
gdextension/src/benchmarks/control.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "control.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
// An empty test, to act as a control
|
||||
|
||||
void CPPBenchmarkControl::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("benchmark_control"), &CPPBenchmarkControl::benchmark_control);
|
||||
}
|
||||
|
||||
void CPPBenchmarkControl::benchmark_control() {}
|
||||
|
||||
CPPBenchmarkControl::CPPBenchmarkControl() {}
|
||||
|
||||
CPPBenchmarkControl::~CPPBenchmarkControl() {}
|
||||
18
gdextension/src/benchmarks/control.h
Normal file
18
gdextension/src/benchmarks/control.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef CPP_BENCHMARK_CONTROL_H
|
||||
#define CPP_BENCHMARK_CONTROL_H
|
||||
|
||||
#include "../cppbenchmark.h"
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmarkControl : public CPPBenchmark {
|
||||
GDCLASS(CPPBenchmarkControl, CPPBenchmark)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
void benchmark_control();
|
||||
CPPBenchmarkControl();
|
||||
~CPPBenchmarkControl();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
26
gdextension/src/benchmarks/forloop.cpp
Normal file
26
gdextension/src/benchmarks/forloop.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "forloop.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void CPPBenchmarkForLoop::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("benchmark_loop_add"), &CPPBenchmarkForLoop::benchmark_loop_add);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_loop_call"), &CPPBenchmarkForLoop::benchmark_loop_call);
|
||||
}
|
||||
|
||||
void CPPBenchmarkForLoop::function() {}
|
||||
|
||||
void CPPBenchmarkForLoop::benchmark_loop_add() {
|
||||
int number = 0;
|
||||
for(int i = 0; i < iterations; i++)
|
||||
number++;
|
||||
}
|
||||
|
||||
void CPPBenchmarkForLoop::benchmark_loop_call() {
|
||||
for(int i = 0; i < iterations; i++)
|
||||
function();
|
||||
}
|
||||
|
||||
CPPBenchmarkForLoop::CPPBenchmarkForLoop() {}
|
||||
|
||||
CPPBenchmarkForLoop::~CPPBenchmarkForLoop() {}
|
||||
22
gdextension/src/benchmarks/forloop.h
Normal file
22
gdextension/src/benchmarks/forloop.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef CPP_BENCHMARK_FOR_LOOP_H
|
||||
#define CPP_BENCHMARK_FOR_LOOP_H
|
||||
|
||||
#include "../cppbenchmark.h"
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmarkForLoop : public CPPBenchmark {
|
||||
GDCLASS(CPPBenchmarkForLoop, CPPBenchmark)
|
||||
|
||||
private:
|
||||
void function();
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
unsigned int iterations = 1000000;
|
||||
void benchmark_loop_add();
|
||||
void benchmark_loop_call();
|
||||
CPPBenchmarkForLoop();
|
||||
~CPPBenchmarkForLoop();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
18
gdextension/src/benchmarks/hello_world.cpp
Normal file
18
gdextension/src/benchmarks/hello_world.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "hello_world.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void CPPBenchmarkHelloWorld::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("benchmark_hello_world"), &CPPBenchmarkHelloWorld::benchmark_hello_world);
|
||||
}
|
||||
|
||||
void CPPBenchmarkHelloWorld::benchmark_hello_world() {
|
||||
godot::UtilityFunctions::print("Hello world!");
|
||||
}
|
||||
|
||||
CPPBenchmarkHelloWorld::CPPBenchmarkHelloWorld() {}
|
||||
|
||||
CPPBenchmarkHelloWorld::~CPPBenchmarkHelloWorld() {}
|
||||
18
gdextension/src/benchmarks/hello_world.h
Normal file
18
gdextension/src/benchmarks/hello_world.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef CPP_BENCHMARK_HELLOWORLD_H
|
||||
#define CPP_BENCHMARK_HELLOWORLD_H
|
||||
|
||||
#include "../cppbenchmark.h"
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmarkHelloWorld : public CPPBenchmark {
|
||||
GDCLASS(CPPBenchmarkHelloWorld, CPPBenchmark)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
void benchmark_hello_world();
|
||||
CPPBenchmarkHelloWorld();
|
||||
~CPPBenchmarkHelloWorld();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
18
gdextension/src/benchmarks/lambda_performance.cpp
Normal file
18
gdextension/src/benchmarks/lambda_performance.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "lambda_performance.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void CPPBenchmarkLambdaPerformance::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("benchmark_lambda_call"), &CPPBenchmarkLambdaPerformance::benchmark_lambda_call);
|
||||
}
|
||||
|
||||
void CPPBenchmarkLambdaPerformance::benchmark_lambda_call() {
|
||||
auto lambda = [](){};
|
||||
for(int i = 0; i < iterations; i++)
|
||||
lambda();
|
||||
}
|
||||
|
||||
CPPBenchmarkLambdaPerformance::CPPBenchmarkLambdaPerformance() {}
|
||||
|
||||
CPPBenchmarkLambdaPerformance::~CPPBenchmarkLambdaPerformance() {}
|
||||
19
gdextension/src/benchmarks/lambda_performance.h
Normal file
19
gdextension/src/benchmarks/lambda_performance.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef CPP_BENCHMARK_LAMBDA_PERFORMANCE_H
|
||||
#define CPP_BENCHMARK_LAMBDA_PERFORMANCE_H
|
||||
|
||||
#include "../cppbenchmark.h"
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmarkLambdaPerformance : public CPPBenchmark {
|
||||
GDCLASS(CPPBenchmarkLambdaPerformance, CPPBenchmark)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
unsigned int iterations = 1000000;
|
||||
void benchmark_lambda_call();
|
||||
CPPBenchmarkLambdaPerformance();
|
||||
~CPPBenchmarkLambdaPerformance();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
69
gdextension/src/benchmarks/mandelbrot_set.cpp
Normal file
69
gdextension/src/benchmarks/mandelbrot_set.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "mandelbrot_set.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
#include <godot_cpp/classes/image.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void CPPBenchmarkMandelbrotSet::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("benchmark_mandelbrot_set"), &CPPBenchmarkMandelbrotSet::benchmark_mandelbrot_set);
|
||||
}
|
||||
|
||||
Color CPPBenchmarkMandelbrotSet::hsv(float hue, float sat, float value) {
|
||||
hue = godot::Math::fposmod(hue, 360.0f);
|
||||
int h = godot::Math::floor(hue) / 60;
|
||||
float f = hue / 60.0 - h;
|
||||
float p = value * (1.0 - sat);
|
||||
float q = value * (1.0 - sat * f);
|
||||
float t = value * (1.0 - sat * (1.0 - f));
|
||||
if (h == 0 || h == 6)
|
||||
return Color(value, t, p);
|
||||
if (h == 1)
|
||||
return Color(q, value, p);
|
||||
if (h == 2)
|
||||
return Color(p, value, t);
|
||||
if (h == 3)
|
||||
return Color(p, q, value);
|
||||
if (h == 4)
|
||||
return Color(t, p, value);
|
||||
return Color(value, p, q);
|
||||
}
|
||||
|
||||
void CPPBenchmarkMandelbrotSet::mandelbrot_set(int p_width, int p_height, int p_max_iteration) {
|
||||
Ref<Image> image = memnew(Image);
|
||||
image = Image::create_empty(p_width, p_height, false, Image::Format::FORMAT_RGB8);
|
||||
float ratio = float(p_width) / float(p_height);
|
||||
float x_range = 3.6;
|
||||
float y_range = x_range / ratio;
|
||||
float min_x = -x_range / 2.0;
|
||||
float max_y = y_range / 2.0;
|
||||
for (int x = 0; x < image->get_width(); x++) {
|
||||
for (int y = 0; y < image->get_height(); y++) {
|
||||
int iteration = 0;
|
||||
float x0 = min_x + x_range * x / p_width;
|
||||
float y0 = max_y - y_range * y / p_height;
|
||||
float xx = 0.0;
|
||||
float yy = 0.0;
|
||||
float x2 = 0.0;
|
||||
float y2 = 0.0;
|
||||
while (x2 + y2 <= 4 && iteration < p_max_iteration) {
|
||||
yy = 2 * xx * yy + y0;
|
||||
xx = x2 - y2 + x0;
|
||||
x2 = xx * xx;
|
||||
y2 = yy * yy;
|
||||
iteration += 1;
|
||||
}
|
||||
float m = float(iteration) / float(p_max_iteration);
|
||||
Color color = hsv(360.0 * m, 1.0, ceilf(1.0 - 1.1 * m));
|
||||
image->set_pixel(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPPBenchmarkMandelbrotSet::benchmark_mandelbrot_set() {
|
||||
mandelbrot_set(width, height, max_iteration);
|
||||
}
|
||||
|
||||
CPPBenchmarkMandelbrotSet::CPPBenchmarkMandelbrotSet() {}
|
||||
|
||||
CPPBenchmarkMandelbrotSet::~CPPBenchmarkMandelbrotSet() {}
|
||||
24
gdextension/src/benchmarks/mandelbrot_set.h
Normal file
24
gdextension/src/benchmarks/mandelbrot_set.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef CPP_BENCHMARK_MANDELBROT_SET_H
|
||||
#define CPP_BENCHMARK_MANDELBROT_SET_H
|
||||
|
||||
#include "../cppbenchmark.h"
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmarkMandelbrotSet : public CPPBenchmark {
|
||||
GDCLASS(CPPBenchmarkMandelbrotSet, CPPBenchmark)
|
||||
|
||||
private:
|
||||
int width = 600;
|
||||
int height = 400;
|
||||
int max_iteration = 1000;
|
||||
Color hsv(float hue, float sat, float value);
|
||||
void mandelbrot_set(int p_width, int p_height, int p_max_iteration);
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
void benchmark_mandelbrot_set();
|
||||
CPPBenchmarkMandelbrotSet();
|
||||
~CPPBenchmarkMandelbrotSet();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
64
gdextension/src/benchmarks/merkle_trees.cpp
Normal file
64
gdextension/src/benchmarks/merkle_trees.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include "merkle_trees.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void CPPBenchmarkMerkleTrees::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("benchmark_merkle_trees_13"), &CPPBenchmarkMerkleTrees::benchmark_merkle_trees_13);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_merkle_trees_15"), &CPPBenchmarkMerkleTrees::benchmark_merkle_trees_15);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_merkle_trees_18"), &CPPBenchmarkMerkleTrees::benchmark_merkle_trees_18);
|
||||
}
|
||||
|
||||
CPPBenchmarkMerkleTrees::TreeNode* CPPBenchmarkMerkleTrees::make_tree(int depth) {
|
||||
if (depth > 0) {
|
||||
depth -= 1;
|
||||
return new TreeNode(-1, make_tree(depth), make_tree(depth));
|
||||
}
|
||||
return new TreeNode(1, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void CPPBenchmarkMerkleTrees::calculate_merkle_trees(int input) {
|
||||
int max_depth = godot::Math::max(min_depth + 2, input);
|
||||
|
||||
int stretch_depth = max_depth + 1;
|
||||
TreeNode* stretch_tree = make_tree(stretch_depth);
|
||||
stretch_tree->cal_hash();
|
||||
godot::UtilityFunctions::print("stretch tree of depth ", stretch_depth, "\t root hash: ", stretch_tree->hash, "\t check: ", stretch_tree->check());
|
||||
delete stretch_tree;
|
||||
|
||||
TreeNode* long_lived_tree = make_tree(max_depth);
|
||||
int max_plus_min_depth = max_depth + min_depth;
|
||||
for (int depth = min_depth; depth < max_depth; depth += 2) {
|
||||
int iterations = 1 << (max_plus_min_depth - depth);
|
||||
int sum = 0;
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
TreeNode* tree = make_tree(depth);
|
||||
tree->cal_hash();
|
||||
sum += tree->hash;
|
||||
delete tree;
|
||||
}
|
||||
|
||||
godot::UtilityFunctions::print(iterations, "\t trees of depth ", depth, "\t root hash sum: ", sum);
|
||||
}
|
||||
long_lived_tree->cal_hash();
|
||||
godot::UtilityFunctions::print("long lived tree of depth ", input, "\t root hash: ", long_lived_tree->hash, "\t check: ", long_lived_tree->check());
|
||||
delete long_lived_tree;
|
||||
}
|
||||
|
||||
void CPPBenchmarkMerkleTrees::benchmark_merkle_trees_13() {
|
||||
calculate_merkle_trees(13);
|
||||
}
|
||||
|
||||
void CPPBenchmarkMerkleTrees::benchmark_merkle_trees_15() {
|
||||
calculate_merkle_trees(15);
|
||||
}
|
||||
|
||||
void CPPBenchmarkMerkleTrees::benchmark_merkle_trees_18() {
|
||||
calculate_merkle_trees(18);
|
||||
}
|
||||
|
||||
CPPBenchmarkMerkleTrees::CPPBenchmarkMerkleTrees() {}
|
||||
|
||||
CPPBenchmarkMerkleTrees::~CPPBenchmarkMerkleTrees() {}
|
||||
72
gdextension/src/benchmarks/merkle_trees.h
Normal file
72
gdextension/src/benchmarks/merkle_trees.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef CPP_BENCHMARK_MERKLE_TREES_H
|
||||
#define CPP_BENCHMARK_MERKLE_TREES_H
|
||||
|
||||
#include "../cppbenchmark.h"
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmarkMerkleTrees : public CPPBenchmark {
|
||||
GDCLASS(CPPBenchmarkMerkleTrees, CPPBenchmark)
|
||||
|
||||
private:
|
||||
class TreeNode {
|
||||
private:
|
||||
int value;
|
||||
TreeNode* left;
|
||||
TreeNode* right;
|
||||
public:
|
||||
TreeNode() {
|
||||
value = -1;
|
||||
left = nullptr;
|
||||
right = nullptr;
|
||||
hash = -1;
|
||||
};
|
||||
TreeNode(int p_value, TreeNode* p_left, TreeNode* p_right) {
|
||||
value = p_value;
|
||||
left = p_left;
|
||||
right = p_right;
|
||||
hash = -1;
|
||||
};
|
||||
~TreeNode() {
|
||||
delete left;
|
||||
delete right;
|
||||
};
|
||||
bool check() {
|
||||
if (hash != -1) {
|
||||
if (value != -1) {
|
||||
return true;
|
||||
}
|
||||
if (left != nullptr && right != nullptr) {
|
||||
return left->check() && right->check();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
void cal_hash() {
|
||||
if (hash == -1) {
|
||||
if (value != -1) {
|
||||
hash = value;
|
||||
}
|
||||
else if (left != nullptr && right != nullptr) {
|
||||
left->cal_hash();
|
||||
right->cal_hash();
|
||||
hash = left->hash + right->hash;
|
||||
}
|
||||
}
|
||||
};
|
||||
int hash;
|
||||
};
|
||||
|
||||
const int min_depth = 4;
|
||||
TreeNode* make_tree(int depth);
|
||||
void calculate_merkle_trees(int input);
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
void benchmark_merkle_trees_13();
|
||||
void benchmark_merkle_trees_15();
|
||||
void benchmark_merkle_trees_18();
|
||||
CPPBenchmarkMerkleTrees();
|
||||
~CPPBenchmarkMerkleTrees();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
93
gdextension/src/benchmarks/nbody.cpp
Normal file
93
gdextension/src/benchmarks/nbody.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "nbody.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void CPPBenchmarkNbody::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("benchmark_nbody_500_000"), &CPPBenchmarkNbody::benchmark_nbody_500_000);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_nbody_1_000_000"), &CPPBenchmarkNbody::benchmark_nbody_1_000_000);
|
||||
}
|
||||
|
||||
void CPPBenchmarkNbody::offset_momentum() {
|
||||
double px, py, pz = 0;
|
||||
for(char i = 0; i < body_count; i++) {
|
||||
Body b = bodies[i];
|
||||
px -= b.vx * b.mass;
|
||||
py -= b.vy * b.mass;
|
||||
pz -= b.vz * b.mass;
|
||||
}
|
||||
Body sol = bodies[0];
|
||||
bodies[0].vx = px / Solarmass;
|
||||
bodies[0].vy = py / Solarmass;
|
||||
bodies[0].vz = pz / Solarmass;
|
||||
}
|
||||
|
||||
void CPPBenchmarkNbody::advance(double dt) {
|
||||
for (char i = 0; i < body_count; i++) {
|
||||
double x = bodies[i].x;
|
||||
double y = bodies[i].y;
|
||||
double z = bodies[i].z;
|
||||
double vx = bodies[i].vx;
|
||||
double vy = bodies[i].vy;
|
||||
double vz = bodies[i].vz;
|
||||
double mi = bodies[i].mass;
|
||||
for (char j = i + 1; j < body_count; j++) {
|
||||
double dx = x - bodies[j].x;
|
||||
double dy = y - bodies[j].y;
|
||||
double dz = z - bodies[j].z;
|
||||
double d2 = dx * dx + dy * dy + dz * dz;
|
||||
double mag = dt / (d2 * godot::Math::sqrt(d2));
|
||||
double bj_m_mag = bodies[j].mass * mag;
|
||||
vx -= dx * bj_m_mag;
|
||||
vy -= dy * bj_m_mag;
|
||||
vz -= dz * bj_m_mag;
|
||||
|
||||
double bi_m_mag = mi * mag;
|
||||
bodies[j].vx += dx * bi_m_mag;
|
||||
bodies[j].vy += dy * bi_m_mag;
|
||||
bodies[j].vz += dz * bi_m_mag;
|
||||
}
|
||||
bodies[i].vx = vx;
|
||||
bodies[i].vy = vy;
|
||||
bodies[i].vz = vz;
|
||||
|
||||
bodies[i].x += vx * dt;
|
||||
bodies[i].y += vy * dt;
|
||||
bodies[i].z += vz * dt;
|
||||
}
|
||||
}
|
||||
|
||||
double CPPBenchmarkNbody::energy() {
|
||||
double e = 0.0;
|
||||
for (int i = 0; i < body_count; i++) {
|
||||
e += 0.5 * bodies[i].mass * (bodies[i].vx * bodies[i].vx + bodies[i].vy * bodies[i].vy + bodies[i].vz * bodies[i].vz);
|
||||
for (int j = i + 1; j < body_count; j++) {
|
||||
double dx = bodies[i].x - bodies[j].x, dy = bodies[i].y - bodies[j].y, dz = bodies[i].z - bodies[j].z;
|
||||
e -= (bodies[i].mass * bodies[j].mass) / godot::Math::sqrt(dx * dx + dy * dy + dz * dz);
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
void CPPBenchmarkNbody::calculate_nbody(int n) {
|
||||
offset_momentum();
|
||||
godot::UtilityFunctions::print(energy());
|
||||
for (int i = 0; i < n; i++) {
|
||||
advance(0.01);
|
||||
}
|
||||
godot::UtilityFunctions::print(energy());
|
||||
}
|
||||
|
||||
void CPPBenchmarkNbody::benchmark_nbody_500_000() {
|
||||
calculate_nbody(500000);
|
||||
}
|
||||
|
||||
void CPPBenchmarkNbody::benchmark_nbody_1_000_000() {
|
||||
calculate_nbody(1000000);
|
||||
}
|
||||
|
||||
CPPBenchmarkNbody::CPPBenchmarkNbody() {}
|
||||
|
||||
CPPBenchmarkNbody::~CPPBenchmarkNbody() {}
|
||||
71
gdextension/src/benchmarks/nbody.h
Normal file
71
gdextension/src/benchmarks/nbody.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef CPP_BENCHMARK_NBODY_H
|
||||
#define CPP_BENCHMARK_NBODY_H
|
||||
|
||||
#include "../cppbenchmark.h"
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmarkNbody : public CPPBenchmark {
|
||||
GDCLASS(CPPBenchmarkNbody, CPPBenchmark)
|
||||
|
||||
private:
|
||||
const double Pi = 3.141592653589793;
|
||||
const double Solarmass = 4 * Pi * Pi;
|
||||
const double DaysPeryear = 365.24;
|
||||
struct Body { double x, y, z, vx, vy, vz, mass; };
|
||||
const char body_count = 5; // We can use char since this value is small
|
||||
Body bodies[5] {
|
||||
{ // Sun
|
||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Solarmass
|
||||
},
|
||||
{ // Jupiter
|
||||
4.84143144246472090e+00,
|
||||
-1.16032004402742839e+00,
|
||||
-1.03622044471123109e-01,
|
||||
1.66007664274403694e-03*DaysPeryear,
|
||||
7.69901118419740425e-03*DaysPeryear,
|
||||
-6.90460016972063023e-05*DaysPeryear,
|
||||
9.54791938424326609e-04*Solarmass
|
||||
},
|
||||
{ // Saturn
|
||||
8.34336671824457987e+00,
|
||||
4.12479856412430479e+00,
|
||||
-4.03523417114321381e-01,
|
||||
-2.76742510726862411e-03*DaysPeryear,
|
||||
4.99852801234917238e-03*DaysPeryear,
|
||||
2.30417297573763929e-05*DaysPeryear,
|
||||
2.85885980666130812e-04*Solarmass,
|
||||
},
|
||||
{ // Uranus
|
||||
1.28943695621391310e+01,
|
||||
-1.51111514016986312e+01,
|
||||
-2.23307578892655734e-01,
|
||||
2.96460137564761618e-03*DaysPeryear,
|
||||
2.37847173959480950e-03*DaysPeryear,
|
||||
-2.96589568540237556e-05*DaysPeryear,
|
||||
4.36624404335156298e-05*Solarmass,
|
||||
},
|
||||
{ // Neptune
|
||||
1.53796971148509165e+01,
|
||||
-2.59193146099879641e+01,
|
||||
1.79258772950371181e-01,
|
||||
2.68067772490389322e-03*DaysPeryear,
|
||||
1.62824170038242295e-03*DaysPeryear,
|
||||
-9.51592254519715870e-05*DaysPeryear,
|
||||
5.15138902046611451e-05*Solarmass,
|
||||
},
|
||||
};
|
||||
|
||||
void offset_momentum();
|
||||
void advance(double dt);
|
||||
double energy();
|
||||
void calculate_nbody(int n);
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
void benchmark_nbody_500_000();
|
||||
void benchmark_nbody_1_000_000();
|
||||
CPPBenchmarkNbody();
|
||||
~CPPBenchmarkNbody();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
84
gdextension/src/benchmarks/spectral_norm.cpp
Normal file
84
gdextension/src/benchmarks/spectral_norm.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "spectral_norm.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void CPPBenchmarkSpectralNorm::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("benchmark_spectral_norm_100"), &CPPBenchmarkSpectralNorm::benchmark_spectral_norm_100);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_spectral_norm_500"), &CPPBenchmarkSpectralNorm::benchmark_spectral_norm_500);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_spectral_norm_1000"), &CPPBenchmarkSpectralNorm::benchmark_spectral_norm_1000);
|
||||
}
|
||||
|
||||
double CPPBenchmarkSpectralNorm::eval_a(int i, int j) {
|
||||
return 1.0 / ((i + j) * (i + j + 1) / 2 + i + 1);
|
||||
}
|
||||
|
||||
/* multiply vector v by matrix A, each thread evaluate its range only */
|
||||
void CPPBenchmarkSpectralNorm::multiply_av(double v[], double av[], int n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
double sum = 0;
|
||||
for (int j = 0; j < n; j++)
|
||||
sum += eval_a(i, j) * v[j];
|
||||
|
||||
av[i] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* multiply vector v by matrix A transposed */
|
||||
void CPPBenchmarkSpectralNorm::multiply_atv(double v[], double atv[], int n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
double sum = 0;
|
||||
for (int j = 0; j < n; j++)
|
||||
sum += eval_a(j, i) * v[j];
|
||||
|
||||
atv[i] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* multiply vector v by matrix A and then by matrix A transposed */
|
||||
void CPPBenchmarkSpectralNorm::multiply_at_av(double v[], double tmp[], double at_av[], int n) {
|
||||
multiply_av(v, tmp, n);
|
||||
multiply_atv(tmp, at_av, n);
|
||||
}
|
||||
|
||||
void CPPBenchmarkSpectralNorm::calculate_spectral_norm(int n) {
|
||||
double u[n];
|
||||
double v[n];
|
||||
double tmp[n];
|
||||
|
||||
// create unit vector
|
||||
for (int i = 0; i < n; i++)
|
||||
u[i] = 1.0;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
multiply_at_av(u, v, tmp, n);
|
||||
multiply_at_av(v, u, tmp, n);
|
||||
}
|
||||
|
||||
double vbv = 0, vv = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
vbv += u[i] * v[i];
|
||||
vv += v[i] * v[i];
|
||||
}
|
||||
|
||||
double square_root = godot::Math::sqrt(vbv / vv);
|
||||
godot::UtilityFunctions::print(square_root);
|
||||
}
|
||||
|
||||
void CPPBenchmarkSpectralNorm::benchmark_spectral_norm_100() {
|
||||
calculate_spectral_norm(100);
|
||||
}
|
||||
|
||||
void CPPBenchmarkSpectralNorm::benchmark_spectral_norm_500() {
|
||||
calculate_spectral_norm(500);
|
||||
}
|
||||
|
||||
void CPPBenchmarkSpectralNorm::benchmark_spectral_norm_1000() {
|
||||
calculate_spectral_norm(1000);
|
||||
}
|
||||
|
||||
CPPBenchmarkSpectralNorm::CPPBenchmarkSpectralNorm() {}
|
||||
|
||||
CPPBenchmarkSpectralNorm::~CPPBenchmarkSpectralNorm() {}
|
||||
26
gdextension/src/benchmarks/spectral_norm.h
Normal file
26
gdextension/src/benchmarks/spectral_norm.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef CPP_BENCHMARK_SPECTRAL_NORM_H
|
||||
#define CPP_BENCHMARK_SPECTRAL_NORM_H
|
||||
|
||||
#include "../cppbenchmark.h"
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmarkSpectralNorm : public CPPBenchmark {
|
||||
GDCLASS(CPPBenchmarkSpectralNorm, CPPBenchmark)
|
||||
|
||||
private:
|
||||
double eval_a(int i, int j);
|
||||
void multiply_av(double v[], double av[], int n);
|
||||
void multiply_atv(double v[], double atv[], int n);
|
||||
void multiply_at_av(double v[], double tmp[], double at_av[], int n);
|
||||
void calculate_spectral_norm(int input);
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
void benchmark_spectral_norm_100();
|
||||
void benchmark_spectral_norm_500();
|
||||
void benchmark_spectral_norm_1000();
|
||||
CPPBenchmarkSpectralNorm();
|
||||
~CPPBenchmarkSpectralNorm();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
84
gdextension/src/benchmarks/string_checksum.cpp
Normal file
84
gdextension/src/benchmarks/string_checksum.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "string_checksum.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void CPPBenchmarkStringChecksum::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("benchmark_md5_buffer_empty"), &CPPBenchmarkStringChecksum::benchmark_md5_buffer_empty);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_md5_buffer_non_empty"), &CPPBenchmarkStringChecksum::benchmark_md5_buffer_non_empty);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_sha1_buffer_empty"), &CPPBenchmarkStringChecksum::benchmark_sha1_buffer_empty);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_sha1_buffer_non_empty"), &CPPBenchmarkStringChecksum::benchmark_sha1_buffer_non_empty);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_sha256_buffer_empty"), &CPPBenchmarkStringChecksum::benchmark_sha256_buffer_empty);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_sha256_buffer_non_empty"), &CPPBenchmarkStringChecksum::benchmark_sha256_buffer_non_empty);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_md5_text_empty"), &CPPBenchmarkStringChecksum::benchmark_md5_text_empty);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_md5_text_non_empty"), &CPPBenchmarkStringChecksum::benchmark_md5_text_non_empty);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_sha1_text_empty"), &CPPBenchmarkStringChecksum::benchmark_sha1_text_empty);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_sha1_text_non_empty"), &CPPBenchmarkStringChecksum::benchmark_sha1_text_non_empty);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_sha256_text_empty"), &CPPBenchmarkStringChecksum::benchmark_sha256_text_empty);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_sha256_text_non_empty"), &CPPBenchmarkStringChecksum::benchmark_sha256_text_non_empty);
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringChecksum::benchmark_md5_buffer_empty() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("").md5_buffer();
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringChecksum::benchmark_md5_buffer_non_empty() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
LOREM_IPSUM.md5_buffer();
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringChecksum::benchmark_sha1_buffer_empty() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("").sha1_buffer();
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringChecksum::benchmark_sha1_buffer_non_empty() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
LOREM_IPSUM.sha1_buffer();
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringChecksum::benchmark_sha256_buffer_empty() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("").sha256_buffer();
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringChecksum::benchmark_sha256_buffer_non_empty() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
LOREM_IPSUM.sha256_buffer();
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringChecksum::benchmark_md5_text_empty() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("").md5_text();
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringChecksum::benchmark_md5_text_non_empty() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
LOREM_IPSUM.md5_text();
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringChecksum::benchmark_sha1_text_empty() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("").sha1_text();
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringChecksum::benchmark_sha1_text_non_empty() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
LOREM_IPSUM.sha1_text();
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringChecksum::benchmark_sha256_text_empty() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("").sha256_text();
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringChecksum::benchmark_sha256_text_non_empty() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
LOREM_IPSUM.sha256_text();
|
||||
}
|
||||
|
||||
|
||||
CPPBenchmarkStringChecksum::CPPBenchmarkStringChecksum() {}
|
||||
|
||||
CPPBenchmarkStringChecksum::~CPPBenchmarkStringChecksum() {}
|
||||
32
gdextension/src/benchmarks/string_checksum.h
Normal file
32
gdextension/src/benchmarks/string_checksum.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef CPP_BENCHMARK_STRING_CHECKSUM_H
|
||||
#define CPP_BENCHMARK_STRING_CHECKSUM_H
|
||||
|
||||
#include "../cppbenchmark.h"
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmarkStringChecksum : public CPPBenchmark {
|
||||
GDCLASS(CPPBenchmarkStringChecksum, CPPBenchmark)
|
||||
|
||||
private:
|
||||
const String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.";
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
unsigned int iterations = 1000000;
|
||||
void benchmark_md5_buffer_empty();
|
||||
void benchmark_md5_buffer_non_empty();
|
||||
void benchmark_sha1_buffer_empty();
|
||||
void benchmark_sha1_buffer_non_empty();
|
||||
void benchmark_sha256_buffer_empty();
|
||||
void benchmark_sha256_buffer_non_empty();
|
||||
void benchmark_md5_text_empty();
|
||||
void benchmark_md5_text_non_empty();
|
||||
void benchmark_sha1_text_empty();
|
||||
void benchmark_sha1_text_non_empty();
|
||||
void benchmark_sha256_text_empty();
|
||||
void benchmark_sha256_text_non_empty();
|
||||
CPPBenchmarkStringChecksum();
|
||||
~CPPBenchmarkStringChecksum();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
96
gdextension/src/benchmarks/string_format.cpp
Normal file
96
gdextension/src/benchmarks/string_format.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#include "string_format.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void CPPBenchmarkStringFormat::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("benchmark_no_op_constant_method"), &CPPBenchmarkStringFormat::benchmark_no_op_constant_method);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_simple_constant_concatenate"), &CPPBenchmarkStringFormat::benchmark_simple_constant_concatenate);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_simple_constant_percent"), &CPPBenchmarkStringFormat::benchmark_simple_constant_percent);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_simple_constant_method"), &CPPBenchmarkStringFormat::benchmark_simple_constant_method);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_simple_constant_method_constant_dict"), &CPPBenchmarkStringFormat::benchmark_simple_constant_method_constant_dict);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_simple_variable_concatenate"), &CPPBenchmarkStringFormat::benchmark_simple_variable_concatenate);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_simple_variable_percent"), &CPPBenchmarkStringFormat::benchmark_simple_variable_percent);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_simple_variable_method"), &CPPBenchmarkStringFormat::benchmark_simple_variable_method);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_complex_variable_concatenate"), &CPPBenchmarkStringFormat::benchmark_complex_variable_concatenate);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_complex_variable_percent"), &CPPBenchmarkStringFormat::benchmark_complex_variable_percent);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_complex_variable_method"), &CPPBenchmarkStringFormat::benchmark_complex_variable_method);
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringFormat::benchmark_no_op_constant_method() {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
Dictionary dict;
|
||||
String("Hello nothing!").format(dict);
|
||||
}
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringFormat::benchmark_simple_constant_concatenate() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
"Hello " + ENGINE_NAME + "!";
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringFormat::benchmark_simple_constant_percent() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Hello %s!") % ENGINE_NAME;
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringFormat::benchmark_simple_constant_method() {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
Dictionary dict;
|
||||
dict["engine"] = ENGINE_NAME;
|
||||
String("Hello {engine}!").format(dict);
|
||||
}
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringFormat::benchmark_simple_constant_method_constant_dict() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Hello {engine}!").format(FORMAT_DICT);
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringFormat::benchmark_simple_variable_concatenate() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
"Hello " + engine_name + "!";
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringFormat::benchmark_simple_variable_percent() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Hello %s!") % engine_name;
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringFormat::benchmark_simple_variable_method() {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
Dictionary dict;
|
||||
dict["engine"] = engine_name;
|
||||
String("Hello {engine}!").format(dict);
|
||||
}
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringFormat::benchmark_complex_variable_concatenate() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
"Hello " + engine_name + "!\nA few examples of formatting: " + godot::UtilityFunctions::str(some_integer) + ", " + godot::UtilityFunctions::str(some_float).pad_decimals(2) + ", " + godot::UtilityFunctions::str(some_vector2i);
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringFormat::benchmark_complex_variable_percent() {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
Array arr = Array::make(engine_name, some_integer, some_float, some_vector2i);
|
||||
String("Hello %s!\nA few examples of formatting: %d, %.2f, %v") % arr;
|
||||
}
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringFormat::benchmark_complex_variable_method() {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
Dictionary dict;
|
||||
dict["engine"] = engine_name;
|
||||
dict["an_integer"] = some_integer;
|
||||
dict["a_float"] = godot::UtilityFunctions::str(some_float).pad_decimals(2);
|
||||
dict["a_vector2i"] = some_vector2i;
|
||||
String("Hello {engine}!\nA few examples of formatting: {an_integer}, {a_float}, {a_vector2i}").format(dict);
|
||||
}
|
||||
}
|
||||
|
||||
CPPBenchmarkStringFormat::CPPBenchmarkStringFormat() {
|
||||
FORMAT_DICT["engine"] = ENGINE_NAME;
|
||||
}
|
||||
|
||||
CPPBenchmarkStringFormat::~CPPBenchmarkStringFormat() {}
|
||||
37
gdextension/src/benchmarks/string_format.h
Normal file
37
gdextension/src/benchmarks/string_format.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef CPP_BENCHMARK_STRING_FORMAT_H
|
||||
#define CPP_BENCHMARK_STRING_FORMAT_H
|
||||
|
||||
#include "../cppbenchmark.h"
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmarkStringFormat : public CPPBenchmark {
|
||||
GDCLASS(CPPBenchmarkStringFormat, CPPBenchmark)
|
||||
|
||||
private:
|
||||
const String ENGINE_NAME = "Godot";
|
||||
Dictionary FORMAT_DICT;
|
||||
|
||||
String engine_name = "Godot";
|
||||
int some_integer = 123456;
|
||||
float some_float = 1.2;
|
||||
Vector2i some_vector2i = Vector2i(12, 34);
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
unsigned int iterations = 1000000;
|
||||
void benchmark_no_op_constant_method();
|
||||
void benchmark_simple_constant_concatenate();
|
||||
void benchmark_simple_constant_percent();
|
||||
void benchmark_simple_constant_method();
|
||||
void benchmark_simple_constant_method_constant_dict();
|
||||
void benchmark_simple_variable_concatenate();
|
||||
void benchmark_simple_variable_percent();
|
||||
void benchmark_simple_variable_method();
|
||||
void benchmark_complex_variable_concatenate();
|
||||
void benchmark_complex_variable_percent();
|
||||
void benchmark_complex_variable_method();
|
||||
CPPBenchmarkStringFormat();
|
||||
~CPPBenchmarkStringFormat();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
282
gdextension/src/benchmarks/string_manipulation.cpp
Normal file
282
gdextension/src/benchmarks/string_manipulation.cpp
Normal file
@@ -0,0 +1,282 @@
|
||||
#include "string_manipulation.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void CPPBenchmarkStringManipulation::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("benchmark_begins_with"), &CPPBenchmarkStringManipulation::benchmark_begins_with);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_ends_with"), &CPPBenchmarkStringManipulation::benchmark_ends_with);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_count"), &CPPBenchmarkStringManipulation::benchmark_count);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_countn"), &CPPBenchmarkStringManipulation::benchmark_countn);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_contains"), &CPPBenchmarkStringManipulation::benchmark_contains);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_find"), &CPPBenchmarkStringManipulation::benchmark_find);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_findn"), &CPPBenchmarkStringManipulation::benchmark_findn);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_rfind"), &CPPBenchmarkStringManipulation::benchmark_rfind);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_rfindn"), &CPPBenchmarkStringManipulation::benchmark_rfindn);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_substr"), &CPPBenchmarkStringManipulation::benchmark_substr);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_insert"), &CPPBenchmarkStringManipulation::benchmark_insert);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_get_slice"), &CPPBenchmarkStringManipulation::benchmark_get_slice);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_get_slice_count"), &CPPBenchmarkStringManipulation::benchmark_get_slice_count);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_bigrams"), &CPPBenchmarkStringManipulation::benchmark_bigrams);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_split"), &CPPBenchmarkStringManipulation::benchmark_split);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_rsplit"), &CPPBenchmarkStringManipulation::benchmark_rsplit);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_split_floats"), &CPPBenchmarkStringManipulation::benchmark_split_floats);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_pad_zeros_pre_constructed"), &CPPBenchmarkStringManipulation::benchmark_pad_zeros_pre_constructed);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_pad_zeros"), &CPPBenchmarkStringManipulation::benchmark_pad_zeros);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_pad_decimals_pre_constructed"), &CPPBenchmarkStringManipulation::benchmark_pad_decimals_pre_constructed);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_pad_decimals"), &CPPBenchmarkStringManipulation::benchmark_pad_decimals);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_lpad"), &CPPBenchmarkStringManipulation::benchmark_lpad);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_rpad"), &CPPBenchmarkStringManipulation::benchmark_rpad);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_similarity"), &CPPBenchmarkStringManipulation::benchmark_similarity);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_simplify_path"), &CPPBenchmarkStringManipulation::benchmark_simplify_path);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_capitalize"), &CPPBenchmarkStringManipulation::benchmark_capitalize);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_to_snake_case"), &CPPBenchmarkStringManipulation::benchmark_to_snake_case);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_to_camel_case"), &CPPBenchmarkStringManipulation::benchmark_to_camel_case);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_to_pascal_case"), &CPPBenchmarkStringManipulation::benchmark_to_pascal_case);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_to_lower"), &CPPBenchmarkStringManipulation::benchmark_to_lower);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_uri_decode"), &CPPBenchmarkStringManipulation::benchmark_uri_decode);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_uri_encode"), &CPPBenchmarkStringManipulation::benchmark_uri_encode);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_xml_escape"), &CPPBenchmarkStringManipulation::benchmark_xml_escape);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_xml_unescape"), &CPPBenchmarkStringManipulation::benchmark_xml_unescape);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_humanize_size"), &CPPBenchmarkStringManipulation::benchmark_humanize_size);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_is_valid_filename"), &CPPBenchmarkStringManipulation::benchmark_is_valid_filename);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_validate_filename"), &CPPBenchmarkStringManipulation::benchmark_validate_filename);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_validate_node_name"), &CPPBenchmarkStringManipulation::benchmark_validate_node_name);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_casecmp_to"), &CPPBenchmarkStringManipulation::benchmark_casecmp_to);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_nocasecmp_to"), &CPPBenchmarkStringManipulation::benchmark_nocasecmp_to);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_naturalnocasecmp_to"), &CPPBenchmarkStringManipulation::benchmark_naturalnocasecmp_to);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_to_utf8_buffer"), &CPPBenchmarkStringManipulation::benchmark_to_utf8_buffer);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_to_utf16_buffer"), &CPPBenchmarkStringManipulation::benchmark_to_utf16_buffer);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_to_utf32_buffer"), &CPPBenchmarkStringManipulation::benchmark_to_utf32_buffer);
|
||||
ClassDB::bind_method(D_METHOD("benchmark_to_wchar_buffer"), &CPPBenchmarkStringManipulation::benchmark_to_wchar_buffer);
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_begins_with() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine").begins_with("Godot"); // true
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_ends_with() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine").ends_with("Engine"); // true
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_count() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine").count("o"); // 2
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_countn() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine").countn("o"); // 2
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_contains() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine").contains("o"); // tr
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_find() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine").find("o"); // 1
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_findn() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine").findn("o"); // 1
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_rfind() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine").rfind("o"); // 3
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_rfindn() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine").rfindn("o"); // 3
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_substr() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Hello Godot!").substr(6, 5); // "Godot"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_insert() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Hello !").insert(6, "Godot"); // "Hello Godot!"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_get_slice() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("1234,5678,90.12").get_slice(",", 1); // "5678"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_get_slice_count() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("1234,5678,90.12").get_slice_count(","); // 3
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_bigrams() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine").bigrams(); // ["Go", "od", "do", "ot", "t ", " E", "En", "ng", "gi", "in", "ne"]
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_split() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("1234,5678,90.12").split(","); // ["1234", "5678", "90.12"]
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_rsplit() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("1234,5678,90.12").rsplit(","); // ["1234", "5678", "90.12"]
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_split_floats() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("1234,5678,90.12").split_floats(","); // [1234.0, 5678.0, 90.12]
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_pad_zeros_pre_constructed() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("12345").pad_zeros(7); // "0012345"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_pad_zeros() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
godot::UtilityFunctions::str(12345).pad_zeros(7); // "0012345"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_pad_decimals_pre_constructed() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("1234.5678").pad_decimals(2); // "1234.56"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_pad_decimals() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
godot::UtilityFunctions::str(1234.5678).pad_decimals(2); // "1234.56"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_lpad() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot").lpad(7, "+"); // "++Godot"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_rpad() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot").rpad(7, "+"); // "Godot++"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_similarity() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot").similarity("Engine");
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_simplify_path() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("./path/to///../file").simplify_path(); // "path/file"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_capitalize() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("godot_engine_demo").capitalize(); // "Godot Engine Demo"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_to_snake_case() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("GodotEngineDemo").to_snake_case(); // "godot_engine_demo"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_to_camel_case() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("godot_engine_demo").to_snake_case(); // "godotEngineDemo"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_to_pascal_case() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("godot_engine_demo").to_pascal_case(); // "GodotEngineDemo"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_to_lower() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine Demo").to_lower(); // "godot engine demo"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_uri_decode() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot%20Engine%3Adocs").uri_decode(); // "Godot Engine:docs"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_uri_encode() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine:docs").uri_encode(); // "Godot%20Engine%3Adocs"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_xml_escape() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine <&>").xml_escape(); // "Godot Engine <&>"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_xml_unescape() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine <&>").xml_unescape(); // "Godot Engine <&>"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_humanize_size() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String::humanize_size(123456); // 120.5 KB
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_is_valid_filename() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine: Demo.exe").is_valid_filename(); // false
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_validate_filename() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine: Demo.exe").validate_filename(); // "Godot Engine_ Demo.exe"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_validate_node_name() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("TestNode:123456").validate_node_name(); // "TestNode123456"
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_casecmp_to() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("2 Example").casecmp_to("10 Example"); // 1
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_nocasecmp_to() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("2 Example").nocasecmp_to("10 Example"); // 1
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_naturalnocasecmp_to() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("2 Example").naturalnocasecmp_to("10 Example"); // -1
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_to_utf8_buffer() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine").to_utf8_buffer();
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_to_utf16_buffer() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine").to_utf16_buffer();
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_to_utf32_buffer() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine").to_utf32_buffer();
|
||||
}
|
||||
|
||||
void CPPBenchmarkStringManipulation::benchmark_to_wchar_buffer() {
|
||||
for (int i = 0; i < iterations; i++)
|
||||
String("Godot Engine").to_wchar_buffer();
|
||||
}
|
||||
|
||||
CPPBenchmarkStringManipulation::CPPBenchmarkStringManipulation() {}
|
||||
|
||||
CPPBenchmarkStringManipulation::~CPPBenchmarkStringManipulation() {}
|
||||
63
gdextension/src/benchmarks/string_manipulation.h
Normal file
63
gdextension/src/benchmarks/string_manipulation.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef CPP_BENCHMARK_STRING_MANIPULATION_H
|
||||
#define CPP_BENCHMARK_STRING_MANIPULATION_H
|
||||
|
||||
#include "../cppbenchmark.h"
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmarkStringManipulation : public CPPBenchmark {
|
||||
GDCLASS(CPPBenchmarkStringManipulation, CPPBenchmark)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
unsigned int iterations = 1000000;
|
||||
void benchmark_begins_with();
|
||||
void benchmark_ends_with();
|
||||
void benchmark_count();
|
||||
void benchmark_countn();
|
||||
void benchmark_contains();
|
||||
void benchmark_find();
|
||||
void benchmark_findn();
|
||||
void benchmark_rfind();
|
||||
void benchmark_rfindn();
|
||||
void benchmark_substr();
|
||||
void benchmark_insert();
|
||||
void benchmark_get_slice();
|
||||
void benchmark_get_slice_count();
|
||||
void benchmark_bigrams();
|
||||
void benchmark_split();
|
||||
void benchmark_rsplit();
|
||||
void benchmark_split_floats();
|
||||
void benchmark_pad_zeros_pre_constructed();
|
||||
void benchmark_pad_zeros();
|
||||
void benchmark_pad_decimals_pre_constructed();
|
||||
void benchmark_pad_decimals();
|
||||
void benchmark_lpad();
|
||||
void benchmark_rpad();
|
||||
void benchmark_similarity();
|
||||
void benchmark_simplify_path();
|
||||
void benchmark_capitalize();
|
||||
void benchmark_to_snake_case();
|
||||
void benchmark_to_camel_case();
|
||||
void benchmark_to_pascal_case();
|
||||
void benchmark_to_lower();
|
||||
void benchmark_uri_decode();
|
||||
void benchmark_uri_encode();
|
||||
void benchmark_xml_escape();
|
||||
void benchmark_xml_unescape();
|
||||
void benchmark_humanize_size();
|
||||
void benchmark_is_valid_filename();
|
||||
void benchmark_validate_filename();
|
||||
void benchmark_validate_node_name();
|
||||
void benchmark_casecmp_to();
|
||||
void benchmark_nocasecmp_to();
|
||||
void benchmark_naturalnocasecmp_to();
|
||||
void benchmark_to_utf8_buffer();
|
||||
void benchmark_to_utf16_buffer();
|
||||
void benchmark_to_utf32_buffer();
|
||||
void benchmark_to_wchar_buffer();
|
||||
CPPBenchmarkStringManipulation();
|
||||
~CPPBenchmarkStringManipulation();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
77
gdextension/src/cppbenchmark.cpp
Normal file
77
gdextension/src/cppbenchmark.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "cppbenchmark.h"
|
||||
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void CPPBenchmark::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_benchmark_time"), &CPPBenchmark::get_benchmark_time);
|
||||
ClassDB::bind_method(D_METHOD("set_benchmark_time", "p_benchmark_time"), &CPPBenchmark::set_benchmark_time);
|
||||
ClassDB::add_property("CPPBenchmark", PropertyInfo(Variant::INT, "benchmark_time"), "set_benchmark_time", "get_benchmark_time");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_test_render_cpu"), &CPPBenchmark::get_test_render_cpu);
|
||||
ClassDB::bind_method(D_METHOD("set_test_render_cpu", "p_test_render_cpu"), &CPPBenchmark::set_test_render_cpu);
|
||||
ClassDB::add_property("CPPBenchmark", PropertyInfo(Variant::BOOL, "test_render_cpu"), "set_test_render_cpu", "get_test_render_cpu");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_test_render_gpu"), &CPPBenchmark::get_test_render_gpu);
|
||||
ClassDB::bind_method(D_METHOD("set_test_render_gpu", "p_test_render_gpu"), &CPPBenchmark::set_test_render_gpu);
|
||||
ClassDB::add_property("CPPBenchmark", PropertyInfo(Variant::BOOL, "test_render_gpu"), "set_test_render_gpu", "get_test_render_gpu");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_test_idle"), &CPPBenchmark::get_test_idle);
|
||||
ClassDB::bind_method(D_METHOD("set_test_idle", "p_test_idle"), &CPPBenchmark::set_test_idle);
|
||||
ClassDB::add_property("CPPBenchmark", PropertyInfo(Variant::BOOL, "test_idle"), "set_test_idle", "get_test_idle");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_test_physics"), &CPPBenchmark::get_test_physics);
|
||||
ClassDB::bind_method(D_METHOD("set_test_physics", "p_test_physics"), &CPPBenchmark::set_test_physics);
|
||||
ClassDB::add_property("CPPBenchmark", PropertyInfo(Variant::BOOL, "test_physics"), "set_test_physics", "get_test_physics");
|
||||
}
|
||||
|
||||
|
||||
CPPBenchmark::CPPBenchmark() {
|
||||
// Initialize any variables here.
|
||||
}
|
||||
|
||||
CPPBenchmark::~CPPBenchmark() {
|
||||
// Add your cleanup here.
|
||||
}
|
||||
|
||||
void CPPBenchmark::set_benchmark_time(const int p_benchmark_time) {
|
||||
benchmark_time = p_benchmark_time;
|
||||
}
|
||||
|
||||
int CPPBenchmark::get_benchmark_time() const {
|
||||
return test_render_cpu;
|
||||
}
|
||||
|
||||
void CPPBenchmark::set_test_render_cpu(const bool p_test_render_cpu) {
|
||||
test_render_cpu = p_test_render_cpu;
|
||||
}
|
||||
|
||||
bool CPPBenchmark::get_test_render_cpu() const {
|
||||
return test_render_cpu;
|
||||
}
|
||||
|
||||
void CPPBenchmark::set_test_render_gpu(const bool p_test_render_gpu) {
|
||||
test_render_gpu = p_test_render_gpu;
|
||||
}
|
||||
|
||||
bool CPPBenchmark::get_test_render_gpu() const {
|
||||
return test_render_gpu;
|
||||
}
|
||||
|
||||
void CPPBenchmark::set_test_idle(const bool p_test_idle) {
|
||||
test_idle = p_test_idle;
|
||||
}
|
||||
|
||||
bool CPPBenchmark::get_test_idle() const {
|
||||
return test_idle;
|
||||
}
|
||||
|
||||
void CPPBenchmark::set_test_physics(const bool p_test_physics) {
|
||||
test_physics = p_test_physics;
|
||||
}
|
||||
|
||||
bool CPPBenchmark::get_test_physics() const {
|
||||
return test_physics;
|
||||
}
|
||||
32
gdextension/src/cppbenchmark.h
Normal file
32
gdextension/src/cppbenchmark.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef CPP_BENCHMARK_H
|
||||
#define CPP_BENCHMARK_H
|
||||
|
||||
#include <godot_cpp/classes/ref_counted.hpp>
|
||||
|
||||
namespace godot {
|
||||
class CPPBenchmark : public RefCounted {
|
||||
GDCLASS(CPPBenchmark, RefCounted)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
int benchmark_time = 5e6;
|
||||
bool test_render_cpu = false;
|
||||
bool test_render_gpu = false;
|
||||
bool test_idle = false;
|
||||
bool test_physics = false;
|
||||
public:
|
||||
void set_benchmark_time(const int p_benchmark_time);
|
||||
int get_benchmark_time() const;
|
||||
void set_test_render_cpu(const bool p_test_render_cpu);
|
||||
bool get_test_render_cpu() const;
|
||||
void set_test_render_gpu(const bool p_test_render_gpu);
|
||||
bool get_test_render_gpu() const;
|
||||
void set_test_idle(const bool p_test_idle);
|
||||
bool get_test_idle() const;
|
||||
void set_test_physics(const bool p_test_physics);
|
||||
bool get_test_physics() const;
|
||||
CPPBenchmark();
|
||||
~CPPBenchmark();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
63
gdextension/src/register_types.cpp
Normal file
63
gdextension/src/register_types.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "register_types.h"
|
||||
|
||||
#include "benchmarks/alloc.h"
|
||||
#include "benchmarks/array.h"
|
||||
#include "benchmarks/binary_trees.h"
|
||||
#include "benchmarks/control.h"
|
||||
#include "benchmarks/forloop.h"
|
||||
#include "benchmarks/hello_world.h"
|
||||
#include "benchmarks/lambda_performance.h"
|
||||
#include "benchmarks/mandelbrot_set.h"
|
||||
#include "benchmarks/merkle_trees.h"
|
||||
#include "benchmarks/nbody.h"
|
||||
#include "benchmarks/spectral_norm.h"
|
||||
#include "benchmarks/string_checksum.h"
|
||||
#include "benchmarks/string_format.h"
|
||||
#include "benchmarks/string_manipulation.h"
|
||||
|
||||
#include <gdextension_interface.h>
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void initialize_benchmark_module(ModuleInitializationLevel p_level) {
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
|
||||
ClassDB::register_class<CPPBenchmark>();
|
||||
ClassDB::register_class<CPPBenchmarkAlloc>();
|
||||
ClassDB::register_class<CPPBenchmarkArray>();
|
||||
ClassDB::register_class<CPPBenchmarkBinaryTrees>();
|
||||
ClassDB::register_class<CPPBenchmarkControl>();
|
||||
ClassDB::register_class<CPPBenchmarkForLoop>();
|
||||
ClassDB::register_class<CPPBenchmarkHelloWorld>();
|
||||
ClassDB::register_class<CPPBenchmarkLambdaPerformance>();
|
||||
ClassDB::register_class<CPPBenchmarkMandelbrotSet>();
|
||||
ClassDB::register_class<CPPBenchmarkMerkleTrees>();
|
||||
ClassDB::register_class<CPPBenchmarkNbody>();
|
||||
ClassDB::register_class<CPPBenchmarkSpectralNorm>();
|
||||
ClassDB::register_class<CPPBenchmarkStringChecksum>();
|
||||
ClassDB::register_class<CPPBenchmarkStringFormat>();
|
||||
ClassDB::register_class<CPPBenchmarkStringManipulation>();
|
||||
}
|
||||
|
||||
void uninitialize_benchmark_module(ModuleInitializationLevel p_level) {
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
// Initialization.
|
||||
GDExtensionBool GDE_EXPORT benchmark_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
|
||||
godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
|
||||
|
||||
init_obj.register_initializer(initialize_benchmark_module);
|
||||
init_obj.register_terminator(uninitialize_benchmark_module);
|
||||
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
|
||||
|
||||
return init_obj.init();
|
||||
}
|
||||
}
|
||||
11
gdextension/src/register_types.h
Normal file
11
gdextension/src/register_types.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef BENCHMARK_REGISTER_TYPES_H
|
||||
#define BENCHMARK_REGISTER_TYPES_H
|
||||
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void initialize_benchmark_module(ModuleInitializationLevel p_level);
|
||||
void uninitialize_benchmark_module(ModuleInitializationLevel p_level);
|
||||
|
||||
#endif // BENCHMARK_REGISTER_TYPES_H
|
||||
52
manager.gd
52
manager.gd
@@ -1,6 +1,22 @@
|
||||
extends Node
|
||||
|
||||
const RANDOM_SEED = 0x60d07
|
||||
const RANDOM_SEED := 0x60d07
|
||||
const CPP_CLASS_NAMES: Array[StringName] = [
|
||||
&"CPPBenchmarkAlloc",
|
||||
&"CPPBenchmarkArray",
|
||||
&"CPPBenchmarkBinaryTrees",
|
||||
&"CPPBenchmarkControl",
|
||||
&"CPPBenchmarkForLoop",
|
||||
&"CPPBenchmarkHelloWorld",
|
||||
&"CPPBenchmarkLambdaPerformance",
|
||||
&"CPPBenchmarkMandelbrotSet",
|
||||
&"CPPBenchmarkMerkleTrees",
|
||||
&"CPPBenchmarkNbody",
|
||||
&"CPPBenchmarkSpectralNorm",
|
||||
&"CPPBenchmarkStringChecksum",
|
||||
&"CPPBenchmarkStringFormat",
|
||||
&"CPPBenchmarkStringManipulation",
|
||||
]
|
||||
|
||||
class Results:
|
||||
var render_cpu := 0.0
|
||||
@@ -49,10 +65,11 @@ func test_ids_from_path(path: String) -> Array[TestID]:
|
||||
|
||||
|
||||
# List of supported languages and their styles.
|
||||
var languages := {".gd": {"test_prefix": "benchmark_"}}
|
||||
var languages := {".gd": {"test_prefix": "benchmark_"}, ".cpp": {"test_prefix": "benchmark_"}}
|
||||
|
||||
# List of benchmarks populated in `_ready()`.
|
||||
var test_results := {}
|
||||
var cpp_classes: Array[RefCounted] = []
|
||||
|
||||
var save_json_to_path := ""
|
||||
var json_results_prefix := ""
|
||||
@@ -78,7 +95,7 @@ func dir_contents(path: String, contents: PackedStringArray = PackedStringArray(
|
||||
return contents
|
||||
|
||||
|
||||
func _ready():
|
||||
func _ready() -> void:
|
||||
RenderingServer.viewport_set_measure_render_time(get_tree().root.get_viewport_rid(),true)
|
||||
set_process(false)
|
||||
|
||||
@@ -91,6 +108,21 @@ func _ready():
|
||||
for test_id in test_ids_from_path(benchmark_path):
|
||||
test_results[test_id] = null
|
||||
|
||||
# Load GDExtension (C++) benchmarks
|
||||
for cpp_class_name in CPP_CLASS_NAMES:
|
||||
if not ClassDB.class_exists(cpp_class_name):
|
||||
continue
|
||||
var cpp_class = ClassDB.instantiate(cpp_class_name)
|
||||
cpp_classes.append(cpp_class)
|
||||
for method in cpp_class.get_method_list():
|
||||
if not method.name.begins_with(languages[".cpp"]["test_prefix"]):
|
||||
continue
|
||||
var test_id := TestID.new()
|
||||
test_id.name = method.name.trim_prefix(languages[".cpp"]["test_prefix"])
|
||||
test_id.category = "C++/" + cpp_class.get_class().replace("CPPBenchmark", "")
|
||||
test_id.language = ".cpp"
|
||||
test_results[test_id] = null
|
||||
|
||||
|
||||
func get_test_ids() -> Array[TestID]:
|
||||
var rv : Array[TestID] = []
|
||||
@@ -148,7 +180,19 @@ func run_test(test_id: TestID) -> void:
|
||||
# Add a dummy child so that the above check works for subsequent reloads
|
||||
get_tree().current_scene.add_child(Node.new())
|
||||
|
||||
var bench_script = load("res://benchmarks/%s%s" % [test_id.category, test_id.language]).new()
|
||||
var language := test_id.language
|
||||
var bench_script
|
||||
if language != ".cpp":
|
||||
bench_script = load("res://benchmarks/%s%s" % [test_id.category, language]).new()
|
||||
else:
|
||||
var cpp_class_name := "CPPBenchmark" + test_id.category.replace("C++", "").replace("/", "")
|
||||
for cpp_class in cpp_classes:
|
||||
if cpp_class_name == cpp_class.get_class():
|
||||
bench_script = ClassDB.instantiate(cpp_class_name)
|
||||
break
|
||||
if not is_instance_valid(bench_script):
|
||||
printerr("Benchmark not found!")
|
||||
return
|
||||
var results := Results.new()
|
||||
|
||||
# Call and time the function to be tested
|
||||
|
||||
2
thirdparty/sponza/sponza.fbx.import
vendored
2
thirdparty/sponza/sponza.fbx.import
vendored
@@ -35,5 +35,3 @@ _subresources={}
|
||||
fbx/importer=0
|
||||
fbx/allow_geometry_helper_nodes=false
|
||||
fbx/embedded_image_handling=1
|
||||
gltf/naming_version=1
|
||||
gltf/embedded_image_handling=1
|
||||
|
||||
Reference in New Issue
Block a user