Skip to content

Commit

Permalink
[unreal]优化结构体/容器指针返回的性能,fix #693
Browse files Browse the repository at this point in the history
  • Loading branch information
chexiongsheng committed Mar 11, 2022
1 parent 603c407 commit 0c64722
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 42 deletions.
56 changes: 20 additions & 36 deletions unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,28 +792,18 @@ FJsEnvImpl::~FJsEnvImpl()
auto Isolate = MainIsolate;
v8::Isolate::Scope IsolateScope(Isolate);
v8::HandleScope HandleScope(Isolate);
for (auto Iter = ClassToTemplateMap.begin(); Iter != ClassToTemplateMap.end(); Iter++)
{
Iter->second.Reset();
}

ClassToTemplateMap.clear();

CppObjectMapper.UnInitialize(Isolate);

for (auto Iter = ObjectMap.begin(); Iter != ObjectMap.end(); Iter++)
{
Iter->second.Reset();
}
ObjectMap.clear();

for (auto Iter = GeneratedObjectMap.begin(); Iter != GeneratedObjectMap.end(); Iter++)
{
Iter->second.Reset();
}
GeneratedObjectMap.clear();

for (auto Iter = StructMap.begin(); Iter != StructMap.end(); Iter++)
{
Iter->second.Reset();
}
StructCache.clear();

ContainerCache.clear();

for (auto Iter = ScriptStructFinalizeInfoMap.begin(); Iter != ScriptStructFinalizeInfoMap.end(); Iter++)
{
Expand Down Expand Up @@ -1549,18 +1539,15 @@ v8::Local<v8::Value> FJsEnvImpl::FindOrAdd(v8::Isolate* Isolate, v8::Local<v8::C
}
}

