初始化提交
This commit is contained in:
		
							
								
								
									
										248
									
								
								Plugins/slua_unreal/Source/slua_profile/Private/slua_profile.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								Plugins/slua_unreal/Source/slua_profile/Private/slua_profile.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,248 @@ | ||||
| // Tencent is pleased to support the open source community by making sluaunreal available. | ||||
|  | ||||
| // Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights reserved. | ||||
| // Licensed under the BSD 3-Clause License (the "License");  | ||||
| // you may not use this file except in compliance with the License. You may obtain a copy of the License at | ||||
|  | ||||
| // https://opensource.org/licenses/BSD-3-Clause | ||||
|  | ||||
| // Unless required by applicable law or agreed to in writing,  | ||||
| // software distributed under the License is distributed on an "AS IS" BASIS,  | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | ||||
| // See the License for the specific language governing permissions and limitations under the License. | ||||
|  | ||||
| #include "slua_profile.h" | ||||
| #include "Framework/MultiBox/MultiBoxBuilder.h" | ||||
| #include "HAL/FileManager.h" | ||||
| #include "Containers/Ticker.h" | ||||
| #include "LuaState.h" | ||||
| #if WITH_EDITOR | ||||
| #include "LevelEditor.h" | ||||
| #include "EditorStyle.h" | ||||
| #include "EditorStyleSet.h" | ||||
| #endif | ||||
|  | ||||
| #include "LuaProfiler.h" | ||||
| #include "slua_remote_profile.h" | ||||
| #include "ProfileDataDefine.h" | ||||
| #include "SluaProfilerDataManager.h" | ||||
|  | ||||
| DEFINE_LOG_CATEGORY(LogSluaProfile) | ||||
| #define LOCTEXT_NAMESPACE "Fslua_profileModule" | ||||
| #define ROOT_NAME "ROOT" | ||||
| namespace { | ||||
|     static const FName slua_profileTabName(TEXT("slua_profile")); | ||||
|  | ||||
|     typedef TMap<int64, NS_SLUA::LuaMemInfo> LuaMemInfoMap; | ||||
|     LuaMemInfoMap memoryInfo; | ||||
|  | ||||
|     typedef TQueue<MemoryFramePtr, EQueueMode::Mpsc> MemoryFrameQueue; | ||||
|     MemoryFrameQueue memoryQueue; | ||||
|     MemoryFramePtr currentMemory = MakeShareable(new MemoryFrame()); | ||||
|  | ||||
|     ProfileCallInfoArray profilerStack; | ||||
|     ProfileNodePtr funcProfilerRoot; | ||||
|     TQueue<ProfileNodePtr, EQueueMode::Mpsc> funcProfilerNodeQueue; | ||||
| } | ||||
|  | ||||
| void Fslua_profileModule::StartupModule() | ||||
| { | ||||
| #if WITH_EDITOR | ||||
|     Flua_profileCommands::Register(); | ||||
|  | ||||
|     PluginCommands = MakeShareable(new FUICommandList); | ||||
|  | ||||
|     PluginCommands->MapAction( | ||||
|         Flua_profileCommands::Get().OpenPluginWindow, | ||||
|         FExecuteAction::CreateRaw(this, &Fslua_profileModule::PluginButtonClicked), | ||||
|         FCanExecuteAction()); | ||||
|  | ||||
|     FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor"); | ||||
|  | ||||
|     { | ||||
|         TSharedPtr<FExtender> MenuExtender = MakeShareable(new FExtender()); | ||||
|         MenuExtender->AddMenuExtension("WindowLayout", EExtensionHook::After, PluginCommands, FMenuExtensionDelegate::CreateRaw(this, &Fslua_profileModule::AddMenuExtension)); | ||||
|  | ||||
|         LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuExtender); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     if (GIsEditor && !IsRunningCommandlet()) | ||||
|     { | ||||
|         sluaProfilerInspector = MakeShareable(new SProfilerInspector); | ||||
|         FGlobalTabmanager::Get()->RegisterNomadTabSpawner(slua_profileTabName, | ||||
|             FOnSpawnTab::CreateRaw(this, &Fslua_profileModule::OnSpawnPluginTab)) | ||||
|             .SetDisplayName(LOCTEXT("Flua_wrapperTabTitle", "slua Profiler")) | ||||
|             .SetMenuType(ETabSpawnerMenuType::Hidden); | ||||
|         TickDelegate = FTickerDelegate::CreateRaw(this, &Fslua_profileModule::Tick); | ||||
| #if ENGINE_MAJOR_VERSION==5 | ||||
|         TickDelegateHandle = FTSTicker::GetCoreTicker().AddTicker(TickDelegate); | ||||
| #else | ||||
|         TickDelegateHandle = FTicker::GetCoreTicker().AddTicker(TickDelegate); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void Fslua_profileModule::ShutdownModule() | ||||
| { | ||||
| #if WITH_EDITOR | ||||
|     sluaProfilerInspector = nullptr; | ||||
|     ClearCurProfiler(); | ||||
|  | ||||
|     Flua_profileCommands::Unregister(); | ||||
|  | ||||
|     FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(slua_profileTabName); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void Fslua_profileModule::PluginButtonClicked() | ||||
| { | ||||
| #if (ENGINE_MINOR_VERSION<25) && (ENGINE_MAJOR_VERSION==4) | ||||
|     FGlobalTabmanager::Get()->InvokeTab(slua_profileTabName); | ||||
| #else | ||||
|     FGlobalTabmanager::Get()->TryInvokeTab(slua_profileTabName); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| bool Fslua_profileModule::Tick(float DeltaTime) | ||||
| { | ||||
|     if (!tabOpened) | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|     //UE_LOG(LogTemp, Warning, TEXT("Fslua_profileModule::Tick")); | ||||
|     while (!funcProfilerNodeQueue.IsEmpty()) | ||||
|     { | ||||
|         MemoryFramePtr memoryFrame; | ||||
|         memoryQueue.Dequeue(memoryFrame); | ||||
|         TSharedPtr<FunctionProfileNode> funcProfilerNode; | ||||
|         funcProfilerNodeQueue.Dequeue(funcProfilerNode); | ||||
|         sluaProfilerInspector->Refresh(funcProfilerNode, memoryInfo, memoryFrame); | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| TSharedRef<class SDockTab> Fslua_profileModule::OnSpawnPluginTab(const FSpawnTabArgs& SpawnTabArgs) | ||||
| { | ||||
|     if (sluaProfilerInspector.IsValid()) | ||||
|     { | ||||
|         sluaProfilerInspector->StartChartRolling(); | ||||
|         auto tab = sluaProfilerInspector->GetSDockTab(); | ||||
|  | ||||
|         tab->SetOnTabClosed(SDockTab::FOnTabClosedCallback::CreateRaw(this, &Fslua_profileModule::OnTabClosed)); | ||||
|  | ||||
|         SluaProfilerDataManager::InitProfileNode(funcProfilerRoot, *FLuaFunctionDefine::Root, 0); | ||||
|         sluaProfilerInspector->ProfileServer = MakeShareable(new NS_SLUA::FProfileServer()); | ||||
|         sluaProfilerInspector->ProfileServer->OnProfileMessageRecv().BindLambda([this](NS_SLUA::FProfileMessagePtr Message) { | ||||
|             this->debug_hook_c(Message); | ||||
|             }); | ||||
|  | ||||
|         tabOpened = true; | ||||
|         return tab; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         return SNew(SDockTab).TabRole(ETabRole::NomadTab); | ||||
|     } | ||||
| } | ||||
|  | ||||
| ////////////////////////////////////////////////////////////////////////// | ||||
| #if WITH_EDITOR | ||||
| Flua_profileCommands::Flua_profileCommands() | ||||
|     : TCommands<Flua_profileCommands>(slua_profileTabName, | ||||
| #if ENGINE_MAJOR_VERSION==5 && ENGINE_MINOR_VERSION>0 | ||||
|         NSLOCTEXT("Contexts", "slua_profile", "slua_profile Plugin"), NAME_None, FAppStyle::GetAppStyleSetName()) | ||||
| #else | ||||
|         NSLOCTEXT("Contexts", "slua_profile", "slua_profile Plugin"), NAME_None, FEditorStyle::GetStyleSetName()) | ||||
| #endif | ||||
| { | ||||
| } | ||||
|  | ||||
| void Flua_profileCommands::RegisterCommands() | ||||
| { | ||||
|     UI_COMMAND(OpenPluginWindow, "slua Profile", "Open slua Profile tool", EUserInterfaceActionType::Button, FInputGesture()); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| void Fslua_profileModule::ClearCurProfiler() | ||||
| { | ||||
|     SluaProfilerDataManager::InitProfileNode(funcProfilerRoot, *FLuaFunctionDefine::Root, 0); | ||||
|     currentMemory = MakeShareable(new MemoryFrame()); | ||||
|     currentMemory->bMemoryTick = false; | ||||
|     profilerStack.Empty(); | ||||
| } | ||||
|  | ||||
| void Fslua_profileModule::AddMenuExtension(FMenuBuilder& Builder) | ||||
| { | ||||
| #if WITH_EDITOR | ||||
|     Builder.AddMenuEntry(Flua_profileCommands::Get().OpenPluginWindow); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void Fslua_profileModule::OnTabClosed(TSharedRef<SDockTab>) | ||||
| { | ||||
|     tabOpened = false; | ||||
| } | ||||
|  | ||||
| void Fslua_profileModule::debug_hook_c(NS_SLUA::FProfileMessagePtr Message) | ||||
| { | ||||
|     //int event, double nanoseconds, int linedefined, const FString& name, const FString& short_src, TArray<NS_SLUA::LuaMemInfo> memoryInfoList | ||||
|     int event = Message->Event; | ||||
|     double nanoseconds = Message->Time; | ||||
|     int linedefined = Message->Linedefined; | ||||
|     const FString& name = Message->Name; | ||||
|     const FString& short_src = Message->ShortSrc; | ||||
|     if (event == NS_SLUA::ProfilerHookEvent::PHE_CALL) | ||||
|     { | ||||
|         if (linedefined == -1 && name.IsEmpty()) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|         //UE_LOG(LogTemp, Log, TEXT("Profile Call %s"), *functionName); | ||||
|  | ||||
|         SluaProfilerDataManager::WatchBegin(short_src, linedefined, name, nanoseconds, funcProfilerRoot, profilerStack); | ||||
|     } | ||||
|     else if (event == NS_SLUA::ProfilerHookEvent::PHE_RETURN) | ||||
|     { | ||||
|         if (linedefined == -1 && name.IsEmpty()) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|          | ||||
|         //UE_LOG(LogTemp, Log, TEXT("Profile Return %s"), *functionName); | ||||
|  | ||||
|         SluaProfilerDataManager::WatchEnd(short_src, linedefined, name, nanoseconds, profilerStack); | ||||
|     } | ||||
|     else if (event == NS_SLUA::ProfilerHookEvent::PHE_TICK) | ||||
|     { | ||||
|         funcProfilerNodeQueue.Enqueue(funcProfilerRoot); | ||||
|         memoryQueue.Enqueue(currentMemory); | ||||
|         ClearCurProfiler(); | ||||
|     } | ||||
|     else if (event == NS_SLUA::ProfilerHookEvent::PHE_MEMORY_TICK) | ||||
|     { | ||||
|         currentMemory->memoryInfoList = Message->memoryInfoList; | ||||
|         currentMemory->bMemoryTick = true; | ||||
|     } | ||||
|     else if (event == NS_SLUA::ProfilerHookEvent::PHE_MEMORY_INCREACE) | ||||
|     { | ||||
|         currentMemory->memoryIncrease = Message->memoryIncrease; | ||||
|     } | ||||
|     else if (event == NS_SLUA::ProfilerHookEvent::PHE_ENTER_COROUTINE) | ||||
|     { | ||||
|         //UE_LOG(LogTemp, Log, TEXT("Profile CoBegin %s"), *functionName); | ||||
|          | ||||
|         SluaProfilerDataManager::CoroutineBegin(linedefined, name, nanoseconds, funcProfilerRoot, profilerStack); | ||||
|     } | ||||
|     else if (event == NS_SLUA::ProfilerHookEvent::PHE_EXIT_COROUTINE) | ||||
|     { | ||||
|         //UE_LOG(LogTemp, Log, TEXT("Profile CoEnd")); | ||||
|         SluaProfilerDataManager::CoroutineEnd(nanoseconds, profilerStack); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #undef LOCTEXT_NAMESPACE | ||||
|  | ||||
| IMPLEMENT_MODULE(Fslua_profileModule, slua_profile) | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -0,0 +1,389 @@ | ||||
| // Tencent is pleased to support the open source community by making sluaunreal available. | ||||
|  | ||||
| // Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights reserved. | ||||
| // Licensed under the BSD 3-Clause License (the "License");  | ||||
| // you may not use this file except in compliance with the License. You may obtain a copy of the License at | ||||
|  | ||||
| // https://opensource.org/licenses/BSD-3-Clause | ||||
|  | ||||
| // Unless required by applicable law or agreed to in writing,  | ||||
| // software distributed under the License is distributed on an "AS IS" BASIS,  | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | ||||
| // See the License for the specific language governing permissions and limitations under the License. | ||||
|  | ||||
| #include "slua_remote_profile.h" | ||||
| #include "slua_profile.h" | ||||
| #include "Common/TcpListener.h" | ||||
| #include "Templates/SharedPointer.h" | ||||
| #include "SocketSubsystem.h" | ||||
| #include "SluaUtil.h" | ||||
| #include "LuaProfiler.h" | ||||
|  | ||||
| FAutoConsoleVariableRef CVarSluaProfilerPort( | ||||
|     TEXT("slua.ProfilerPort"), | ||||
|     NS_SLUA::FProfileServer::Port, | ||||
|     TEXT("Slua profiler server port.\n"), | ||||
|     ECVF_Default); | ||||
|  | ||||
| namespace NS_SLUA | ||||
| { | ||||
|     int32 FProfileServer::Port = 8081; | ||||
|  | ||||
|     FProfileServer::FProfileServer() | ||||
|         : Thread(nullptr) | ||||
|         , bStop(true) | ||||
|     { | ||||
|         Thread = FRunnableThread::Create(this, TEXT("FProfileServer"), 0, TPri_Normal); | ||||
|     } | ||||
|  | ||||
|     FProfileServer::~FProfileServer() | ||||
|     { | ||||
|         StopTransport(); | ||||
|          | ||||
|         Thread->WaitForCompletion(); | ||||
|         delete Thread; | ||||
|     } | ||||
|  | ||||
|     FOnProfileMessageDelegate& FProfileServer::OnProfileMessageRecv() | ||||
|     { | ||||
|         return OnProfileMessageDelegate; | ||||
|     } | ||||
|  | ||||
|     bool FProfileServer::Init() | ||||
|     { | ||||
|         bStop = false; | ||||
|  | ||||
|         ListenEndpoint.Address = FIPv4Address(0, 0, 0, 0); | ||||
|         ListenEndpoint.Port = (std::numeric_limits<uint16>::min() < Port) && (Port < std::numeric_limits<uint16>::max()) ? Port : 8081; | ||||
|         Listener = new FTcpListener(ListenEndpoint); | ||||
|         Listener->OnConnectionAccepted().BindRaw(this, &FProfileServer::HandleConnectionAccepted); | ||||
|         return true; | ||||
|     } | ||||
|      | ||||
|     TArray<TSharedPtr<FProfileConnection>> FProfileServer::GetConnections() { | ||||
|         return Connections; | ||||
|     } | ||||
|  | ||||
|     uint32 FProfileServer::Run() | ||||
|     { | ||||
|         while (!bStop) | ||||
|         { | ||||
|             TSharedPtr<FProfileConnection> Connection; | ||||
|             while (PendingConnections.Dequeue(Connection)) | ||||
|             { | ||||
|                 Connection->Start(); | ||||
|                 Connections.Add(Connection); | ||||
|             } | ||||
|  | ||||
|             int32 ActiveConnections = 0; | ||||
|             for (int32 Index = 0; Index < Connections.Num(); Index++) | ||||
|             { | ||||
|                 auto& conn = Connections[Index]; | ||||
|  | ||||
|                 // handle disconnected by remote | ||||
|                 switch (conn->GetConnectionState()) | ||||
|                 { | ||||
|                 case FProfileConnection::STATE_Connected: | ||||
|                     ActiveConnections++; | ||||
|                     break; | ||||
|  | ||||
|                 case FProfileConnection::STATE_Disconnected: | ||||
|                     Connections.RemoveAtSwap(Index); | ||||
|                     Index--; | ||||
|                     break; | ||||
|  | ||||
|                 default: | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             for (auto& conn : Connections) | ||||
|             { | ||||
|                 TSharedPtr<FProfileMessage, ESPMode::ThreadSafe> Message; | ||||
|  | ||||
|                 while (conn->ReceiveData(Message)) | ||||
|                 { | ||||
|                     (void)OnProfileMessageDelegate.ExecuteIfBound(Message); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             FPlatformProcess::Sleep(ActiveConnections > 0 ? 0.01f : 1.f); | ||||
|         } | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     void FProfileServer::Stop() | ||||
|     { | ||||
|         bStop = true; | ||||
|     } | ||||
|  | ||||
|     void FProfileServer::StopTransport() | ||||
|     { | ||||
|         bStop = true; | ||||
|  | ||||
|         if (Listener) | ||||
|         { | ||||
|             delete Listener; | ||||
|             Listener = nullptr; | ||||
|         } | ||||
|  | ||||
|         for (auto& Connection : Connections) | ||||
|         { | ||||
|             Connection->Close(); | ||||
|         } | ||||
|  | ||||
|         Connections.Empty(); | ||||
|         PendingConnections.Empty(); | ||||
|     } | ||||
|  | ||||
|     bool FProfileServer::HandleConnectionAccepted(FSocket* ClientSocket, const FIPv4Endpoint& ClientEndpoint) | ||||
|     { | ||||
|         PendingConnections.Enqueue(MakeShareable(new FProfileConnection(ClientSocket, ClientEndpoint))); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     FProfileConnection::FProfileConnection(FSocket* InSocket, const FIPv4Endpoint& InRemoteEndpoint) | ||||
|         : RemoteEndpoint(InRemoteEndpoint) | ||||
|         , Socket(InSocket) | ||||
|         , Thread(nullptr) | ||||
|         , TotalBytesReceived(0) | ||||
|         , RecvMessageDataRemaining(0) | ||||
|         , hookEvent(0) | ||||
|         , ConnectionState(EConnectionState::STATE_Connecting) | ||||
|         , bRun(false) | ||||
|     { | ||||
|         int32 NewSize = 0; | ||||
|         // Socket->IsNotEncrypt = true; // For PUBG Mobile | ||||
|         Socket->SetReceiveBufferSize(2 * 1024 * 1024, NewSize); | ||||
|         Socket->SetSendBufferSize(2 * 1024 * 1024, NewSize); | ||||
|     } | ||||
|  | ||||
|     FProfileConnection::~FProfileConnection() | ||||
|     { | ||||
|         if (Thread != nullptr) | ||||
|         { | ||||
|             if (bRun) | ||||
|             { | ||||
|                 bRun = false; | ||||
|                 Thread->WaitForCompletion(); | ||||
|             } | ||||
|             delete Thread; | ||||
|         } | ||||
|  | ||||
|         if (Socket) | ||||
|         { | ||||
|             Socket->Close(); | ||||
|             ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(Socket); | ||||
|             Socket = nullptr; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void FProfileConnection::Start() | ||||
|     { | ||||
|         check(Thread == nullptr); | ||||
|         bRun = true; | ||||
|         Thread = FRunnableThread::Create(this, *FString::Printf(TEXT("FProfileConnection %s"), *RemoteEndpoint.ToString()), 128 * 1024, TPri_Normal); | ||||
|     } | ||||
|  | ||||
|     FProfileConnection::EConnectionState FProfileConnection::GetConnectionState() const | ||||
|     { | ||||
|         return ConnectionState; | ||||
|     } | ||||
|  | ||||
|     bool FProfileConnection::ReceiveData(TSharedPtr<FProfileMessage, ESPMode::ThreadSafe>& OutMessage) | ||||
|     { | ||||
|         if (Inbox.Dequeue(OutMessage)) | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     void FProfileConnection::Close() | ||||
|     { | ||||
|         // let the thread shutdown on its own | ||||
|         if (Thread != nullptr) | ||||
|         { | ||||
|             bRun = false; | ||||
|             Thread->WaitForCompletion(); | ||||
|             delete Thread; | ||||
|             Thread = nullptr; | ||||
|         } | ||||
|  | ||||
|         // if there a socket, close it so our peer will get a quick disconnect notification | ||||
|         if (Socket) | ||||
|         { | ||||
|             Socket->Close(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     bool FProfileConnection::Init() | ||||
|     { | ||||
|         ConnectionState = EConnectionState::STATE_Connected; | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     FSocket* FProfileConnection::GetSocket() | ||||
|     { | ||||
|         if(Socket) return Socket; | ||||
|         return nullptr; | ||||
|     } | ||||
|      | ||||
|     uint32 FProfileConnection::Run() | ||||
|     { | ||||
|           | ||||
|         while (bRun) | ||||
|         { | ||||
|             if ((!ReceiveMessages() || Socket->GetConnectionState() == SCS_ConnectionError) && bRun) | ||||
|             { | ||||
|                 bRun = false; | ||||
|             } | ||||
|  | ||||
|             FPlatformProcess::SleepNoStats(0.0001f); | ||||
|         } | ||||
|  | ||||
|         ConnectionState = EConnectionState::STATE_Disconnected; | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     void FProfileConnection::Stop() | ||||
|     { | ||||
|         if (Socket) | ||||
|         { | ||||
|             Socket->Close(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void FProfileConnection::Exit() | ||||
|     { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     bool FProfileConnection::ReceiveMessages() | ||||
|     { | ||||
|         ISocketSubsystem* SocketSubsystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM); | ||||
|         uint32 PendingDataSize = 0; | ||||
|  | ||||
|         // check if the socket has closed | ||||
|         { | ||||
|             int32 BytesRead; | ||||
|             uint8 Dummy; | ||||
|             if (!Socket->Recv(&Dummy, 1, BytesRead, ESocketReceiveFlags::Peek)) | ||||
|             { | ||||
|                 UE_LOG(LogSluaProfile, Verbose, TEXT("Dummy read failed with code %d"), (int32)SocketSubsystem->GetLastErrorCode()); | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Block waiting for some data | ||||
|         if (!Socket->Wait(ESocketWaitConditions::WaitForRead, FTimespan::FromSeconds(1.0))) | ||||
|         { | ||||
|             return (Socket->GetConnectionState() != SCS_ConnectionError); | ||||
|         } | ||||
|  | ||||
|         // keep going until we have no data. | ||||
|         for (;;) | ||||
|         { | ||||
|             int32 BytesRead = 0; | ||||
|             // See if we're in the process of receiving a (large) message | ||||
|             if (RecvMessageDataRemaining == 0) | ||||
|             { | ||||
|                 // no partial message. Try to receive the size of a message | ||||
|                 if (!Socket->HasPendingData(PendingDataSize) || (PendingDataSize < sizeof(uint32))) | ||||
|                 { | ||||
|                     // no messages | ||||
|                     return true; | ||||
|                 } | ||||
|  | ||||
|                 FArrayReader MessagesizeData = FArrayReader(true); | ||||
|                 MessagesizeData.SetNumUninitialized(sizeof(uint32)); | ||||
|  | ||||
|                 // read message size from the stream | ||||
|                 BytesRead = 0; | ||||
|                 if (!Socket->Recv(MessagesizeData.GetData(), sizeof(uint32), BytesRead)) | ||||
|                 { | ||||
|                     UE_LOG(LogSluaProfile, Verbose, TEXT("In progress read failed with code %d"), (int32)SocketSubsystem->GetLastErrorCode()); | ||||
|                     return false; | ||||
|                 } | ||||
|  | ||||
|                 check(BytesRead == sizeof(uint32)); | ||||
|                 TotalBytesReceived += BytesRead; | ||||
|                 // Setup variables to receive the message | ||||
|                 MessagesizeData << RecvMessageDataRemaining; | ||||
|  | ||||
|                 RecvMessageData = MakeShareable(new FArrayReader(true)); | ||||
|                 RecvMessageData->SetNumUninitialized(RecvMessageDataRemaining); | ||||
|                 check(RecvMessageDataRemaining > 0); | ||||
|             } | ||||
|  | ||||
|             BytesRead = 0; | ||||
|             if (!Socket->Recv(RecvMessageData->GetData() + RecvMessageData->Num() - RecvMessageDataRemaining, RecvMessageDataRemaining, BytesRead)) | ||||
|             { | ||||
|                 UE_LOG(LogSluaProfile, Verbose, TEXT("Read failed with code %d"), (int32)SocketSubsystem->GetLastErrorCode()); | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             if (BytesRead > 0) | ||||
|             { | ||||
|                 check(BytesRead <= RecvMessageDataRemaining); | ||||
|                 TotalBytesReceived += BytesRead; | ||||
|                 RecvMessageDataRemaining -= BytesRead; | ||||
|                 if (RecvMessageDataRemaining == 0) | ||||
|                 { | ||||
|                     FProfileMessage* DeserializedMessage = new FProfileMessage(); | ||||
|                     if (DeserializedMessage->Deserialize(RecvMessageData)) | ||||
|                     { | ||||
|                         Inbox.Enqueue(MakeShareable(DeserializedMessage)); | ||||
|                     } | ||||
|                     RecvMessageData.Reset(); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // no data | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     FProfileMessage::FProfileMessage() | ||||
|         : Event(0) | ||||
|         , Time(0) | ||||
|         , Linedefined(-1) | ||||
|         , Name() | ||||
|         , ShortSrc() | ||||
|     { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     FProfileMessage::~FProfileMessage() | ||||
|     { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     bool FProfileMessage::Deserialize(const TSharedPtr<FArrayReader, ESPMode::ThreadSafe>& Message) | ||||
|     { | ||||
|         FArrayReader& MessageReader = Message.ToSharedRef().Get(); | ||||
|  | ||||
|         MessageReader << Event; | ||||
|         switch (Event) | ||||
|         { | ||||
|         case NS_SLUA::ProfilerHookEvent::PHE_MEMORY_TICK: | ||||
|             MessageReader << memoryInfoList; | ||||
|             return true; | ||||
|         case NS_SLUA::ProfilerHookEvent::PHE_MEMORY_INCREACE: | ||||
|             MessageReader << memoryIncrease; | ||||
|             return true; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|          | ||||
|         MessageReader << Time; | ||||
|         MessageReader << Linedefined; | ||||
|         MessageReader << Name; | ||||
|         MessageReader << ShortSrc; | ||||
|          | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,79 @@ | ||||
| // Tencent is pleased to support the open source community by making sluaunreal available. | ||||
|  | ||||
| // Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights reserved. | ||||
| // Licensed under the BSD 3-Clause License (the "License");  | ||||
| // you may not use this file except in compliance with the License. You may obtain a copy of the License at | ||||
|  | ||||
| // https://opensource.org/licenses/BSD-3-Clause | ||||
|  | ||||
| // Unless required by applicable law or agreed to in writing,  | ||||
| // software distributed under the License is distributed on an "AS IS" BASIS,  | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | ||||
| // See the License for the specific language governing permissions and limitations under the License. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "CoreMinimal.h" | ||||
| #include "Containers/Ticker.h" | ||||
| #include "Modules/ModuleManager.h" | ||||
| #include "Framework/Commands/Commands.h" | ||||
| #include "slua_profile_inspector.h" | ||||
| #include "LuaMemoryProfile.h" | ||||
| #include "slua_profile.h" | ||||
|  | ||||
| /** Declares a log category for this module. */ | ||||
| DECLARE_LOG_CATEGORY_EXTERN(LogSluaProfile, Log, All); | ||||
|  | ||||
| namespace NS_SLUA | ||||
| { | ||||
|     class FProfileServer; | ||||
| } | ||||
|  | ||||
| class SLUA_PROFILE_API Fslua_profileModule : public IModuleInterface | ||||
| { | ||||
| public: | ||||
|  | ||||
|     /** IModuleInterface implementation */ | ||||
|     virtual void StartupModule() override; | ||||
|     virtual void ShutdownModule() override; | ||||
|  | ||||
|  | ||||
|     void PluginButtonClicked(); | ||||
| private: | ||||
|     // fields | ||||
|     FTickerDelegate TickDelegate; | ||||
| #if ENGINE_MAJOR_VERSION==5 | ||||
|     FTSTicker::FDelegateHandle TickDelegateHandle; | ||||
| #else | ||||
|     FDelegateHandle TickDelegateHandle; | ||||
| #endif | ||||
|  | ||||
|     TSharedPtr<SProfilerInspector> sluaProfilerInspector; | ||||
|     bool tabOpened = false; | ||||
|     TSharedPtr<class FUICommandList> PluginCommands; | ||||
|  | ||||
|     // functions | ||||
|     void OnTabClosed(TSharedRef<SDockTab> tab); | ||||
|  | ||||
|     TSharedRef<class SDockTab> OnSpawnPluginTab(const class FSpawnTabArgs& SpawnTabArgs); | ||||
|     bool Tick(float DeltaTime); | ||||
|     void ClearCurProfiler(); | ||||
|     void AddMenuExtension(FMenuBuilder& Builder); | ||||
|  | ||||
|     void debug_hook_c(NS_SLUA::FProfileMessagePtr Message); | ||||
| }; | ||||
|  | ||||
| #if WITH_EDITOR | ||||
| class Flua_profileCommands : public TCommands<Flua_profileCommands> | ||||
| { | ||||
| public: | ||||
|  | ||||
|     Flua_profileCommands(); | ||||
|  | ||||
|     // TCommands<> interface | ||||
|     virtual void RegisterCommands() override; | ||||
|  | ||||
| public: | ||||
|     TSharedPtr< FUICommandInfo > OpenPluginWindow; | ||||
| }; | ||||
| #endif | ||||
| @ -0,0 +1,216 @@ | ||||
| // Tencent is pleased to support the open source community by making sluaunreal available. | ||||
|  | ||||
| // Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights reserved. | ||||
| // Licensed under the BSD 3-Clause License (the "License"); | ||||
| // you may not use this file except in compliance with the License. You may obtain a copy of the License at | ||||
|  | ||||
| // https://opensource.org/licenses/BSD-3-Clause | ||||
|  | ||||
| // Unless required by applicable law or agreed to in writing, | ||||
| // software distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and limitations under the License. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Widgets/Docking/SDockTab.h" | ||||
| #include "Widgets/Layout/SScrollBox.h" | ||||
| #include "Widgets/Layout/SWidgetSwitcher.h" | ||||
| #include "Widgets/Text/STextBlock.h" | ||||
| #include "Widgets/Views/STreeView.h" | ||||
| #include "Widgets/Views/SListView.h" | ||||
| #include "Widgets/Notifications/SProgressBar.h" | ||||
| #include "slua_remote_profile.h" | ||||
| #include "LuaMemoryProfile.h" | ||||
| #include "ProfileDataDefine.h" | ||||
| #include "slua_profile_inspector.h" | ||||
|  | ||||
| #define IsMemoryProfiler (m_stdLineVisibility.Get() != EVisibility::Visible) | ||||
| class SProfilerWidget; | ||||
| class SProfilerTabWidget; | ||||
| class Profiler; | ||||
| class SSlider; | ||||
|  | ||||
| class SLUA_PROFILE_API SProfilerInspector | ||||
| { | ||||
| public: | ||||
|     SProfilerInspector(); | ||||
|     ~SProfilerInspector(); | ||||
|      | ||||
|     void Refresh(TSharedPtr<FunctionProfileNode> funcInfoRoot, TMap<int64, NS_SLUA::LuaMemInfo>& memoryInfoList, MemoryFramePtr memoryFrame); | ||||
|     TSharedRef<class SDockTab> GetSDockTab(); | ||||
|     TSharedRef<ITableRow> OnGenerateMemRowForList(TSharedPtr<FileMemInfo> Item, const TSharedRef<STableViewBase>& OwnerTable); | ||||
|     void OnGetMemChildrenForTree(TSharedPtr<FileMemInfo> Parent, TArray<TSharedPtr<FileMemInfo>>& OutChildren); | ||||
|      | ||||
|     void OnGetChildrenForTree(TSharedPtr<FunctionProfileNode> Parent, TArray<TSharedPtr<FunctionProfileNode>>& OutChildren); | ||||
|     TSharedRef<ITableRow> OnGenerateRowForList(TSharedPtr<FunctionProfileNode> Item, const TSharedRef<STableViewBase>& OwnerTable); | ||||
|     void StartChartRolling(); | ||||
|     bool GetNeedProfilerCleared() const | ||||
|     { | ||||
|         return needProfilerCleared; | ||||
|     } | ||||
|     void SetNeedProfilerCleared(const bool needClear) | ||||
|     { | ||||
|         needProfilerCleared = needClear; | ||||
|     } | ||||
|  | ||||
|     MemFileInfoMap GetMemoryFrameInfo(int32 memoryFrameIndex) const; | ||||
|      | ||||
|     TSharedPtr<NS_SLUA::FProfileServer> ProfileServer; | ||||
|      | ||||
| private: | ||||
|     const static int sampleNum = cMaxSampleNum; | ||||
|     const static int fixRowWidth = 600; | ||||
|     const static int refreshInterval = 1; | ||||
|     const float perMilliSec = 1000.0f; | ||||
|     const static int maxMemoryFile = 30; | ||||
|     bool bIsTouching = false; | ||||
|     typedef TMap<FString, int> MemInfoIndexMap; | ||||
|      | ||||
|     TSharedPtr<STreeView<TSharedPtr<FunctionProfileNode>>> treeview; | ||||
|     TSharedPtr<SListView<TSharedPtr<FileMemInfo>>> listview; | ||||
|     TSharedPtr<STreeView<TSharedPtr<FileMemInfo>>> memTreeView; | ||||
|     TSharedPtr<SSlider> cpuSlider,memSlider; | ||||
|  | ||||
|     TSharedPtr<SProgressBar> profilerBarArray[sampleNum]; | ||||
|     TSharedPtr<SProfilerWidget> cpuProfilerWidget; | ||||
|     TSharedPtr<SProfilerWidget> memProfilerWidget; | ||||
|     TSharedPtr<SProfilerTabWidget> cpuTabWidget; | ||||
|     TSharedPtr<SProfilerTabWidget> memTabWidget; | ||||
|     TSharedPtr<SProfilerTabWidget> fpsTabWidget; | ||||
|     TSharedPtr<SWidgetSwitcher> tabSwitcher; | ||||
|      | ||||
|      | ||||
|     TArray<float> chartValArray; | ||||
|     TArray<float> memChartValArray; | ||||
|     bool stopChartRolling; | ||||
|     int cpuViewBeginIndex; | ||||
|     int memViewBeginIndex; | ||||
|      | ||||
|     float maxLuaMemory; | ||||
|     float avgLuaMemory; | ||||
|     double luaTotalMemSize; | ||||
|     double lastLuaTotalMemSize; | ||||
|     float maxProfileSamplesCostTime; | ||||
|     float avgProfileSamplesCostTime; | ||||
|     bool hasCleared; | ||||
|     bool needProfilerCleared; | ||||
|     FVector2D mouseUpPoint; | ||||
|     FVector2D mouseDownPoint; | ||||
|  | ||||
|      | ||||
|     TArray<TArray<TSharedPtr<FunctionProfileNode>>> allProfileData; | ||||
|  | ||||
|     TArray<TSharedPtr<FunctionProfileNode>> profileRootArr;     | ||||
|     TSharedPtr<FProflierMemNode> lastLuaMemNode; | ||||
|     /* holding all of the memory node which are showed on Profiler chart */ | ||||
|     MemNodeInfoList allLuaMemNodeList; | ||||
|      | ||||
|     /* refresh with the chart line, when mouse clicks down, it'll get point from this array */ | ||||
|     MemFileInfoMap shownFileInfo; | ||||
|     /* store the file name as the parent item in memory treeview */ | ||||
|     ShownMemInfoList shownParentFileName; | ||||
|      | ||||
|     void RefreshBarValue(); | ||||
|      | ||||
|     void ShowProfilerTree(TArray<TSharedPtr<FunctionProfileNode>>&selectedProfiler); | ||||
|     void CheckBoxChanged(ECheckBoxState newState); | ||||
|      | ||||
|     FString GenBrevFuncName(const FLuaFunctionDefine &functionDefine); | ||||
|      | ||||
|     void RestartMemoryStatistis(); | ||||
|     void OnClearBtnClicked(); | ||||
|     void CalcPointMemdiff(int beginIndex, int endIndex); | ||||
|     void CollectMemoryNode(TMap<int64, NS_SLUA::LuaMemInfo>& memoryInfoMap, MemoryFramePtr memoryFrame); | ||||
|     void CombineSameFileInfo(FProflierMemNode& proflierMemNode, int32 memoryFrameIndex); | ||||
|     int ContainsFile(FString& fileName, MemInfoIndexMap &list); | ||||
|     FString ChooseMemoryUnit(float memorySize); | ||||
|  | ||||
|     // save/load disk profile file | ||||
|     void OnLoadFileBtnClicked(); | ||||
|     void OnSaveFileBtnClicked(); | ||||
|     void OnCpuSliderValueChanged(float Value); | ||||
|     void OnMemSliderValueChanged(float Value); | ||||
|  | ||||
|     void ShowNotificationDialog(const FString& message); | ||||
|     TWeakPtr<class SNotificationItem> notification; | ||||
| }; | ||||
|  | ||||
| class SLUA_PROFILE_API SProfilerWidget : public SCompoundWidget | ||||
| { | ||||
| public: | ||||
|     SLATE_BEGIN_ARGS(SProfilerWidget) | ||||
|     :_StdLineVisibility(EVisibility::Visible) | ||||
|     {} | ||||
|      | ||||
|     SLATE_ATTRIBUTE(EVisibility, StdLineVisibility) | ||||
|      | ||||
|     SLATE_END_ARGS() | ||||
|      | ||||
|     /** Constructs this widget with InArgs */ | ||||
|     void Construct(const FArguments& InArgs); | ||||
|     void SetMouseMovePoint(FVector2D mouseDownPoint); | ||||
|     void SetMouseClickPoint(FVector2D mouseClickPoint); | ||||
|     void SetArrayValue(TArray<float> &chartValArray, float maxCostTime, float maxMemSize); | ||||
|     int CalcClickSampleIdx(FVector2D &cursorPos); | ||||
|     int CalcHoverSampleIdx(const FVector2D cursorPos); | ||||
|     void SetToolTipVal(float val); | ||||
|     void ClearClickedPoint(); | ||||
|     void SetStdLineVisibility(TAttribute<EVisibility> InVisibility); | ||||
|      | ||||
|     // SWidget interface | ||||
|     virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override; | ||||
|     virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override; | ||||
| protected: | ||||
|     virtual FVector2D ComputeDesiredSize(float size) const override; | ||||
|      | ||||
| private: | ||||
|     void DrawStdLine(const FGeometry& AllottedGeometry, FSlateWindowElementList& OutDrawElements, int32 LayerId, float positionY, FString stdStr) const; | ||||
|     void AddStdLine(float &maxPointValue, float &stdLineValue, FString &stdLineName); | ||||
|     void CalcStdLine(float &maxCostTime); | ||||
|     void CalcMemStdText(float &maxMemorySize); | ||||
|      | ||||
|     TArray<FVector2D> m_arraylinePath; | ||||
|     TArray<float> m_arrayVal; | ||||
|  | ||||
|     TArray<float> m_stdPositionY; | ||||
|     TArray<FString> m_stdStr; | ||||
|     TArray<FString> m_stdMemStr; | ||||
|     TAttribute<EVisibility> m_stdLineVisibility; | ||||
|     const int32 m_cSliceCount = cMaxSampleNum; | ||||
|     const float m_cStdWidth = 1300; | ||||
|     float m_widgetWidth = 0; | ||||
|     const int32 m_cStdLeftPosition = 30; | ||||
|     float m_maxCostTime = 0; | ||||
|     float m_maxMemSize = 0; | ||||
|     float m_maxPointHeight = 0; | ||||
|     float m_pointInterval = 0; | ||||
|     float m_toolTipVal = 0; | ||||
|     int32 m_memStdScale = 1; | ||||
|     int32 m_pathArrayNum = 0; | ||||
|     FVector2D m_clickedPoint; | ||||
|     FVector2D m_mouseDownPoint; | ||||
|     const float m_cStdHighVal = cMaxViewHeight; | ||||
| }; | ||||
|  | ||||
| class SLUA_PROFILE_API SProfilerTabWidget : public SCompoundWidget | ||||
| { | ||||
|     SLATE_BEGIN_ARGS(SProfilerTabWidget) | ||||
|     : _TabName(FText::FromString("")) | ||||
|     , _TabIcon(FCoreStyle::Get().GetDefaultBrush()) | ||||
|     {} | ||||
|      | ||||
|     SLATE_ATTRIBUTE(FText, TabName) | ||||
|      | ||||
|     SLATE_ATTRIBUTE(const FSlateBrush*, TabIcon) | ||||
|      | ||||
|     SLATE_EVENT(FOnClicked, OnClicked) | ||||
|      | ||||
|     /** The visual style of the button */ | ||||
|     SLATE_END_ARGS() | ||||
|      | ||||
| public: | ||||
|     int32 activeTabIndex = 0; | ||||
|      | ||||
|     void Construct(const FArguments& InArgs); | ||||
| }; | ||||
| @ -0,0 +1,162 @@ | ||||
| // Tencent is pleased to support the open source community by making sluaunreal available. | ||||
|  | ||||
| // Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights reserved. | ||||
| // Licensed under the BSD 3-Clause License (the "License");  | ||||
| // you may not use this file except in compliance with the License. You may obtain a copy of the License at | ||||
|  | ||||
| // https://opensource.org/licenses/BSD-3-Clause | ||||
|  | ||||
| // Unless required by applicable law or agreed to in writing,  | ||||
| // software distributed under the License is distributed on an "AS IS" BASIS,  | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | ||||
| // See the License for the specific language governing permissions and limitations under the License. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "CoreMinimal.h" | ||||
| #include "HAL/Runnable.h" | ||||
| #include "Containers/Queue.h" | ||||
| #include "Interfaces/IPv4/IPv4Endpoint.h" | ||||
| #include "LuaMemoryProfile.h" | ||||
| #include "Templates/SharedPointer.h" | ||||
| #include "Serialization/ArrayReader.h" | ||||
| #include "Delegates/DelegateCombinations.h" | ||||
|  | ||||
| class FSocket; | ||||
| class FTcpListener; | ||||
|  | ||||
| namespace NS_SLUA { | ||||
|     class FProfileConnection; | ||||
|     class FProfileMessage; | ||||
|      | ||||
|     typedef TSharedPtr<FProfileMessage, ESPMode::ThreadSafe> FProfileMessagePtr; | ||||
|     DECLARE_DELEGATE_OneParam(FOnProfileMessageDelegate, FProfileMessagePtr); | ||||
|  | ||||
|     class FProfileServer : public FRunnable | ||||
|     { | ||||
|     public: | ||||
|         FProfileServer(); | ||||
|         ~FProfileServer(); | ||||
|  | ||||
|         FOnProfileMessageDelegate& OnProfileMessageRecv(); | ||||
|  | ||||
|         TArray<TSharedPtr<FProfileConnection>> GetConnections(); | ||||
|  | ||||
|         static int32 Port; | ||||
|          | ||||
|     protected: | ||||
|         bool Init() override; | ||||
|         uint32 Run() override; | ||||
|         void Stop() override; | ||||
|          | ||||
|         void StopTransport(); | ||||
|  | ||||
|     private: | ||||
|         /** Callback for accepted connections to the local server. */ | ||||
|         bool HandleConnectionAccepted(FSocket* ClientSocket, const FIPv4Endpoint& ClientEndpoint); | ||||
|  | ||||
|         FRunnableThread* Thread; | ||||
|  | ||||
|         FIPv4Endpoint ListenEndpoint; | ||||
|  | ||||
|         FTcpListener* Listener; | ||||
|  | ||||
|         /** Current connections */ | ||||
|         TArray<TSharedPtr<FProfileConnection>> Connections; | ||||
|  | ||||
|         /** Holds a queue of pending connections. */ | ||||
|         TQueue<TSharedPtr<FProfileConnection>, EQueueMode::Mpsc> PendingConnections; | ||||
|          | ||||
|         FOnProfileMessageDelegate OnProfileMessageDelegate; | ||||
|  | ||||
|         bool bStop; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|     * Implements a TCP message tunnel connection. | ||||
|     */ | ||||
|     class FProfileConnection | ||||
|         : public FRunnable | ||||
|         , public TSharedFromThis<FProfileConnection> | ||||
|     { | ||||
|     public: | ||||
|         FProfileConnection(FSocket* InSocket, const FIPv4Endpoint& InRemoteEndpoint); | ||||
|  | ||||
|         /** Virtual destructor. */ | ||||
|         virtual ~FProfileConnection(); | ||||
|  | ||||
|         void Start(); | ||||
|  | ||||
|     public: | ||||
|         enum EConnectionState | ||||
|         { | ||||
|             STATE_Connecting,                    // connecting but don't yet have RemoteNodeId | ||||
|             STATE_Connected,                    // connected and RemoteNodeId is valid | ||||
|             STATE_Disconnected                    // disconnected. Previous RemoteNodeId is retained | ||||
|         }; | ||||
|  | ||||
|         EConnectionState GetConnectionState() const; | ||||
|  | ||||
|         FSocket* GetSocket(); | ||||
|          | ||||
|         bool ReceiveData(TSharedPtr<FProfileMessage, ESPMode::ThreadSafe>& OutMessage); | ||||
|          | ||||
|         void Close(); | ||||
|  | ||||
|     private: | ||||
|         //~ FRunnable interface | ||||
|         virtual bool Init() override; | ||||
|         virtual uint32 Run() override; | ||||
|         virtual void Stop() override; | ||||
|         virtual void Exit() override; | ||||
|  | ||||
|     protected: | ||||
|         bool ReceiveMessages(); | ||||
|  | ||||
|         /** Holds the IP endpoint of the remote client. */ | ||||
|         FIPv4Endpoint RemoteEndpoint; | ||||
|  | ||||
|         /** Holds the connection socket. */ | ||||
|         FSocket* Socket; | ||||
|  | ||||
|         FRunnableThread* Thread; | ||||
|  | ||||
|         /** Holds the total number of bytes received from the connection. */ | ||||
|         uint64 TotalBytesReceived; | ||||
|  | ||||
|         /** Holds the collection of received Messages. */ | ||||
|         TQueue<TSharedPtr<FProfileMessage, ESPMode::ThreadSafe>, EQueueMode::Mpsc> Inbox; | ||||
|  | ||||
|         /** Message data we're currently in the process of receiving, if any */ | ||||
|         TSharedPtr<FArrayReader, ESPMode::ThreadSafe> RecvMessageData; | ||||
|  | ||||
|         int32 RecvMessageDataRemaining; | ||||
|          | ||||
|         int hookEvent; | ||||
|  | ||||
|         EConnectionState ConnectionState; | ||||
|  | ||||
|         bool bRun; | ||||
|     }; | ||||
|  | ||||
|     class FProfileMessage | ||||
|     { | ||||
|     public: | ||||
|         FProfileMessage(); | ||||
|         ~FProfileMessage(); | ||||
|  | ||||
|         bool Deserialize(const TSharedPtr<FArrayReader, ESPMode::ThreadSafe>& Message); | ||||
|  | ||||
|     public: | ||||
|         int Event; | ||||
|         int64 Time; | ||||
|  | ||||
|         int Linedefined; | ||||
|         FString Name; | ||||
|         FString ShortSrc; | ||||
|          | ||||
|         //Memory infomation | ||||
|         TArray<NS_SLUA::LuaMemInfo> memoryInfoList; | ||||
|         TArray<NS_SLUA::LuaMemInfo> memoryIncrease; | ||||
|     }; | ||||
| } | ||||
| @ -0,0 +1,72 @@ | ||||
| // Tencent is pleased to support the open source community by making sluaunreal available. | ||||
|  | ||||
| // Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights reserved. | ||||
| // Licensed under the BSD 3-Clause License (the "License");  | ||||
| // you may not use this file except in compliance with the License. You may obtain a copy of the License at | ||||
|  | ||||
| // https://opensource.org/licenses/BSD-3-Clause | ||||
|  | ||||
| // Unless required by applicable law or agreed to in writing,  | ||||
| // software distributed under the License is distributed on an "AS IS" BASIS,  | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | ||||
| // See the License for the specific language governing permissions and limitations under the License. | ||||
|  | ||||
| using UnrealBuildTool; | ||||
| using System.IO; | ||||
|  | ||||
| public class slua_profile : ModuleRules | ||||
| { | ||||
|     public slua_profile(ReadOnlyTargetRules Target) : base(Target) | ||||
|     { | ||||
|         PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; | ||||
|         // enable exception | ||||
|         bEnableExceptions = true; | ||||
|  | ||||
| #if UE_5_2_OR_LATER | ||||
|         IWYUSupport = IWYUSupport.None; | ||||
| #else | ||||
|         bEnforceIWYU = false; | ||||
| #endif | ||||
|         bEnableUndefinedIdentifierWarnings = false; | ||||
|  | ||||
|         PrivateDependencyModuleNames.AddRange(new string[] { "slua_unreal" }); | ||||
|         PublicIncludePathModuleNames.AddRange(new string[] { "slua_unreal" }); | ||||
| #if UE_4_21_OR_LATER | ||||
|         PublicDefinitions.Add("ENABLE_PROFILER"); | ||||
| #else | ||||
|         Definitions.Add("ENABLE_PROFILER"); | ||||
| #endif | ||||
|  | ||||
|  | ||||
|         PublicDependencyModuleNames.AddRange( | ||||
|             new string[] | ||||
|             { | ||||
|                 "Core", | ||||
|                 "UMG", | ||||
| 				// ... add other public dependencies that you statically link with here ... | ||||
| 			} | ||||
|             ); | ||||
|  | ||||
|         if (Target.Type == TargetType.Editor) | ||||
|         { | ||||
|             PrivateDependencyModuleNames.Add("UnrealEd"); | ||||
|             PrivateDependencyModuleNames.Add("EditorStyle"); | ||||
|             PrivateDependencyModuleNames.Add("LevelEditor"); | ||||
|         } | ||||
|  | ||||
|         PrivateDependencyModuleNames.AddRange( | ||||
|             new string[] | ||||
|             { | ||||
|                 "CoreUObject", | ||||
|                 "Engine", | ||||
|                 "Slate", | ||||
|                 "SlateCore", | ||||
|                 "UMG", | ||||
|                 "InputCore", | ||||
|                 "Networking", | ||||
|                 "Sockets", | ||||
| 				// ... add private dependencies that you statically link with here ...	 | ||||
| 			} | ||||
|     ); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user