diff --git a/src/TraceEvent/Symbols/SymbolReader.cs b/src/TraceEvent/Symbols/SymbolReader.cs
index 351c6589d..a01e34f51 100644
--- a/src/TraceEvent/Symbols/SymbolReader.cs
+++ b/src/TraceEvent/Symbols/SymbolReader.cs
@@ -113,7 +113,7 @@ public string FindSymbolFilePathForModule(string dllFilePath, bool ilPDB = false
else
{
m_log.WriteLine("FindSymbolFilePathForModule: Could not find PDB for NGEN image, Trying to generate it.");
- ret = GenerateNGenSymbolsForModule(Path.GetFullPath(dllFilePath));
+ ret = GenerateNGenSymbolsForModule(Path.GetFullPath(dllFilePath), m_log, SymbolPath, SymbolCacheDirectory);
}
}
m_log.WriteLine("FindSymbolFilePathForModule returns {0} for {1} {2} {3} {4}", ret ?? "NULL", pdbName, pdbGuid, pdbAge, fileVersionString ?? "NULL");
@@ -514,16 +514,11 @@ public SymbolReaderOptions Options
///
/// The full path name of the PDB generated for the NGEN image.
///
- public string GenerateNGenSymbolsForModule(string ngenImageFullPath, string outputDirectory = null)
+ public static string GenerateNGenSymbolsForModule(string ngenImageFullPath, TextWriter log, string symbolPath, string outputDirectory)
{
- if (outputDirectory == null)
- {
- outputDirectory = SymbolCacheDirectory;
- }
-
if (!File.Exists(ngenImageFullPath))
{
- m_log.WriteLine("Warning, NGEN image does not exist: {0}", ngenImageFullPath);
+ log.WriteLine("Warning, NGEN image does not exist: {0}", ngenImageFullPath);
return null;
}
@@ -534,7 +529,7 @@ public string GenerateNGenSymbolsForModule(string ngenImageFullPath, string outp
{
if (!peFile.GetPdbSignature(out pdbFileName, out pdbGuid, out pdbAge, true))
{
- m_log.WriteLine("Could not get PDB signature for {0}", ngenImageFullPath);
+ log.WriteLine("Could not get PDB signature for {0}", ngenImageFullPath);
return null;
}
}
@@ -552,22 +547,22 @@ public string GenerateNGenSymbolsForModule(string ngenImageFullPath, string outp
// We only handle cases where we generate NGEN pdbs.
if (!pdbPath.EndsWith(".ni.pdb", StringComparison.OrdinalIgnoreCase))
{
- m_log.WriteLine("Pdb does not have .ni.pdb suffix");
+ log.WriteLine("Pdb does not have .ni.pdb suffix");
return null;
}
string privateRuntimeVerString;
- var clrDir = GetClrDirectoryForNGenImage(ngenImageFullPath, m_log, out privateRuntimeVerString);
+ var clrDir = GetClrDirectoryForNGenImage(ngenImageFullPath, log, out privateRuntimeVerString);
if (clrDir == null)
{
- m_log.WriteLine("Could not find CLR directory for NGEN image {0}, Trying .NET Core", ngenImageFullPath);
- return HandleNetCorePdbs(ngenImageFullPath, pdbPath);
+ log.WriteLine("Could not find CLR directory for NGEN image {0}, Trying .NET Core", ngenImageFullPath);
+ return HandleNetCorePdbs(ngenImageFullPath, pdbPath, log);
}
// See if this is a V4.5 CLR, if so we can do line numbers too.l
var lineNumberArg = "";
var ngenexe = Path.Combine(clrDir, "ngen.exe");
- m_log.WriteLine("Checking for V4.5 for NGEN image {0}", ngenexe);
+ log.WriteLine("Checking for V4.5 for NGEN image {0}", ngenexe);
if (!File.Exists(ngenexe))
{
return null;
@@ -582,7 +577,7 @@ public string GenerateNGenSymbolsForModule(string ngenImageFullPath, string outp
if (fileVersionInfo != null)
{
var clrFileVersion = fileVersionInfo.FileVersion;
- m_log.WriteLine("Got NGEN image file version number: {0}", clrFileVersion);
+ log.WriteLine("Got NGEN image file version number: {0}", clrFileVersion);
m = Regex.Match(clrFileVersion, @"(\d+).(\d+)((\d|\.)*)");
if (m.Success)
@@ -592,7 +587,7 @@ public string GenerateNGenSymbolsForModule(string ngenImageFullPath, string outp
var majorMinor = majorVersion * 10 + minorVersion;
if (majorMinor >= 46)
{
- m_log.WriteLine("Is a V4.6 or beyond");
+ log.WriteLine("Is a V4.6 or beyond");
isV4_5Runtime = true;
}
else if (majorMinor == 40)
@@ -609,8 +604,8 @@ public string GenerateNGenSymbolsForModule(string ngenImageFullPath, string outp
}
var options = new CommandOptions();
- options.AddEnvironmentVariable("_NT_SYMBOL_PATH", SymbolPath);
- options.AddOutputStream(m_log);
+ options.AddEnvironmentVariable("_NT_SYMBOL_PATH", symbolPath);
+ options.AddOutputStream(log);
options.AddNoThrow();
options.AddEnvironmentVariable("COMPLUS_NGenEnableCreatePdb", "1");
@@ -633,12 +628,12 @@ public string GenerateNGenSymbolsForModule(string ngenImageFullPath, string outp
m = Regex.Match(ngenImageFullPath, @"(.*)\\Microsoft\\CLR_v(\d+)\.\d+(_(\d\d))?\\NativeImages", RegexOptions.IgnoreCase);
if (m.Success)
{
- tempDir = Path.Combine(m.Groups[1].Value, @"Temp\NGenPdb");
+ tempDir = Path.Combine(Path.GetTempPath(), "NGenPdb", Path.GetRandomFileName());
DirectoryUtilities.Clean(tempDir);
Directory.CreateDirectory(tempDir);
ngenOutputDirectory = tempDir;
outputPdbPath = Path.Combine(tempDir, relDirPath, pdbFileName);
- m_log.WriteLine("Updating NGEN createPdb output file to {0}", outputPdbPath); // TODO FIX NOW REMOVE (for debugging)
+ log.WriteLine("Updating NGEN createPdb output file to {0}", outputPdbPath); // TODO FIX NOW REMOVE (for debugging)
}
// TODO: Hack. V4.6.1 has both these characteristics, which leads to the issue
@@ -647,7 +642,7 @@ public string GenerateNGenSymbolsForModule(string ngenImageFullPath, string outp
// Should be fixed by 12/2015
if (isV4_5Runtime)
{
- InsurePathIsInNIC(m_log, ref ngenImageFullPath);
+ InsurePathIsInNIC(log, ref ngenImageFullPath);
}
try
@@ -656,8 +651,8 @@ public string GenerateNGenSymbolsForModule(string ngenImageFullPath, string outp
{
if (!string.IsNullOrEmpty(privateRuntimeVerString))
{
- m_log.WriteLine("Ngen will run for private runtime ", privateRuntimeVerString);
- m_log.WriteLine("set COMPLUS_Version=" + privateRuntimeVerString);
+ log.WriteLine("Ngen will run for private runtime ", privateRuntimeVerString);
+ log.WriteLine("set COMPLUS_Version=" + privateRuntimeVerString);
options.AddEnvironmentVariable("COMPLUS_Version", privateRuntimeVerString);
}
// TODO FIX NOW: there is a and ugly problem with persistence of suboptimal PDB files
@@ -668,17 +663,17 @@ public string GenerateNGenSymbolsForModule(string ngenImageFullPath, string outp
var cmdLine = string.Format(@"{0}\ngen.exe createpdb {1} {2} {3}",
clrDir, Command.Quote(ngenImageFullPath), Command.Quote(ngenOutputDirectory), lineNumberArg);
// TODO FIX NOW REMOVE after V4.5 is out a while
- m_log.WriteLine("set COMPLUS_NGenEnableCreatePdb=1");
+ log.WriteLine("set COMPLUS_NGenEnableCreatePdb=1");
if (!isV4_5Runtime)
{
- m_log.WriteLine("set COMPLUS_NGenLocalWorker=1");
+ log.WriteLine("set COMPLUS_NGenLocalWorker=1");
}
- m_log.WriteLine("set PATH=" + newPath);
- m_log.WriteLine("set _NT_SYMBOL_PATH={0}", SymbolPath);
- m_log.WriteLine("*** NGEN CREATEPDB cmdline: {0}\r\n", cmdLine);
+ log.WriteLine("set PATH=" + newPath);
+ log.WriteLine("set _NT_SYMBOL_PATH={0}", symbolPath);
+ log.WriteLine("*** NGEN CREATEPDB cmdline: {0}\r\n", cmdLine);
var cmd = Command.Run(cmdLine, options);
- m_log.WriteLine("*** NGEN CREATEPDB returns: {0}", cmd.ExitCode);
+ log.WriteLine("*** NGEN CREATEPDB returns: {0}", cmd.ExitCode);
if (cmd.ExitCode != 0)
{
@@ -691,7 +686,7 @@ public string GenerateNGenSymbolsForModule(string ngenImageFullPath, string outp
// We may have failed because we could not get the PDB.
if (lineNumberArg.Length != 0)
{
- m_log.WriteLine("Ngen failed to generate pdb for {0}, trying again without /lines", ngenImageFullPath);
+ log.WriteLine("Ngen failed to generate pdb for {0}, trying again without /lines", ngenImageFullPath);
lineNumberArg = "";
continue;
}
@@ -699,7 +694,7 @@ public string GenerateNGenSymbolsForModule(string ngenImageFullPath, string outp
if (cmd.ExitCode != 0 || !File.Exists(outputPdbPath))
{
- m_log.WriteLine("ngen failed to generate pdb for {0} at expected location {1}", ngenImageFullPath, outputPdbPath);
+ log.WriteLine("ngen failed to generate pdb for {0} at expected location {1}", ngenImageFullPath, outputPdbPath);
return null;
}
@@ -729,12 +724,12 @@ public string GenerateNGenSymbolsForModule(string ngenImageFullPath, string outp
///
/// TODO can be removed when we properly publish the NGEN pdbs as part of build.
///
- private string HandleNetCorePdbs(string ngenImageFullPath, string pdbPath)
+ private static string HandleNetCorePdbs(string ngenImageFullPath, string pdbPath, TextWriter log)
{
// We only handle NGEN PDB.
if (!pdbPath.EndsWith(".ni.pdb", StringComparison.OrdinalIgnoreCase))
{
- m_log.WriteLine("Not a crossGen PDB {0}", pdbPath);
+ log.WriteLine("Not a crossGen PDB {0}", pdbPath);
return null;
}
@@ -742,10 +737,10 @@ private string HandleNetCorePdbs(string ngenImageFullPath, string pdbPath)
var pdbDir = Path.GetDirectoryName(pdbPath);
// We need Crossgen, and there are several options, see what we can do.
- string crossGen = GetCrossGenExePath(ngenImageFullPath);
+ string crossGen = GetCrossGenExePath(ngenImageFullPath, log);
if (crossGen == null)
{
- m_log.WriteLine("Could not find Crossgen.exe to generate PDBs, giving up.");
+ log.WriteLine("Could not find Crossgen.exe to generate PDBs, giving up.");
return null;
}
@@ -775,7 +770,7 @@ private string HandleNetCorePdbs(string ngenImageFullPath, string pdbPath)
" " + Command.Quote(crossGenInputName);
var options = new CommandOptions();
- options.AddOutputStream(m_log);
+ options.AddOutputStream(log);
options.AddNoThrow();
// Needs diasymreader.dll to be on the path.
@@ -783,9 +778,9 @@ private string HandleNetCorePdbs(string ngenImageFullPath, string pdbPath)
winDir + @"\Microsoft.NET\Framework64\v4.0.30319" + ";%PATH%";
options.AddEnvironmentVariable("PATH", newPath);
options.AddCurrentDirectory(ngenImageDir);
- m_log.WriteLine("**** Running CrossGen");
- m_log.WriteLine("set PATH=" + newPath);
- m_log.WriteLine("{0}\r\n", cmdLine);
+ log.WriteLine("**** Running CrossGen");
+ log.WriteLine("set PATH=" + newPath);
+ log.WriteLine("{0}\r\n", cmdLine);
var cmd = Command.Run(cmdLine, options);
// Delete the temporary file if necessary
@@ -796,7 +791,7 @@ private string HandleNetCorePdbs(string ngenImageFullPath, string pdbPath)
if (cmd.ExitCode != 0 || !File.Exists(pdbPath))
{
- m_log.WriteLine("CrossGen failed to generate {0} exit code {0}", pdbPath, cmd.ExitCode);
+ log.WriteLine("CrossGen failed to generate {0} exit code {0}", pdbPath, cmd.ExitCode);
return null;
}
@@ -826,12 +821,12 @@ private static string getNugetPackageDir()
return nugetPackageDir;
}
- private string GetCrossGenExePath(string ngenImageFullPath)
+ private static string GetCrossGenExePath(string ngenImageFullPath, TextWriter log)
{
var imageDir = Path.GetDirectoryName(ngenImageFullPath);
string crossGen = Path.Combine(imageDir, "crossGen.exe");
- m_log.WriteLine("Checking for CoreCLR case, looking for CrossGen at {0}", crossGen);
+ log.WriteLine("Checking for CoreCLR case, looking for CrossGen at {0}", crossGen);
if (File.Exists(crossGen))
{
return crossGen;
@@ -841,11 +836,11 @@ private string GetCrossGenExePath(string ngenImageFullPath)
if (File.Exists(coreclr))
{
DateTime coreClrTimeStamp = File.GetLastWriteTimeUtc(coreclr);
- m_log.WriteLine("Found coreclr: at {0}, timestamp {1}", coreclr, coreClrTimeStamp);
+ log.WriteLine("Found coreclr: at {0}, timestamp {1}", coreclr, coreClrTimeStamp);
string nugetDir = getNugetPackageDir();
if (nugetDir != null)
{
- m_log.WriteLine("Found nuget package dir: at {0}", nugetDir);
+ log.WriteLine("Found nuget package dir: at {0}", nugetDir);
foreach (var runtimeDir in Directory.GetDirectories(nugetDir, "runtime.win*.microsoft.netcore.runtime.coreclr"))
{
foreach (var runtimeVersionDir in Directory.GetDirectories(runtimeDir))
@@ -854,11 +849,11 @@ private string GetCrossGenExePath(string ngenImageFullPath)
{
string packageCoreCLR = Path.Combine(osarchDir, @"native\coreclr.dll");
DateTime packageCoreClrTimeStamp = File.GetLastWriteTimeUtc(packageCoreCLR);
- m_log.WriteLine("Checking timestamp of file {0} = {1}", packageCoreCLR, packageCoreClrTimeStamp);
+ log.WriteLine("Checking timestamp of file {0} = {1}", packageCoreCLR, packageCoreClrTimeStamp);
if (File.Exists(packageCoreCLR) && packageCoreClrTimeStamp == coreClrTimeStamp)
{
crossGen = Path.Combine(runtimeVersionDir, @"tools\crossgen.exe");
- m_log.WriteLine("Found matching CoreCLR, probing for crossgen at {0}", crossGen);
+ log.WriteLine("Found matching CoreCLR, probing for crossgen at {0}", crossGen);
if (File.Exists(crossGen))
{
return crossGen;
@@ -881,12 +876,12 @@ private string GetCrossGenExePath(string ngenImageFullPath)
}
}
- m_log.WriteLine("Could not find crossgen, giving up");
+ log.WriteLine("Could not find crossgen, giving up");
return null;
}
// TODO remove after 12/2015
- private void InsurePathIsInNIC(TextWriter log, ref string ngenImageFullPath)
+ private static void InsurePathIsInNIC(TextWriter log, ref string ngenImageFullPath)
{
// We only get called if we are 4.5. or beyond, so we should have AUX files if we are in the nic.
string auxFilePath = ngenImageFullPath + ".aux";
diff --git a/src/TraceEvent/ZippedETL.cs b/src/TraceEvent/ZippedETL.cs
index bb0421ebf..c3dfc181a 100644
--- a/src/TraceEvent/ZippedETL.cs
+++ b/src/TraceEvent/ZippedETL.cs
@@ -401,17 +401,45 @@ internal static List GetNGenPdbs(string etlFile, SymbolReader symbolRead
{
// Generate the NGen images for any NGEN image needing symbolic information.
var pdbFileList = new List(100);
+ var tasks = new List>>();
foreach (var imageName in ETWTraceEventSource.GetModulesNeedingSymbols(etlFile))
{
- var sw = Stopwatch.StartNew();
- var pdbName = symbolReader.GenerateNGenSymbolsForModule(imageName);
+ var symbolPath = symbolReader.SymbolPath;
+ var symbolCacheDirectory = symbolReader.SymbolCacheDirectory;
+
+ tasks.Add(Task.Run(() =>
+ {
+ var sw = Stopwatch.StartNew();
+ using (var log = new StringWriter())
+ {
+ var pdbName = SymbolReader.GenerateNGenSymbolsForModule(imageName, log, symbolPath, symbolCacheDirectory);
+ return Tuple.Create(imageName, pdbName, log.ToString(), sw.Elapsed);
+ }
+ }));
+ }
+
+ Task.WaitAll(tasks.ToArray());
+ foreach (var task in tasks)
+ {
+ var imageName = task.Result.Item1;
+ var pdbName = task.Result.Item2;
+ var taskLog = task.Result.Item3;
+ var elapsed = task.Result.Item4;
+
+ if (!string.IsNullOrEmpty(taskLog))
+ {
+ symbolReader.Log.Write(taskLog);
+ }
+
if (pdbName != null)
{
pdbFileList.Add(pdbName);
log.WriteLine("Found NGEN pdb {0}", pdbName);
}
- log.WriteLine("NGEN PDB creation for {0} took {1:n2} Sec", imageName, sw.Elapsed.TotalSeconds);
+
+ log.WriteLine("NGEN PDB creation for {0} took {1:n2} Sec", imageName, elapsed.TotalSeconds);
}
+
return pdbFileList;
}