v8::Local<v8::Value> FJsEnvImpl::FindOrAddStruct(
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UScriptStruct* ScriptStruct, void* Ptr, bool PassByPointer)
v8::Local<v8::Value> FJsEnvImpl::FindOrAddStruct(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UScriptStruct* ScriptStruct,
void* Ptr, bool PassByPointer, bool ForceNoCache)
{
check(Ptr); // must not null

//查询历史记录,当初这么改是因为一个结构体如果其第一个成员也是结构体,这个结构体的指针将和这个第一个成员的指针值一样,导致访问该成员也会返回外层结构体
//但问题是目前看,这部分是多余代码了,如果不是传指针才查,但不是传指针每次都是new堆内存,实际上是不可能查找到的,还是走到后面的逻辑
//另外,这有没更好的解决办法呢?记录下ScriptStruct,如果类型不一致才new?
if (!PassByPointer)
if (LIKELY(!ForceNoCache)) // default: false
{
auto Iter = StructMap.find(Ptr);
if (Iter != StructMap.end())
auto Iter = StructCache.find(Ptr);
if (Iter != StructCache.end())
{
return v8::Local<v8::Value>::New(Isolate, Iter->second);
}
Expand Down Expand Up @@ -2405,13 +2392,10 @@ v8::Local<v8::Value> FJsEnvImpl::FindOrAddContainer(v8::Isolate* Isolate, v8::Lo
{
check(Ptr); // must not null

if (!PassByPointer)
auto Iter = ContainerCache.find(Ptr);
if (Iter != ContainerCache.end())
{
auto Iter = StructMap.find(Ptr);
if (Iter != StructMap.end())
{
return v8::Local<v8::Value>::New(Isolate, Iter->second);
}
return v8::Local<v8::Value>::New(Isolate, Iter->second);
}

auto BindTo = v8::External::New(Context->GetIsolate(), Ptr);
Expand Down Expand Up @@ -2451,11 +2435,11 @@ void FJsEnvImpl::BindStruct(
DataTransfer::SetPointer(
MainIsolate, JSObject, static_cast<UScriptStruct*>(ScriptStructWrapper->Struct.Get()), 1); // add type info

StructCache[Ptr] = v8::UniquePersistent<v8::Value>(MainIsolate, JSObject);
if (!PassByPointer)
{
StructMap[Ptr] = v8::UniquePersistent<v8::Value>(MainIsolate, JSObject);
ScriptStructFinalizeInfoMap[Ptr] = {ScriptStructWrapper->Struct, ScriptStructWrapper->ExternalFinalize};
StructMap[Ptr].SetWeak<FScriptStructWrapper>(
StructCache[Ptr].SetWeak<FScriptStructWrapper>(
ScriptStructWrapper, FScriptStructWrapper::OnGarbageCollectedWithFree, v8::WeakCallbackType::kInternalFields);
}
}
Expand All @@ -2469,7 +2453,7 @@ void FJsEnvImpl::BindCppObject(
void FJsEnvImpl::UnBindStruct(void* Ptr)
{
ScriptStructFinalizeInfoMap.erase(Ptr);
StructMap.erase(Ptr);
StructCache.erase(Ptr);
}

void FJsEnvImpl::UnBindCppObject(JSClassDefinition* ClassDefinition, void* Ptr)
Expand All @@ -2480,13 +2464,13 @@ void FJsEnvImpl::UnBindCppObject(JSClassDefinition* ClassDefinition, void* Ptr)
void FJsEnvImpl::BindContainer(void* Ptr, v8::Local<v8::Object> JSObject, void (*Callback)(const v8::WeakCallbackInfo<void>& data))
{
DataTransfer::SetPointer(MainIsolate, JSObject, Ptr, 0);
StructMap[Ptr] = v8::UniquePersistent<v8::Value>(MainIsolate, JSObject);
StructMap[Ptr].SetWeak<void>(nullptr, Callback, v8::WeakCallbackType::kInternalFields);
ContainerCache[Ptr] = v8::UniquePersistent<v8::Value>(MainIsolate, JSObject);
ContainerCache[Ptr].SetWeak<void>(nullptr, Callback, v8::WeakCallbackType::kInternalFields);
}

void FJsEnvImpl::UnBindContainer(void* Ptr)
{
StructMap.erase(Ptr);
ContainerCache.erase(Ptr);
}

std::shared_ptr<FStructWrapper> FJsEnvImpl::GetStructWrapper(UStruct* InStruct)
Expand Down
8 changes: 5 additions & 3 deletions unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ class FJsEnvImpl : public IJsEnv, IObjectMapper, public FUObjectArray::FUObjectD

virtual void UnBindCppObject(JSClassDefinition* ClassDefinition, void* Ptr) override;

virtual v8::Local<v8::Value> FindOrAddStruct(
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UScriptStruct* ScriptStruct, void* Ptr, bool PassByPointer) override;
virtual v8::Local<v8::Value> FindOrAddStruct(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UScriptStruct* ScriptStruct,
void* Ptr, bool PassByPointer, bool ForceNoCache) override;

virtual void BindCppObject(v8::Isolate* InIsolate, JSClassDefinition* ClassDefinition, void* Ptr,
v8::Local<v8::Object> JSObject, bool PassByPointer) override;
Expand Down Expand Up @@ -468,7 +468,9 @@ class FJsEnvImpl : public IJsEnv, IObjectMapper, public FUObjectArray::FUObjectD
std::map<UObject*, v8::UniquePersistent<v8::Value>> ObjectMap;
std::map<const class UObjectBase*, v8::UniquePersistent<v8::Value>> GeneratedObjectMap;

std::map<void*, v8::UniquePersistent<v8::Value>> StructMap;
std::map<void*, v8::UniquePersistent<v8::Value>> StructCache;

std::map<void*, v8::UniquePersistent<v8::Value>> ContainerCache;

FCppObjectMapper CppObjectMapper;

Expand Down
7 changes: 5 additions & 2 deletions unreal/Puerts/Source/JsEnv/Private/ObjectMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,11 @@ class IObjectMapper : public ICppObjectMapper

virtual void UnBindStruct(void* Ptr) = 0;

virtual v8::Local<v8::Value> FindOrAddStruct(
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UScriptStruct* ScriptStruct, void* Ptr, bool PassByPointer) = 0;
// PassByPointer为false代表需要在js对象释放时,free相应的内存
// ForceNoCache强制别cache,在结构体嵌套时,第一个成员为结构体时,可强制别cache
// 相关信息见该issue:https://github.com/Tencent/puerts/issues/693
virtual v8::Local<v8::Value> FindOrAddStruct(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UScriptStruct* ScriptStruct,
void* Ptr, bool PassByPointer, bool ForceNoCache = false) = 0;

virtual void Merge(
v8::Isolate* Isolate, v8::Local<v8::Context> Context, v8::Local<v8::Object> Src, UStruct* DesType, void* Des) = 0;
Expand Down
11 changes: 10 additions & 1 deletion unreal/Puerts/Source/JsEnv/Private/PropertyTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,15 @@ class FScriptStructPropertyTranslator : public FPropertyWithDestructorReflection
{
ParamShallowCopySize = StructProperty->Struct->GetStructureSize();
}
#if ENGINE_MINOR_VERSION >= 25 || ENGINE_MAJOR_VERSION > 4
auto Owner = Property->GetOwnerUObject();
#else
auto Owner = Property->GetOuter();
#endif
if (Owner && Owner->IsA<UScriptStruct>() && Property->GetOffset_ForInternal() == 0)
{
ForceNoCache = true;
}
}

v8::Local<v8::Value> UEToJs(
Expand All @@ -569,7 +578,7 @@ class FScriptStructPropertyTranslator : public FPropertyWithDestructorReflection
StructProperty->CopySingleValue(Ptr, ValuePtr);
}
return FV8Utils::IsolateData<IObjectMapper>(Isolate)->FindOrAddStruct(
Isolate, Context, StructProperty->Struct, Ptr, PassByPointer);
Isolate, Context, StructProperty->Struct, Ptr, PassByPointer, ForceNoCache);
}

bool JsToUE(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::Local<v8::Value>& Value, void* ValuePtr,
Expand Down
2 changes: 2 additions & 0 deletions unreal/Puerts/Source/JsEnv/Private/PropertyTranslator.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ class FPropertyTranslator

std::unique_ptr<FPropertyTranslator> Inner;

bool ForceNoCache = false;

static void Getter(const v8::FunctionCallbackInfo<v8::Value>& Info);

void Getter(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::FunctionCallbackInfo<v8::Value>& Info);
Expand Down

0 comments on commit 0c64722

Please sign in to comment.