Skip to content

Instantly share code, notes, and snippets.

@filipnavara
Created January 25, 2019 18:07
Show Gist options
  • Save filipnavara/8b12019ce2321e83a79d11a1d5f4f093 to your computer and use it in GitHub Desktop.
Save filipnavara/8b12019ce2321e83a79d11a1d5f4f093 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
namespace MailClient.Utils
{
class MonoProfiling
{
#if MAC
public static void Profile(int seconds, string outputPath)
{
var outputFilePath = Path.GetTempFileName();
var startInfo = new ProcessStartInfo("sample");
startInfo.UseShellExecute = false;
startInfo.Arguments = $"{Process.GetCurrentProcess().Id} {seconds} -file {outputFilePath}";
var sampleProcess = Process.Start(startInfo);
sampleProcess.EnableRaisingEvents = true;
sampleProcess.Exited += delegate
{
ConvertJITAddressesToMethodNames(outputFilePath, "Profile", outputPath);
File.Delete(outputFilePath);
};
}
[DllImport("__Internal")]
extern static string mono_pmip(long offset);
static Dictionary<long, string> methodsCache = new Dictionary<long, string>();
static void ConvertJITAddressesToMethodNames(string fileName, string profilingType, string outputPath)
{
var rx = new Regex(@"\?\?\? \(in <unknown binary>\) \[0x([0-9a-f]+)\]", RegexOptions.Compiled);
if (File.Exists(fileName) && new FileInfo(fileName).Length > 0)
{
Directory.CreateDirectory(outputPath);
var outputFilename = Path.Combine(outputPath, $"{profilingType}_{DateTime.Now:yyyy-MM-dd__HH-mm-ss}.txt");
using (var sr = new StreamReader(fileName))
using (var sw = new StreamWriter(outputFilename))
{
string line;
while ((line = sr.ReadLine()) != null)
{
if (rx.IsMatch(line))
{
var match = rx.Match(line);
var offset = long.Parse(match.Groups[1].Value, NumberStyles.HexNumber);
string pmipMethodName;
if (!methodsCache.TryGetValue(offset, out pmipMethodName))
{
pmipMethodName = mono_pmip(offset)?.TrimStart();
methodsCache.Add(offset, pmipMethodName);
}
if (pmipMethodName != null)
{
line = line.Remove(match.Index, match.Length);
line = line.Insert(match.Index, pmipMethodName);
}
}
sw.WriteLine(line);
}
}
}
}
#endif
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment