249 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			249 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								// 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)
							 |