diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index d741890decf00..dbb15521e1949 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -481,7 +481,7 @@ RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_ProfAPI_ValidateNGENInstrumentation, W("Pro #ifdef FEATURE_PERFMAP RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapEnabled, W("PerfMapEnabled"), 0, "This flag is used on Linux to enable writing /tmp/perf-$pid.map. It is disabled by default") -RETAIL_CONFIG_STRING_INFO(EXTERNAL_PerfMapJitDumpPath, W("PerfMapJitDumpPath"), "Specifies a path to write the perf jitdump file. Defaults to GetTempPathA()") +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_PerfMapJitDumpPath, W("PerfMapJitDumpPath"), "Specifies a path to write the perf jitdump file. Defaults to /tmp", CLRConfig::LookupOptions::TrimWhiteSpaceFromStringValue) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapIgnoreSignal, W("PerfMapIgnoreSignal"), 0, "When perf map is enabled, this option will configure the specified signal to be accepted and ignored as a marker in the perf logs. It is disabled by default") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapShowOptimizationTiers, W("PerfMapShowOptimizationTiers"), 1, "Shows optimization tiers in the perf map for methods, as part of the symbol name. Useful for seeing separate stack frames for different optimization tiers of each method.") #endif diff --git a/src/coreclr/vm/perfinfo.cpp b/src/coreclr/vm/perfinfo.cpp index 0452f413f41d1..0be2e519936fb 100644 --- a/src/coreclr/vm/perfinfo.cpp +++ b/src/coreclr/vm/perfinfo.cpp @@ -10,19 +10,13 @@ #include "perfinfo.h" #include "pal.h" -PerfInfo::PerfInfo(int pid) +PerfInfo::PerfInfo(int pid, const char* basePath) : m_Stream(nullptr) { LIMITED_METHOD_CONTRACT; - SString tempPath; - if (!WszGetTempPath(tempPath)) - { - return; - } - SString path; - path.Printf("%sperfinfo-%d.map", tempPath.GetUTF8(), pid); + path.Printf("%s/perfinfo-%d.map", basePath, pid); OpenFile(path); } diff --git a/src/coreclr/vm/perfinfo.h b/src/coreclr/vm/perfinfo.h index 02624008af66f..ce54cc19faee6 100644 --- a/src/coreclr/vm/perfinfo.h +++ b/src/coreclr/vm/perfinfo.h @@ -20,7 +20,7 @@ */ class PerfInfo { public: - PerfInfo(int pid); + PerfInfo(int pid, const char* basePath); ~PerfInfo(); void LogImage(PEAssembly* pPEAssembly, CHAR* guid); diff --git a/src/coreclr/vm/perfmap.cpp b/src/coreclr/vm/perfmap.cpp index 25f4ead7353b5..4ede16efca076 100644 --- a/src/coreclr/vm/perfmap.cpp +++ b/src/coreclr/vm/perfmap.cpp @@ -19,6 +19,14 @@ #define FMT_CODE_ADDR "%p" +#ifndef __ANDROID__ +#define TEMP_DIRECTORY_PATH "/tmp" +#else +// On Android, "/tmp/" doesn't exist; temporary files should go to +// /data/local/tmp/ +#define TEMP_DIRECTORY_PATH "/data/local/tmp" +#endif + Volatile PerfMap::s_enabled = false; PerfMap * PerfMap::s_Current = nullptr; bool PerfMap::s_ShowOptimizationTiers = false; @@ -36,6 +44,16 @@ void PerfMap::Initialize() PerfMap::Enable(perfMapType, false); } +const char * PerfMap::InternalConstructPath() +{ + CLRConfigNoCache value = CLRConfigNoCache::Get("PerfMapJitDumpPath"); + if (value.IsSet()) + { + return value.AsString(); + } + return TEMP_DIRECTORY_PATH; +} + void PerfMap::Enable(PerfMapType type, bool sendExisting) { LIMITED_METHOD_CONTRACT; @@ -48,6 +66,8 @@ void PerfMap::Enable(PerfMapType type, bool sendExisting) { CrstHolder ch(&(s_csPerfMap)); + const char* basePath = InternalConstructPath(); + if (s_Current == nullptr && (type == PerfMapType::ALL || type == PerfMapType::PERFMAP)) { s_Current = new PerfMap(); @@ -64,27 +84,13 @@ void PerfMap::Enable(PerfMapType type, bool sendExisting) } int currentPid = GetCurrentProcessId(); - s_Current->OpenFileForPid(currentPid); + s_Current->OpenFileForPid(currentPid, basePath); s_enabled = true; } if (!PAL_PerfJitDump_IsStarted() && (type == PerfMapType::ALL || type == PerfMapType::JITDUMP)) - { - const char* jitdumpPath; - char jitdumpPathBuffer[4096]; - - CLRConfigNoCache value = CLRConfigNoCache::Get("PerfMapJitDumpPath"); - if (value.IsSet()) - { - jitdumpPath = value.AsString(); - } - else - { - GetTempPathA(sizeof(jitdumpPathBuffer) - 1, jitdumpPathBuffer); - jitdumpPath = jitdumpPathBuffer; - } - - PAL_PerfJitDump_Start(jitdumpPath); + { + PAL_PerfJitDump_Start(basePath); if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapShowOptimizationTiers) != 0) { @@ -209,23 +215,15 @@ PerfMap::~PerfMap() m_PerfInfo = nullptr; } -void PerfMap::OpenFileForPid(int pid) +void PerfMap::OpenFileForPid(int pid, const char* basePath) { - // Build the path to the map file on disk. - WCHAR tempPath[MAX_LONGPATH+1]; - if(!GetTempPathW(MAX_LONGPATH, tempPath)) - { - return; - } - - SString path; - path.Append(tempPath); - path.AppendPrintf("perf-%d.map", pid); + SString fullPath; + fullPath.Printf("%s/perf-%d.map", basePath, pid); // Open the map file for writing. - OpenFile(path); + OpenFile(fullPath); - m_PerfInfo = new PerfInfo(pid); + m_PerfInfo = new PerfInfo(pid, basePath); } // Open the specified destination map file. diff --git a/src/coreclr/vm/perfmap.h b/src/coreclr/vm/perfmap.h index 393f302cefff0..ffc7f3228b2cf 100644 --- a/src/coreclr/vm/perfmap.h +++ b/src/coreclr/vm/perfmap.h @@ -38,14 +38,18 @@ class PerfMap // Set to true if an error is encountered when writing to the file. bool m_ErrorEncountered; - // Construct a new map for the specified pid. + // Construct a new map PerfMap(); - void OpenFileForPid(int pid); + // Open a perfmap map for the specified pid + void OpenFileForPid(int pid, const char* basePath); // Write a line to the map file. void WriteLine(SString & line); + // Default to /tmp or use DOTNET_PerfMapJitDumpPath if set + static const char* InternalConstructPath(); + protected: // Open the perf map file for write. void OpenFile(SString& path);