summaryrefslogtreecommitdiff
path: root/Runtime/Profiler/ProfilerConnection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Runtime/Profiler/ProfilerConnection.cpp')
-rw-r--r--Runtime/Profiler/ProfilerConnection.cpp353
1 files changed, 353 insertions, 0 deletions
diff --git a/Runtime/Profiler/ProfilerConnection.cpp b/Runtime/Profiler/ProfilerConnection.cpp
new file mode 100644
index 0000000..7d299dc
--- /dev/null
+++ b/Runtime/Profiler/ProfilerConnection.cpp
@@ -0,0 +1,353 @@
+#include "UnityPrefix.h"
+#include "ProfilerConnection.h"
+
+#if ENABLE_PROFILER
+
+#if ENABLE_PLAYERCONNECTION
+#include "ProfilerImpl.h"
+#include "ProfilerFrameData.h"
+#include "ProfilerStats.h"
+#include "Runtime/Mono/MonoHeapShot.h"
+#include "Runtime/Misc/BuildSettings.h"
+#include "Runtime/Network/NetworkUtility.h"
+#include "Runtime/Network/PlayerCommunicator/PlayerConnection.h"
+#include "Runtime/Network/PlayerCommunicator/EditorConnection.h"
+#include "ProfilerHistory.h"
+#include "ObjectMemoryProfiler.h"
+#endif
+
+#if UNITY_EDITOR
+#include "Editor/Src/ProjectWizardUtility.h"
+#include "Runtime/Utilities/FileUtilities.h"
+#include "Runtime/Utilities/PathNameUtility.h"
+#include "Runtime/Scripting/ScriptingUtility.h"
+#include "Runtime/Mono/MonoManager.h"
+#include <ctime>
+#endif
+
+UInt32 ProfilerConnection::ms_EditorGuid = 0xFFFFFFFF;
+UInt32 ProfilerConnection::ms_CustomIPGuid = 0xFFFFFFFE;
+ProfilerConnection* ProfilerConnection::ms_Instance = NULL;
+
+void ProfilerConnection::Initialize()
+{
+ Assert(ms_Instance == NULL);
+ ms_Instance = new ProfilerConnection();
+#if ENABLE_PLAYERCONNECTION
+ ms_Instance->PrepareConnections();
+#endif
+}
+
+void ProfilerConnection::Cleanup()
+{
+ Assert(ms_Instance != NULL);
+#if ENABLE_PLAYERCONNECTION
+ ms_Instance->RemoveConnections();
+#endif
+ delete ms_Instance;
+ ms_Instance = NULL;
+}
+
+ProfilerConnection::ProfilerConnection()
+: m_ConnectedProfiler(ms_EditorGuid)
+, m_CurrentBuildTarget(kBuildNoTargetPlatform)
+{
+}
+
+#if UNITY_EDITOR
+
+void ProfilerConnection::DirectIPConnect(const std::string& IP)
+{
+ m_ConnectedProfiler = EditorConnection::Get().ConnectPlayerDirectIP(IP);
+ if(m_ConnectedProfiler == PLAYER_DIRECT_IP_CONNECT_GUID)
+ EnableConnectedProfiler(true);
+}
+
+void ProfilerConnection::GetAvailableProfilers ( std::vector<UInt32>& values )
+{
+ values.clear();
+ values.push_back(ms_EditorGuid);
+ EditorConnection::Get().GetAvailablePlayers(values);
+}
+
+void ProfilerConnection::EnableConnectedProfiler ( bool enable )
+{
+ int enabled = enable;
+ EditorConnection::Get().SendMessage(m_ConnectedProfiler, GeneralConnection::kProfileStartupInformation, &enabled, 4);
+}
+
+std::string ProfilerConnection::GetConnectionIdentification(UInt32 guid)
+{
+ if (guid != ms_EditorGuid)
+ return EditorConnection::Get().GetConnectionIdentifier(guid);
+ return "Editor";
+}
+
+bool ProfilerConnection::IsIdentifierConnectable(UInt32 guid)
+{
+ if (guid != ms_EditorGuid)
+ return EditorConnection::Get().IsIdentifierConnectable(guid);
+ return true;
+}
+
+bool ProfilerConnection::IsIdentifierOnLocalhost(UInt32 guid)
+{
+ if (guid != ms_EditorGuid)
+ return EditorConnection::Get().IsIdentifierOnLocalhost(guid);
+ return true;
+}
+
+bool ProfilerConnection::IsConnectionEditor()
+{
+ return m_ConnectedProfiler == ms_EditorGuid;
+}
+
+void ProfilerConnection::SetConnectedProfiler( UInt32 guid, bool sendDisable)
+{
+ if (guid == ms_EditorGuid){
+ if(m_ConnectedProfiler != guid && sendDisable)
+ EnableConnectedProfiler(false);
+ m_ConnectedProfiler = ms_EditorGuid;
+ return;
+ }
+
+ m_ConnectedProfiler = EditorConnection::Get().ConnectPlayer(guid);
+ if(m_ConnectedProfiler == guid)
+ EnableConnectedProfiler(true);
+}
+
+void ProfilerConnection::SetupTargetSpecificConnection(BuildTargetPlatform targetPlatform)
+{
+ if (m_CurrentBuildTarget == targetPlatform)
+ return;
+ m_CurrentBuildTarget = targetPlatform;
+ EditorConnection::Get().RemovePlayer(PLAYER_DIRECTCONNECT_GUID);
+ switch (targetPlatform)
+ {
+ case kBuild_Android:
+ {
+ std::string localhost = "127.0.0.1";
+ std::string hostName = Format("AndroidPlayer(ADB@%s:%i)", localhost.c_str(), PLAYER_DIRECTCONNECT_PORT);
+ UInt32 guid = EditorConnection::Get().AddPlayer(hostName, localhost, PLAYER_DIRECTCONNECT_PORT, PLAYER_DIRECTCONNECT_GUID, GeneralConnection::kSupportsProfile);
+ AssertMsg(guid == PLAYER_DIRECTCONNECT_GUID, "Unable to add Android direct profiler connection");
+ }
+ }
+}
+
+UInt32 ProfilerConnection::GetConnectedProfiler()
+{
+ return m_ConnectedProfiler;
+}
+
+UInt32 ProfilerConnection::GetEditorGuid()
+{
+ return ms_EditorGuid;
+}
+
+void ProfilerConnection::HandleDisconnectionMessage (UInt32 guid)
+{
+ Assert (UNITY_EDITOR);
+ ProfilerConnection::Get().SetConnectedProfiler(ms_EditorGuid, false);
+}
+
+#endif
+
+
+
+
+// Network communication and serialization
+
+#if ENABLE_PLAYERCONNECTION
+
+void ProfilerConnection::PrepareConnections()
+{
+#if UNITY_EDITOR
+ EditorConnection::Get().RegisterConnectionHandler(&ProfilerConnection::HandleConnectionMessage);
+ EditorConnection::Get().RegisterDisconnectionHandler(&ProfilerConnection::HandleDisconnectionMessage);
+ EditorConnection::Get().RegisterMessageHandler(GeneralConnection::kProfileDataMessage, &ProfilerConnection::HandleProfilerDataMessage);
+ EditorConnection::Get().RegisterMessageHandler(GeneralConnection::kObjectMemoryProfileDataMessage, &ProfilerConnection::HandleObjectMemoryProfileDataMessage);
+ EditorConnection::Get().RegisterMessageHandler(GeneralConnection::kFileTransferMessage, &ProfilerConnection::HandleFileDataMessage);
+#else
+ PlayerConnection::Get().RegisterConnectionHandler(&ProfilerConnection::HandleConnectionMessage);
+ PlayerConnection::Get().RegisterMessageHandler(GeneralConnection::kProfileStartupInformation, &ProfilerConnection::EnableProfilerMessage);
+ PlayerConnection::Get().RegisterMessageHandler(GeneralConnection::kObjectMemoryProfileSnapshot, &ProfilerConnection::GetObjectMemoryProfile);
+ PlayerConnection::Get().RegisterMessageHandler(GeneralConnection::kCaptureHeaphshotMessage, &ProfilerConnection::HandleCaptureHeapshotMessage);
+#endif
+}
+
+void ProfilerConnection::RemoveConnections()
+{
+#if UNITY_EDITOR
+ EditorConnection::Get().UnregisterConnectionHandler(&ProfilerConnection::HandleConnectionMessage);
+ EditorConnection::Get().UnregisterDisconnectionHandler(&ProfilerConnection::HandleDisconnectionMessage);
+ EditorConnection::Get().UnregisterMessageHandler(GeneralConnection::kProfileDataMessage, &ProfilerConnection::HandleProfilerDataMessage);
+ EditorConnection::Get().UnregisterMessageHandler(GeneralConnection::kObjectMemoryProfileDataMessage, &ProfilerConnection::HandleObjectMemoryProfileDataMessage);
+ EditorConnection::Get().UnregisterMessageHandler(GeneralConnection::kFileTransferMessage, &ProfilerConnection::HandleFileDataMessage);
+#else
+ PlayerConnection::Get().UnregisterConnectionHandler(&ProfilerConnection::HandleConnectionMessage);
+ PlayerConnection::Get().UnregisterMessageHandler(GeneralConnection::kProfileStartupInformation, &ProfilerConnection::EnableProfilerMessage);
+ PlayerConnection::Get().UnregisterMessageHandler(GeneralConnection::kObjectMemoryProfileSnapshot, &ProfilerConnection::GetObjectMemoryProfile);
+ PlayerConnection::Get().UnregisterMessageHandler(GeneralConnection::kCaptureHeaphshotMessage, &ProfilerConnection::HandleCaptureHeapshotMessage);
+#endif
+}
+
+void ProfilerConnection::HandleConnectionMessage (UInt32 guid)
+{
+ ProfilerConnection::Get().m_ConnectedProfiler = guid;
+#if UNITY_EDITOR
+ ProfilerConnection::Get().EnableConnectedProfiler(true);
+#endif
+}
+
+
+void ProfilerConnection::EnableProfilerMessage ( const void* data, UInt32 size, UInt32 guid)
+{
+ // message sent from Editor to Player, to start and stop the profiler
+ Assert(!UNITY_EDITOR);
+ if(GetBuildSettingsPtr() && !GetBuildSettingsPtr()->hasAdvancedVersion)
+ {
+ ErrorString("Profiler is only supported with Pro License");
+ return;
+ }
+ bool enable = *(int*)data != 0;
+ if (enable)
+ ProfilerConnection::Get().m_ConnectedProfiler = guid;
+ if ( ProfilerConnection::Get().m_ConnectedProfiler == guid )
+ UnityProfiler::Get().SetEnabled(enable);
+}
+
+void ProfilerConnection::GetObjectMemoryProfile( const void* data, UInt32 size, UInt32 guid)
+{
+ // message recieved on the player from Editor
+ Assert(!UNITY_EDITOR);
+ if ( ProfilerConnection::Get().m_ConnectedProfiler != guid )
+ return;
+
+ if(GetBuildSettingsPtr() && !GetBuildSettingsPtr()->hasAdvancedVersion)
+ {
+ ErrorString("Profiler is only supported with Pro License");
+ return;
+ }
+
+#if ENABLE_MEM_PROFILER
+ dynamic_array<int> buffer;
+ ObjectMemoryProfiler::TakeMemorySnapshot(buffer);
+ PlayerConnection::Get().SendMessage(ProfilerConnection::Get().m_ConnectedProfiler,PlayerConnection::kObjectMemoryProfileDataMessage, &buffer[0], buffer.size()*sizeof(int));
+#endif
+}
+
+
+void ProfilerConnection::HandleCaptureHeapshotMessage (const void* data, UInt32 size, UInt32 guid)
+{
+#if ENABLE_MONO_HEAPSHOT
+ printf_console("Capturing heapshot\n");
+ HeapShotData heapShotData;
+ HeapShotDumpObjectMap(heapShotData);
+ //bool WriteBytesToFile (const void *data, int byteLength, const string& pathName);
+ //WriteBytesToFile(&data[0], data.size(), "game:\\test.dump");
+ if (heapShotData.size() > 0)
+ TransferFileOverPlayerConnection("testplayer.heapshot", &heapShotData[0], heapShotData.size());
+#endif
+}
+
+
+void ProfilerConnection::SendFrameDataToEditor ( ProfilerFrameData& data )
+{
+ // TODO: Send partial data ( right now we double buffer the frame on the profiler side, to wait for GPU data)
+ dynamic_array<int> buffer;
+
+ UnityProfiler::SerializeFrameData(data, buffer);
+
+ if(buffer.size()<128*1024)
+ PlayerConnection::Get().SendMessage(m_ConnectedProfiler,PlayerConnection::kProfileDataMessage, &buffer[0], buffer.size()*sizeof(int));
+}
+
+
+
+#if UNITY_EDITOR
+
+void ProfilerConnection::SendCaptureHeapshotMessage()
+{
+ int enabled = 1;
+ //printf_console("Sending capture heapshot cmd");
+ EditorConnection::Get().SendMessage(m_ConnectedProfiler, GeneralConnection::kCaptureHeaphshotMessage, &enabled, sizeof(int));
+}
+
+void ProfilerConnection::HandleFileDataMessage (const void* data, UInt32 size, UInt32 guid)
+{
+ UInt8* uData = (UInt8*) data;
+ //printf_console("HandleFileDataMessage");
+
+ UInt32 fileNameLength = *(UInt32*)uData;
+ uData += sizeof(UInt32);
+
+ char rawFileName[255];
+ memcpy(rawFileName, uData, fileNameLength);
+ rawFileName[fileNameLength] = '\0';
+ uData += fileNameLength;
+
+ UInt32 contentLength = *(UInt32*)uData;
+ uData += sizeof(UInt32);
+
+ //printf_console("Name: %s Content length: %d\n", rawFileName, contentLength);
+
+ time_t now;
+ time(&now);
+ struct tm nowTime;
+ nowTime = *localtime(&now);
+
+ std::string fileName = Format("%04d-%02d-%02d_%02dh%02dm%02ds.heapshot", nowTime.tm_year + 1900, nowTime.tm_mon + 1, nowTime.tm_mday,
+ nowTime.tm_hour, nowTime.tm_min, nowTime.tm_sec);
+ //printf_console(fileName.c_str());
+ // ToDo: figure it out what we're saving, for now think always that it's a heapshot file
+ std::string heapShotDirectory = AppendPathName (GetProjectPath (), "Heapshots");
+ if (CreateDirectorySafe(heapShotDirectory))
+ {
+ std::string fullPath = AppendPathName (heapShotDirectory, fileName);
+ WriteBytesToFile(uData, contentLength, fullPath);
+
+ void* params[] = {scripting_string_new(fileName)};
+ CallStaticMonoMethod ("HeapshotWindow", "EventHeapShotReceived", params);
+ }
+}
+void ProfilerConnection::HandleProfilerDataMessage ( const void* data, UInt32 size, UInt32 guid )
+{
+ if (ProfilerConnection::Get().GetConnectedProfiler() != guid)
+ return;
+
+ if (!UnityProfiler::Get().GetEnabled())
+ return;
+
+ ProfilerFrameData* frame = UNITY_NEW(ProfilerFrameData, kMemProfiler) (1, 0);
+ if( UnityProfiler::DeserializeFrameData(frame, data, size) )
+ ProfilerHistory::Get().AddFrameDataAndTransferOwnership(frame, guid);
+ else
+ UNITY_DELETE(frame, kMemProfiler);
+}
+
+void ProfilerConnection::SendGetObjectMemoryProfile()
+{
+#if ENABLE_MEM_PROFILER
+ if(m_ConnectedProfiler == ms_EditorGuid)
+ ObjectMemoryProfiler::SetDataFromEditor();
+ else
+ EditorConnection::Get().SendMessage(m_ConnectedProfiler, GeneralConnection::kObjectMemoryProfileSnapshot, NULL, 0);
+#endif
+}
+
+void ProfilerConnection::HandleObjectMemoryProfileDataMessage ( const void* data, UInt32 size, UInt32 guid )
+{
+#if ENABLE_MEM_PROFILER
+ if (ProfilerConnection::Get().GetConnectedProfiler() != guid)
+ return;
+
+ ObjectMemoryProfiler::DeserializeAndApply(data,size);
+#endif
+}
+
+#endif
+
+
+
+#endif
+#endif