From a79b76c8f428faeef0c5c65c5d3413b7429115f1 Mon Sep 17 00:00:00 2001 From: ouczbs Date: Thu, 11 Apr 2024 10:13:15 +0800 Subject: [PATCH] refl benchmark --- engine/3rdparty/xmake.lua | 3 +- .../3rdparty/zlib/include/refl/detail/field.h | 7 + .../zlib/include/refl/detail/field.inl | 45 ++++ .../zlib/include/refl/detail/uclass.h | 13 +- .../zlib/include/refl/detail/uclass.inl | 7 +- .../3rdparty/zlib/include/refl/detail/view.h | 54 ++--- .../zlib/include/refl/detail/view.inl | 206 ++++++------------ engine/3rdparty/zlib/include/refl/refl.h | 1 + engine/3rdparty/zlib/test/refl/vertex.h | 96 ++++---- engine/3rdparty/zlib/test/refl_01.cpp | 128 +++-------- engine/3rdparty/zlib/xmake.lua | 1 + 11 files changed, 236 insertions(+), 325 deletions(-) create mode 100644 engine/3rdparty/zlib/include/refl/detail/field.inl diff --git a/engine/3rdparty/xmake.lua b/engine/3rdparty/xmake.lua index f460306..ebc09d8 100644 --- a/engine/3rdparty/xmake.lua +++ b/engine/3rdparty/xmake.lua @@ -5,4 +5,5 @@ add_requires("tinyobjloader") add_requires("vulkansdk") add_requires("assimp") add_requires("nlohmann_json") -add_requires("ylt") \ No newline at end of file +add_requires("ylt") +add_requires("benchmark") \ No newline at end of file diff --git a/engine/3rdparty/zlib/include/refl/detail/field.h b/engine/3rdparty/zlib/include/refl/detail/field.h index 1a89a2c..d505fe4 100644 --- a/engine/3rdparty/zlib/include/refl/detail/field.h +++ b/engine/3rdparty/zlib/include/refl/detail/field.h @@ -42,6 +42,13 @@ namespace refl { Data data; Default value; uint32_t flag; + + //safe + bool Invoke(std::vector& ArgsList)const; + //unsafe + bool Invoke(const std::vector& ArgsList)const; + + std::vector GetParams() const; }; } \ No newline at end of file diff --git a/engine/3rdparty/zlib/include/refl/detail/field.inl b/engine/3rdparty/zlib/include/refl/detail/field.inl new file mode 100644 index 0000000..42a3fe7 --- /dev/null +++ b/engine/3rdparty/zlib/include/refl/detail/field.inl @@ -0,0 +1,45 @@ +#include "uclass.h" +namespace refl { + bool FieldPtr::Invoke(const std::vector& ArgsList)const{ + auto Call = type->vtable.Call; + if (Call) { + Call(this, ArgsList); + } + return Call; + } + bool FieldPtr::Invoke(std::vector& ArgsList)const { + auto Call = type->vtable.Call; + if (Call) { + auto params = GetParams(); + int paramsSize = params.size(); + int argsSize = ArgsList.size(); + if (argsSize < paramsSize && flag & FIELD_METHOD_VALUE_FLAG) { + auto [argsPtr, valueSize] = value.method(); + if (argsSize + valueSize >= paramsSize) { + for (int i = valueSize + argsSize - paramsSize; i < valueSize; i++) { + ArgsList.push_back(*(argsPtr + i)); + } + argsSize = paramsSize; + } + } + if (argsSize < paramsSize) { + return false; + } + + for (int i = 0; i < paramsSize; i++) { + if (ArgsList[i].cls != params[i] && !ArgsList[i].ConvertTo(params[i])) { + return false; + } + } + Call(this, ArgsList); + } + return Call; + } + std::vector FieldPtr::GetParams() const { + auto GetParams = type->vtable.GetParams; + if (GetParams) { + return GetParams(type); + } + return{}; + } +} \ No newline at end of file diff --git a/engine/3rdparty/zlib/include/refl/detail/uclass.h b/engine/3rdparty/zlib/include/refl/detail/uclass.h index dbaa097..33005b6 100644 --- a/engine/3rdparty/zlib/include/refl/detail/uclass.h +++ b/engine/3rdparty/zlib/include/refl/detail/uclass.h @@ -10,7 +10,7 @@ namespace refl { //function std::vector(*GetParams)(const UClass*); //function - void (*Call)(const FieldPtr&, std::vector&); + void (*Call)(const FieldPtr*, const std::vector&); //object void (*InitObject)(void*); @@ -78,17 +78,6 @@ namespace refl { } return nullptr; } - std::vector GetParams() const { - if (vtable.GetParams) { - return vtable.GetParams(this); - } - return{}; - } - void Call(const FieldPtr& field, std::vector& ArgsList)const{ - if (vtable.Call) { - return vtable.Call(field, ArgsList); - } - } void InitObject(void* ptr)const { if (vtable.InitObject) { vtable.InitObject(ptr); diff --git a/engine/3rdparty/zlib/include/refl/detail/uclass.inl b/engine/3rdparty/zlib/include/refl/detail/uclass.inl index f4d353a..87af7df 100644 --- a/engine/3rdparty/zlib/include/refl/detail/uclass.inl +++ b/engine/3rdparty/zlib/include/refl/detail/uclass.inl @@ -1,4 +1,5 @@ #pragma once +#include #include "uclass.h" namespace refl { template<_ReflCheck_Ctor T> @@ -35,14 +36,14 @@ namespace refl { auto& UList = static_cast(cls)->UList; return { UList.data(), UList.data() + UList.size() }; } - static void Call(const FieldPtr& field, std::vector& ArgsList) { + static void Call(const FieldPtr* field, const std::vector& ArgsList) { if constexpr (std::is_same_v) { - MethodType fptr = (MethodType)field.data.method; + MethodType fptr = (MethodType)field->data.method; auto param = ArgsList.rbegin(); fptr(param++->cast_to()...); } else { - MethodType fptr = (MethodType)field.data.method; + MethodType fptr = (MethodType)field->data.method; auto param = ArgsList.rbegin(); auto ret = ArgsList.begin(); if (ret->cls == &TypeInfo::StaticClass) { diff --git a/engine/3rdparty/zlib/include/refl/detail/view.h b/engine/3rdparty/zlib/include/refl/detail/view.h index fff94f0..a17bf78 100644 --- a/engine/3rdparty/zlib/include/refl/detail/view.h +++ b/engine/3rdparty/zlib/include/refl/detail/view.h @@ -4,46 +4,28 @@ namespace refl { class UClass; class FieldPtr; - class ObjectView { - public: - const char* ptr; - const UClass* cls; - const FieldPtr* cache{nullptr}; - ObjectView(const void* ptr, const UClass* cls) : ptr((const char*)ptr), cls(cls){} - public: - - template - bool Get(const Name& name, T& t); - - template - bool Set(const Name& name, const T& t); - - template - bool Invoke(const Name& name, Args&&... args); - - template - R Invoke(const Name& name, Args&&... args); - - ObjectView Parent(); - }; //生命周期短,适用于传参,不建议保存数据 //只能指向指针,引用=>指针,指针=>指针,T => T*,T的类型丢失 struct ArgsView { public: const void* val; const UClass* cls; - ArgsView(const void* val = nullptr, const UClass* cls = nullptr) : val(val), cls(cls) {} + ArgsView() : val(nullptr), cls(nullptr) {} //右值=>右值压入栈,caller入栈地址 //左值=>caller变量地址 template ArgsView(T&& v): val(&v), cls(&TypeInfo*>::StaticClass){ - if constexpr (std::is_same_v, ArgsView>) { + if constexpr (std::is_same_v, void*>) { + val = v; + cls = &TypeInfo::StaticClass; + } + else if constexpr (std::is_same_v, ArgsView>) { val = v.val; cls = v.cls; } } template//参数 T* => T* - constexpr inline T cast_to() { + constexpr inline T cast_to() const { if constexpr (std::is_pointer_v) { return (T)val; } @@ -55,7 +37,7 @@ namespace refl { } } template - T cast_ret() { + T cast_ret() const { if constexpr (std::is_pointer_v) { return *(T*)val; } @@ -82,4 +64,24 @@ namespace refl { ArgsValueList(const std::vector& args); ~ArgsValueList(); }; + class ObjectView { + public: + const char* ptr; + const UClass* cls; + const FieldPtr* cache{ nullptr }; + ObjectView(const void* ptr, const UClass* cls) : ptr((const char*)ptr), cls(cls) {} + public: + + template + bool Get(const Name& name, T& t); + + template + bool Set(const Name& name, const T& t); + + bool Invoke(const Name& name,const std::vector& ArgsList);//这里是内存分配慢呀,这里是可以改成栈容器的 + + bool Invoke(const Name& name,std::vector& ArgsList); + + ObjectView Parent(); + }; } \ No newline at end of file diff --git a/engine/3rdparty/zlib/include/refl/detail/view.inl b/engine/3rdparty/zlib/include/refl/detail/view.inl index 5e31273..1707fe2 100644 --- a/engine/3rdparty/zlib/include/refl/detail/view.inl +++ b/engine/3rdparty/zlib/include/refl/detail/view.inl @@ -1,146 +1,7 @@ #pragma once #include "uclass.h" +#include "view.h" namespace refl { - template - inline bool ObjectView::Get(const Name& name, T& t) - { - if (cache && cache->name == name) { - _cache_get: bool isChild = cache->type->IsChildOf(true); - if (isChild) { - t = *(T*)(ptr + cache->data.offset); - } - return isChild; - } - auto field = cls->GetField(name, false); - if (field) { - cache = field; - goto _cache_get; - } - if (cls->parent) { - return Parent().Get(name, t); - } - return false; - } - template - inline bool ObjectView::Set(const Name& name, const T& t) - { - if (cache && cache->name == name) { - _cache_set: bool isChild = cache->type->IsChildOf(true); - if (isChild) { - *(T*)(ptr + cache->data.offset) = t; - } - return isChild; - } - auto field = cls->GetField(name, false); - if (field) { - cache = field; - goto _cache_set; - } - if (cls->parent) { - return Parent().Set(name, t); - } - return false; - } - template - bool ObjectView::Invoke(const Name& name, Args&&... args) - { - auto field = cls->GetField(name, true); - if (!field) { - if (cls->parent) { - return Parent().Invoke(name, args...); - } - return false; - } - constexpr int inputSize = sizeof...(Args); - auto params = field->type->GetParams(); - int paramsSize = params.size(); - - std::vector ArgsList; - ArgsList.reserve(paramsSize); - ArgsList.emplace_back(); - - bool member = field->flag & FIELD_MEMBER_FLAG; - if (member) { - ArgsList.emplace_back(ptr, &TypeInfo::StaticClass); - } - (..., (ArgsList.emplace_back(args))); - - - int argsSize = ArgsList.size(); - if (argsSize < paramsSize && field->flag & FIELD_METHOD_VALUE_FLAG) { - auto [argsPtr, valueSize] = field->value.method(); - if (argsSize + valueSize >= paramsSize) { - for (int i = valueSize + argsSize - paramsSize; i < valueSize; i++) { - ArgsList.push_back(*(argsPtr + i)); - } - argsSize = paramsSize; - } - } - - if (argsSize < paramsSize) { - return false; - } - - for (int i = member + 1; i < paramsSize; i++) { - if (ArgsList[i].cls != params[i] && !ArgsList[i].ConvertTo(params[i])) { - return false; - } - } - field->type->Call(*field, ArgsList); - return true; - } - template - R ObjectView::Invoke(const Name& name, Args&&... args) - { - //int x = 1; val = &x; *(int*)val = 2;//(x = 2) return *val; //val=>cast_to - //int* x = nullptr; val = &x; *(int**)val = 0xff1234;//(x = 0xff1234) return *val; - real_type_t data{}; - ArgsView ret{ &data, &TypeInfo*>::StaticClass }; - auto field = cls->GetField(name, true); - if (!field) { - if (cls->parent) { - return Parent().Invoke(name, args...); - } - return ret.cast_ret(); - } - constexpr int inputSize = sizeof...(Args); - auto params = field->type->GetParams(); - int paramsSize = params.size(); - std::vector ArgsList; - ArgsList.reserve(paramsSize); - ArgsList.emplace_back(ret); - - if (field->flag & FIELD_MEMBER_FLAG) { - ArgsList.emplace_back(ptr, &TypeInfo::StaticClass); - } - (..., (ArgsList.emplace_back(args))); - - int argsSize = ArgsList.size(); - if (argsSize < paramsSize && field->flag & FIELD_METHOD_VALUE_FLAG) { - auto [argsPtr, valueSize] = field->value.method(); - if (argsSize + valueSize >= paramsSize) { - for (int i = valueSize + argsSize - paramsSize; i < valueSize; i++) { - ArgsList.push_back(*(argsPtr + i)); - } - argsSize = paramsSize; - } - } - - if (argsSize < paramsSize) { - return ret.cast_ret(); - } - - for (int i = 0; i < paramsSize; i++) { - if (ArgsList[i].cls != params[i] && !ArgsList[i].ConvertTo(params[i])) { - return ret.cast_ret(); - } - } - field->type->Call(*field, ArgsList); - return ret.cast_ret(); - } - ObjectView ObjectView::Parent() { - return { ptr, cls ? cls->parent : nullptr }; - } /*平凡对象的转化要支持吗 * 比如同大小的安全转化 * 对象从小到大 @@ -185,4 +46,69 @@ namespace refl { num = 0; data = nullptr; } + template + inline bool ObjectView::Get(const Name& name, T& t) + { + if (cache && cache->name == name) { + _cache_get: bool isChild = cache->type->IsChildOf(true); + if (isChild) { + t = *(T*)(ptr + cache->data.offset); + } + return isChild; + } + auto field = cls->GetField(name, false); + if (field) { + cache = field; + goto _cache_get; + } + if (cls->parent) { + return Parent().Get(name, t); + } + return false; + } + template + inline bool ObjectView::Set(const Name& name, const T& t) + { + if (cache && cache->name == name) { + _cache_set: bool isChild = cache->type->IsChildOf(true); + if (isChild) { + *(T*)(ptr + cache->data.offset) = t; + } + return isChild; + } + auto field = cls->GetField(name, false); + if (field) { + cache = field; + goto _cache_set; + } + if (cls->parent) { + return Parent().Set(name, t); + } + return false; + } + bool ObjectView::Invoke(const Name& name,const std::vector& ArgsList) + { + auto field = cls->GetField(name, true); + if (!field) { + if (cls->parent) { + return Parent().Invoke(name, ArgsList); + } + return false; + } + return field->Invoke(ArgsList); + } + bool ObjectView::Invoke(const Name& name, std::vector& ArgsList) + { + auto field = cls->GetField(name, true); + if (!field) { + if (cls->parent) { + return Parent().Invoke(name, ArgsList); + } + return false; + } + return field->Invoke(ArgsList); + } + ObjectView ObjectView::Parent() { + return { ptr, cls ? cls->parent : nullptr }; + } } \ No newline at end of file diff --git a/engine/3rdparty/zlib/include/refl/refl.h b/engine/3rdparty/zlib/include/refl/refl.h index ec5de73..231eb71 100644 --- a/engine/3rdparty/zlib/include/refl/refl.h +++ b/engine/3rdparty/zlib/include/refl/refl.h @@ -1,5 +1,6 @@ #include "detail/uclass.inl" #include "detail/view.inl" +#include "detail/field.inl" namespace refl { /* 成员变量需要定义默认值吗?那为什么不在initObjec里初始化?*/ template diff --git a/engine/3rdparty/zlib/test/refl/vertex.h b/engine/3rdparty/zlib/test/refl/vertex.h index 1e41df0..a7ec335 100644 --- a/engine/3rdparty/zlib/test/refl/vertex.h +++ b/engine/3rdparty/zlib/test/refl/vertex.h @@ -1,53 +1,47 @@ -#pragma once -#include -#include -#include +#include +#include "refl/refl.h" using namespace std; -#define sizeof_field(_struct, _field) sizeof(((_struct*)0)->_field) -// 顶点最多关联4个骨骼 -#define MAX_NUM_BONES_PER_VERTEX 4 -struct Vector2 { - float x; - float y; +using namespace refl; +struct vec3_parent { + virtual void norm(int x1, int& x2) { + x2 = x1 * x2; + //cout << x2 << "vec3_parent::norm" << endl; + } }; -struct Vector3 { - float x; - float y; - float z; -}; -struct Vertex { - struct UClass { - virtual void BindLayout() = 0; - - }; -}; -struct PosVertex : public Vertex { - Vector3 Position = {}; - struct UClass : public Vertex::UClass{ - int MemCount = 1; - tuple Position{sizeof_field(PosVertex, Position), offsetof(PosVertex, Position)}; - - virtual void BindLayout() {}; - }; -}; - -struct TexVertex : public Vertex { - Vector3 Position = {}; - Vector3 Normal = {}; - Vector2 TexCoords = {}; -}; -struct BoneVertex : public Vertex -{ - Vector3 Position = {}; - Vector2 TexCoords = {}; - Vector3 Normal = {}; - Vector3 Tangent = {}; - // 骨骼蒙皮数据 - float Weights[MAX_NUM_BONES_PER_VERTEX] = {}; - uint32_t BoneIDs[MAX_NUM_BONES_PER_VERTEX] = {}; - - void AddBoneData(uint32_t boneID, float weight) {}; -}; - - - +struct vec3 : public vec3_parent { + float x = 1; + float y = 2; + float z = 3; + string name{ "hellohellohellohellohellohello" }; + void norm(int x1, int& x2)override { + //x2 = x1 * x2; + //cout << x2 << "vec3::norm" << endl; + } + virtual float norm1(int& x1) { + //x1 = x1 * x * y * z; + //x = x1; + //y = x1 - 1; + //z = x1 - 10; + //cout << x1 << "::norm1" << endl; + return x1; + } + static void norm2(int x1 = 10) { + //cout << x1 << "::norm2" << endl; + } + static void norm3(int x1 = 10) { + x1 = x1 * 10; + //cout << x1 << "::norm3" << endl; + } + using MyUClass = UClass_Custom; + static void BuildClass(MyUClass& cls) { + cls.parent = &TypeInfo::StaticClass; + cls.AttrNum = 3; + cls.FList = { + MakeMemberField(&vec3::x, "x"), + MakeMemberField(&vec3::y, "y"), + MakeMemberField(&vec3::z, "z"), + MakeMethodField(&vec3::norm, "norm", {8, 9}), + MakeMethodField(&vec3::norm1, "norm1",{(float)2.0}) + }; + } +}; \ No newline at end of file diff --git a/engine/3rdparty/zlib/test/refl_01.cpp b/engine/3rdparty/zlib/test/refl_01.cpp index 29fbc78..5c3d28a 100644 --- a/engine/3rdparty/zlib/test/refl_01.cpp +++ b/engine/3rdparty/zlib/test/refl_01.cpp @@ -1,96 +1,40 @@ -#include -#include -#include "refl/refl.h" -#include "vertex.h" -#include "tstring.h" -#include -using namespace std; -using namespace refl; -struct vec3_parent { - virtual void norm(int x1, int& x2) { - x2 = x1 * x2; - cout << x2 << "vec3_parent::norm" << endl; +#include "refl/vertex.h" +#include +void TestRefl1(benchmark::State& state) { + auto cls = &TypeInfo::StaticClass; + vec3 v; + auto ptr = (void*)&v; + auto ov = cls->New(ptr); + int x = 1, y = 2; + for (auto _ : state) { + ov.Invoke("norm", { {},ptr, x, y}); } -}; -struct vec3 : public vec3_parent { - float x = 1; - float y = 2; - float z = 3; - string name{ "hellohellohellohellohellohello" }; - void norm(int x1, int& x2)override { - x2 = x1 * x2; - cout << x2 << "vec3::norm" << endl; +} +BENCHMARK(TestRefl1); +void TestRefl2(benchmark::State& state) { + auto cls = &TypeInfo::StaticClass; + vec3 v; + auto ptr = (void*)&v; + auto ov = cls->New(ptr); + int x = 1, y = 2; + std::vector ArgsList; + ArgsList.emplace_back(); + ArgsList.emplace_back(ptr); + ArgsList.emplace_back(x); + ArgsList.emplace_back(y); + auto field = cls->GetField(cls, "norm", true); + for (auto _ : state) { + field->Invoke(ArgsList); } - virtual float norm1(float& x1) { - cout << x1 << "::norm1" << endl; - return x1; +} +BENCHMARK(TestRefl2); +void TestCPlusPlus(benchmark::State& state) { + vec3 v; + int x = 1, y = 2; + for (auto _ : state) { + v.norm(x, y); } - static void norm2(int x1 = 10) { - cout << x1 << "::norm2" << endl; - } - static void norm3(int x1 = 10) { - x1 = x1 * 10; - cout << x1 << "::norm3" << endl; - } - using MyUClass = UClass_Custom; - static void BuildClass(MyUClass& cls) { - cls.parent = &TypeInfo::StaticClass; - cls.AttrNum = 3; - cls.FList = { - MakeMemberField(&vec3::x, "x"), - MakeMemberField(&vec3::y, "y"), - MakeMemberField(&vec3::z, "z"), - MakeMethodField(&vec3::norm, "norm", {8, 9}), - MakeMethodField(&vec3::norm1, "norm1",{(float)2.0}) - }; - } -}; -int main() { - { - //T = > T* - int x = 1; - auto val = &x; - //T* = > T - //*val; - //x = 2; - *val = 2; - } - { - //T* = > T* - int x = 1, y = 2; - int* px = &x; - auto val = px; - //T* => T* - //val; - //px = &y;//做不到哈 - val = &y; +} +BENCHMARK(TestCPlusPlus); - } - { - //T* => T** - int x = 1, y = 2; - int* px = &x; - auto val = &px; - //T** = > T*; - //*val; - //px = &y; - *val = &y; - } - auto cls = &TypeInfo::StaticClass; - int x = 2, y = 3; - int* q1; - void* q2 = &q1; - *(int**)q2 = &x; - ArgsView a(&y); - ArgsView b(x); - ArgsView c(&q1); - auto ov = cls->New(); - ov.Invoke("norm", x); - ov.Invoke("norm", x); - ov.Invoke("norm", x, y); - auto f = ov.Invoke("norm1"); - vec3* v = (vec3*)ov.ptr; - ov.Invoke("norm1", (float)y); - delete v; - cout << "hello world\n"; -} \ No newline at end of file +BENCHMARK_MAIN(); diff --git a/engine/3rdparty/zlib/xmake.lua b/engine/3rdparty/zlib/xmake.lua index cf90af2..0455c1a 100644 --- a/engine/3rdparty/zlib/xmake.lua +++ b/engine/3rdparty/zlib/xmake.lua @@ -33,6 +33,7 @@ target("zlib_test") target("refl_zlib") set_kind("binary") add_deps("zlib") + add_packages("benchmark") add_includedirs("test/refl") add_files("test/refl_01.cpp") add_headerfiles("test/refl/*.h") \ No newline at end of file