diff options
-rw-r--r-- | src/vm/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/vm/crossgen/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/vm/domainfile.cpp | 10 | ||||
-rw-r--r-- | src/vm/perfinfo.cpp | 125 | ||||
-rw-r--r-- | src/vm/perfinfo.h | 40 | ||||
-rw-r--r-- | src/vm/perfmap.cpp | 52 | ||||
-rw-r--r-- | src/vm/perfmap.h | 13 |
7 files changed, 200 insertions, 42 deletions
diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt index 13106a4a68..346acb264f 100644 --- a/src/vm/CMakeLists.txt +++ b/src/vm/CMakeLists.txt @@ -115,6 +115,7 @@ set(VM_SOURCES_DAC_AND_WKS_COMMON peimage.cpp peimagelayout.cpp perfmap.cpp + perfinfo.cpp precode.cpp prestub.cpp rejit.cpp diff --git a/src/vm/crossgen/CMakeLists.txt b/src/vm/crossgen/CMakeLists.txt index e3b5c6ae74..24a6fbdc53 100644 --- a/src/vm/crossgen/CMakeLists.txt +++ b/src/vm/crossgen/CMakeLists.txt @@ -150,6 +150,7 @@ endif (WIN32) if (CLR_CMAKE_PLATFORM_LINUX) list(APPEND VM_CROSSGEN_SOURCES ../perfmap.cpp + ../perfinfo.cpp ) endif (CLR_CMAKE_PLATFORM_LINUX) diff --git a/src/vm/domainfile.cpp b/src/vm/domainfile.cpp index 3837e82a60..9ccf46e35c 100644 --- a/src/vm/domainfile.cpp +++ b/src/vm/domainfile.cpp @@ -1310,11 +1310,6 @@ void DomainFile::FinishLoad() // Inform metadata that it has been loaded from a native image // (and so there was an opportunity to check for or fix inconsistencies in the original IL metadata) m_pFile->GetMDImport()->SetVerifiedByTrustedSource(TRUE); - -#ifdef FEATURE_PERFMAP - // Notify the perfmap of the native image load. - PerfMap::LogNativeImageLoad(m_pFile); -#endif } // Are we absolutely required to use a native image? @@ -1382,6 +1377,11 @@ void DomainFile::FinishLoad() // Set a bit to indicate that the module has been loaded in some domain, and therefore // typeloads can involve types from this module. (Used for candidate instantiations.) GetModule()->SetIsReadyForTypeLoad(); + +#ifdef FEATURE_PERFMAP + // Notify the perfmap of the IL image load. + PerfMap::LogImageLoad(m_pFile); +#endif } void DomainFile::VerifyExecution() diff --git a/src/vm/perfinfo.cpp b/src/vm/perfinfo.cpp new file mode 100644 index 0000000000..3f85f44ebc --- /dev/null +++ b/src/vm/perfinfo.cpp @@ -0,0 +1,125 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// =========================================================================== +// File: perfinfo.cpp +// + +#include "common.h" + +#if defined(FEATURE_PERFMAP) && !defined(DACCESS_COMPILE) +#include "perfinfo.h" +#include "pal.h" + +PerfInfo::PerfInfo(int pid) +{ + LIMITED_METHOD_CONTRACT; + + SString tempPath; + if (!WszGetTempPath(tempPath)) + { + return; + } + + SString path; + path.Printf("%Sperfinfo-%d.map", tempPath.GetUnicode(), pid); + OpenFile(path); +} + +// Logs image loads into the process' perfinfo-%d.map file +void PerfInfo::LogImage(PEFile* pFile, WCHAR* guid) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_PREEMPTIVE; + PRECONDITION(pFile != NULL); + PRECONDITION(guid != NULL); + } CONTRACTL_END; + + SString value; + const SString& path = pFile->GetPath(); + value.Printf("%S%c%S", path.GetUnicode(), sDelimiter, guid); + + SString command; + command.Printf("%s", "ImageLoad"); + WriteLine(command, value); + +} + +// Writes a command line, with "type" being the type of command, with "value" as the command's corresponding instructions/values. This is to be used to log specific information, e.g. LogImage +void PerfInfo::WriteLine(SString& type, SString& value) +{ + + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + if (m_Stream == NULL) + { + return; + } + + SString line; + line.Printf("%S%c%S%c\n", + type.GetUnicode(), sDelimiter, value.GetUnicode(), sDelimiter); + + EX_TRY + { + StackScratchBuffer scratch; + const char* strLine = line.GetANSI(scratch); + ULONG inCount = line.GetCount(); + ULONG outCount; + + m_Stream->Write(strLine, inCount, &outCount); + + if (inCount != outCount) + { + // error encountered + } + } + EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); +} + +// Opens a file ready to be written in. +void PerfInfo::OpenFile(SString& path) +{ + STANDARD_VM_CONTRACT; + + m_Stream = new (nothrow) CFileStream(); + + if (m_Stream != NULL) + { + HRESULT hr = m_Stream->OpenForWrite(path.GetUnicode()); + if (FAILED(hr)) + { + delete m_Stream; + m_Stream = NULL; + } + } +} + +PerfInfo::~PerfInfo() +{ + LIMITED_METHOD_CONTRACT; + + delete m_Stream; + m_Stream = NULL; +} + + +#endif + + + + + + + + + + diff --git a/src/vm/perfinfo.h b/src/vm/perfinfo.h new file mode 100644 index 0000000000..4ea87f35b4 --- /dev/null +++ b/src/vm/perfinfo.h @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// =========================================================================== +// File: perfinfo.h +// + +#ifndef PERFINFO_H +#define PERFINFO_H + + +#include "sstring.h" +#include "fstream.h" + +/* + A perfinfo-%d.map is created for every process that is created with manage code, the %d + being repaced with the process ID. + Every line in the perfinfo-%d.map is a type and value, separated by sDelimiter character: type;value + type represents what the user might want to do with its given value. value has a format chosen by + the user for parsing later on. +*/ +class PerfInfo { +public: + PerfInfo(int pid); + ~PerfInfo(); + void LogImage(PEFile* pFile, WCHAR* guid); + +private: + CFileStream* m_Stream; + + const char sDelimiter = ';'; + + void OpenFile(SString& path); + + void WriteLine(SString& type, SString& value); + +}; + + +#endif diff --git a/src/vm/perfmap.cpp b/src/vm/perfmap.cpp index 5c83584bda..4e04ca7d43 100644 --- a/src/vm/perfmap.cpp +++ b/src/vm/perfmap.cpp @@ -9,6 +9,7 @@ #if defined(FEATURE_PERFMAP) && !defined(DACCESS_COMPILE) #include "perfmap.h" +#include "perfinfo.h" #include "pal.h" PerfMap * PerfMap::s_Current = NULL; @@ -61,6 +62,8 @@ PerfMap::PerfMap(int pid) // Open the map file for writing. OpenFile(path); + + m_PerfInfo = new PerfInfo(pid); } // Construct a new map without a specified file name. @@ -77,6 +80,9 @@ PerfMap::~PerfMap() delete m_FileStream; m_FileStream = NULL; + + delete m_PerfInfo; + m_PerfInfo = NULL; } // Open the specified destination map file. @@ -159,8 +165,17 @@ void PerfMap::LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize) EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); } -// Log a native image to the map. -void PerfMap::LogNativeImage(PEFile * pFile) + +void PerfMap::LogImageLoad(PEFile * pFile) +{ + if (s_Current != NULL) + { + s_Current->LogImage(pFile); + } +} + +// Log an image load to the map. +void PerfMap::LogImage(PEFile * pFile) { CONTRACTL{ THROWS; @@ -169,52 +184,23 @@ void PerfMap::LogNativeImage(PEFile * pFile) PRECONDITION(pFile != NULL); } CONTRACTL_END; + if (m_FileStream == NULL || m_ErrorEncountered) { // A failure occurred, do not log. return; } - // Logging failures should not cause any exceptions to flow upstream. EX_TRY { - // Get the native image name. - LPCUTF8 lpcSimpleName = pFile->GetSimpleName(); - - // Get the native image signature. WCHAR wszSignature[39]; GetNativeImageSignature(pFile, wszSignature, lengthof(wszSignature)); - SString strNativeImageSymbol; - strNativeImageSymbol.Printf("%s.ni.%S", lpcSimpleName, wszSignature); - - // Get the base addess of the native image. - SIZE_T baseAddress = (SIZE_T)pFile->GetLoaded()->GetBase(); - - // Get the image size - COUNT_T imageSize = pFile->GetLoaded()->GetVirtualSize(); - - // Log baseAddress imageSize strNativeImageSymbol - StackScratchBuffer scratch; - SString line; - line.Printf("%p %x %s\n", baseAddress, imageSize, strNativeImageSymbol.GetANSI(scratch)); - - // Write the line. - WriteLine(line); + m_PerfInfo->LogImage(pFile, wszSignature); } EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); } -// Log a native image load to the map. -void PerfMap::LogNativeImageLoad(PEFile * pFile) -{ - STANDARD_VM_CONTRACT; - - if (s_Current != NULL) - { - s_Current->LogNativeImage(pFile); - } -} // Log a method to the map. void PerfMap::LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize) diff --git a/src/vm/perfmap.h b/src/vm/perfmap.h index ca86f5b028..fe38ed3ad5 100644 --- a/src/vm/perfmap.h +++ b/src/vm/perfmap.h @@ -10,6 +10,8 @@ #include "sstring.h" #include "fstream.h" +class PerfInfo; + // Generates a perfmap file. class PerfMap { @@ -20,6 +22,9 @@ private: // The file stream to write the map to. CFileStream * m_FileStream; + // The perfinfo file to log images to. + PerfInfo* m_PerfInfo; + // Set to true if an error is encountered when writing to the file. bool m_ErrorEncountered; @@ -43,10 +48,10 @@ protected: // Does the actual work to log a method to the map. void LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize); - // Does the actual work to log a native image load to the map. - void LogNativeImage(PEFile * pFile); + // Does the actual work to log an image + void LogImage(PEFile * pFile); - // Get the native image signature and store it as a string. + // Get the image signature and store it as a string. static void GetNativeImageSignature(PEFile * pFile, WCHAR * pwszSig, unsigned int nSigSize); public: @@ -54,7 +59,7 @@ public: static void Initialize(); // Log a native image load to the map. - static void LogNativeImageLoad(PEFile * pFile); + static void LogImageLoad(PEFile * pFile); // Log a JIT compiled method to the map. static void LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize); |