diff options
author | Radek Doulik <radekdoulik@users.noreply.github.com> | 2019-09-11 15:42:58 +0300 |
---|---|---|
committer | Larry Ewing <lewing@microsoft.com> | 2019-09-11 15:42:58 +0300 |
commit | 52aa2cd3e138218f2639200688e9a7808c0f7da6 (patch) | |
tree | c70f59b40feee20d08aaca19d40d825f992d9f54 /mcs/tools | |
parent | f97ceb5c3e9180e1be0d83eb8a5c98c5c945ea33 (diff) |
[aprofutil] Add -p and -f options (#16766)
-p PORT allows easier retrieval of AOT profile from the application
running with aot profiler, using the socket connection on local PORT
-f instructs the tool to try setup adb port forwarding to/from Android
device or emulator
Example usage, retrieve the AOT profile from Android:
> mono aprofutil.exe -s -v -f -p 9998 -o my.aprof
Calling 'adb forward tcp:9998 tcp:9998'...
Reading from '127.0.0.1:9998'...
Read total 94903 bytes...
Summary:
Modules: 6
Types: 262
Methods: 1,162
Going to write the profile to 'my.aprof'
Diffstat (limited to 'mcs/tools')
-rw-r--r-- | mcs/tools/aprofutil/Program.cs | 103 |
1 files changed, 85 insertions, 18 deletions
diff --git a/mcs/tools/aprofutil/Program.cs b/mcs/tools/aprofutil/Program.cs index edf245f6ed2..12972eb7348 100644 --- a/mcs/tools/aprofutil/Program.cs +++ b/mcs/tools/aprofutil/Program.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Net.Sockets; using System.Text.RegularExpressions; using Mono.Options; using Mono.Profiler.Aot; @@ -11,6 +12,7 @@ namespace aotprofiletool { class MainClass { static readonly string Name = "aotprofile-tool"; + static bool AdbForward; static bool Methods; static bool Modules; static bool Summary; @@ -23,6 +25,8 @@ namespace aotprofiletool { static string Output; + static int Port = -1; + static string ProcessArguments (string [] args) { var help = false; @@ -43,21 +47,27 @@ namespace aotprofiletool { { "d|modules", "Show modules in the profile", v => Modules = true }, + { "f|adb-forward", + "Set adb socket forwarding for Android", + v => AdbForward = true }, { "filter-method=", - "Filter by method with regex VALUE", + "Filter by method with regex {VALUE}", v => FilterMethod = new Regex (v) }, { "filter-module=", - "Filter by module with regex VALUE", + "Filter by module with regex {VALUE}", v => FilterModule = new Regex (v) }, { "filter-type=", - "Filter by type with regex VALUE", + "Filter by type with regex {VALUE}", v => FilterType = new Regex (v) }, { "m|methods", "Show methods in the profile", v => Methods = true }, { "o|output=", - "Write profile to OUTPUT file", + "Write profile to {OUTPUT} file", v => Output = v }, + { "p|port=", + "Read profile from aot profiler using local connection on {PORT}", + v => int.TryParse (v, out Port) }, { "s|summary", "Show summary of the profile", v => Summary = true }, @@ -79,35 +89,92 @@ namespace aotprofiletool { Environment.Exit (0); } - if (remaining.Count != 1) { - Error ("Please specify one <aotprofile-file> to process."); + if (remaining.Count != 1 && Port < 0) { + Error ("Please specify one <aotprofile-file> to process or network PORT with -p."); Environment.Exit (2); } - return remaining [0]; + return remaining.Count > 0 ? remaining [0] : null; } - public static void Main (string [] args) + static ProfileData ReadProfileFromPort (ProfileReader reader) { - var path = ProcessArguments (args); + ProfileData pd; - if (!File.Exists (path)) { - Error ($"'{path}' doesn't exist."); - Environment.Exit (3); + if (AdbForward) { + var cmdArgs = $"forward tcp:{Port} tcp:{Port}"; + if (Verbose) + ColorWriteLine ($"Calling 'adb {cmdArgs}'...", ConsoleColor.Yellow); + + System.Diagnostics.Process.Start ("adb", cmdArgs); + } + + using (var client = new TcpClient ("127.0.0.1", Port)) { + using (var stream = client.GetStream ()) { + var msgData = System.Text.Encoding.ASCII.GetBytes ("save\n"); + + stream.Write (msgData, 0, msgData.Length); + + if (Verbose) + ColorWriteLine ($"Reading from '127.0.0.1:{Port}'...", ConsoleColor.Yellow); + + using (var memoryStream = new MemoryStream (128 * 1024)) { + var data = new byte [4 * 1024]; + int len; + + while ((len = stream.Read (data, 0, data.Length)) > 0) { + memoryStream.Write (data, 0, len); + + if (Verbose) + ColorWrite ($"Read {len} bytes...\r", ConsoleColor.Yellow); + } + + if (Verbose) + ColorWriteLine ($"Read total {memoryStream.Length} bytes...", ConsoleColor.Yellow); + + memoryStream.Seek (0, SeekOrigin.Begin); + + pd = reader.ReadAllData (memoryStream); + } + } } + return pd; + } + + public static void Main (string [] args) + { + var path = ProcessArguments (args); + if (args.Length == 1) { Modules = Types = Methods = true; } var reader = new ProfileReader (); - ProfileData pd; - - using (var stream = new FileStream (path, FileMode.Open)) { - if (Verbose) - ColorWriteLine ($"Reading '{path}'...", ConsoleColor.Yellow); + ProfileData pd = null; + + if (path == null) { + if (Port < 0) { + Error ($"You should specify path or -p PORT to read the profile."); + Environment.Exit (4); + } else { + try { + pd = ReadProfileFromPort (reader); + } catch (Exception e) { + Error ($"Unable to read profile through local port: {Port}.\n{e}"); + Environment.Exit (5); + } + } + } else if (!File.Exists (path)) { + Error ($"'{path}' doesn't exist."); + Environment.Exit (3); + } else { + using (var stream = new FileStream (path, FileMode.Open)) { + if (Verbose) + ColorWriteLine ($"Reading '{path}'...", ConsoleColor.Yellow); - pd = reader.ReadAllData (stream); + pd = reader.ReadAllData (stream); + } } List<MethodRecord> methods = new List<MethodRecord> (pd.Methods); |