diff options
author | Radek Doulik <radekdoulik@users.noreply.github.com> | 2019-08-07 19:24:51 +0300 |
---|---|---|
committer | Alexander Köplinger <alex.koeplinger@outlook.com> | 2019-08-07 19:24:51 +0300 |
commit | 1f2b37ed37ec0f28129a6041e977f465188dff5a (patch) | |
tree | cdd882755790643bcc1c2207697b8902c7684e4a /mcs/tools | |
parent | dcd57151613af34b213e0bd49de70e402d19cc47 (diff) |
[aotprof-tool] Initial import of AOT profiler tool (#15384)
* [aotprof-tool] Initial import
Imported https://github.com/radekdoulik/aotprofile-tool and updated it
to use Mono.Profiler.Log
* [aotprof-tool] Added man page
* [aotprof-tool] Use the shortened name in README.md
Diffstat (limited to 'mcs/tools')
-rw-r--r-- | mcs/tools/Makefile | 1 | ||||
-rw-r--r-- | mcs/tools/aprofutil/Makefile | 8 | ||||
-rw-r--r-- | mcs/tools/aprofutil/Program.cs | 232 | ||||
-rw-r--r-- | mcs/tools/aprofutil/README.md | 70 | ||||
-rw-r--r-- | mcs/tools/aprofutil/aprofutil.csproj | 66 | ||||
-rw-r--r-- | mcs/tools/aprofutil/aprofutil.exe.sources | 1 |
6 files changed, 378 insertions, 0 deletions
diff --git a/mcs/tools/Makefile b/mcs/tools/Makefile index c632a8bf388..fcda3b1b56e 100644 --- a/mcs/tools/Makefile +++ b/mcs/tools/Makefile @@ -2,6 +2,7 @@ thisdir = tools net_4_5_dirs := \ al \ + aprofutil \ linker \ culevel \ genxs \ diff --git a/mcs/tools/aprofutil/Makefile b/mcs/tools/aprofutil/Makefile new file mode 100644 index 00000000000..46b47779c3c --- /dev/null +++ b/mcs/tools/aprofutil/Makefile @@ -0,0 +1,8 @@ +thisdir = tools/aprofutil +include ../../build/rules.make + +PROGRAM = aprofutil.exe + +LIB_REFS = System System.Core Mono.Options Mono.Profiler.Log + +include ../../build/executable.make diff --git a/mcs/tools/aprofutil/Program.cs b/mcs/tools/aprofutil/Program.cs new file mode 100644 index 00000000000..edf245f6ed2 --- /dev/null +++ b/mcs/tools/aprofutil/Program.cs @@ -0,0 +1,232 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using Mono.Options; +using Mono.Profiler.Aot; + +using static System.Console; + +namespace aotprofiletool { + class MainClass { + static readonly string Name = "aotprofile-tool"; + + static bool Methods; + static bool Modules; + static bool Summary; + static bool Types; + static bool Verbose; + + static Regex FilterMethod; + static Regex FilterModule; + static Regex FilterType; + + static string Output; + + static string ProcessArguments (string [] args) + { + var help = false; + var options = new OptionSet { + $"Usage: {Name}.exe OPTIONS* <aotprofile-file>", + "", + "Processes AOTPROFILE files created by Mono's AOT Profiler", + "", + "Copyright 2019 Microsoft Corporation", + "", + "Options:", + { "h|help|?", + "Show this message and exit", + v => help = v != null }, + { "a|all", + "Show modules, types and methods in the profile", + v => Modules = Types = Methods = true }, + { "d|modules", + "Show modules in the profile", + v => Modules = true }, + { "filter-method=", + "Filter by method with regex VALUE", + v => FilterMethod = new Regex (v) }, + { "filter-module=", + "Filter by module with regex VALUE", + v => FilterModule = new Regex (v) }, + { "filter-type=", + "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", + v => Output = v }, + { "s|summary", + "Show summary of the profile", + v => Summary = true }, + { "t|types", + "Show types in the profile", + v => Types = true }, + { "v|verbose", + "Output information about progress during the run of the tool", + v => Verbose = true }, + "", + "If no other option than -v is used then --all is used by default" + }; + + var remaining = options.Parse (args); + + if (help || args.Length < 1) { + options.WriteOptionDescriptions (Out); + + Environment.Exit (0); + } + + if (remaining.Count != 1) { + Error ("Please specify one <aotprofile-file> to process."); + Environment.Exit (2); + } + + return remaining [0]; + } + + public static void Main (string [] args) + { + var path = ProcessArguments (args); + + if (!File.Exists (path)) { + Error ($"'{path}' doesn't exist."); + Environment.Exit (3); + } + + 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); + + pd = reader.ReadAllData (stream); + } + + List<MethodRecord> methods = new List<MethodRecord> (pd.Methods); + ICollection<TypeRecord> types = new List<TypeRecord> (pd.Types); + ICollection<ModuleRecord> modules = new List<ModuleRecord> (pd.Modules); + + if (FilterMethod != null || FilterType != null || FilterModule != null) { + methods = new List<MethodRecord> (); + types = new HashSet<TypeRecord> (); + modules = new HashSet<ModuleRecord> (); + + foreach (var method in pd.Methods) { + + var type = method.Type; + var module = type.Module; + + if (FilterModule != null) { + var match = FilterModule.Match (module.ToString ()); + + if (!match.Success) + continue; + } + + if (FilterType != null) { + var match = FilterType.Match (method.Type.ToString ()); + + if (!match.Success) + continue; + } + + if (FilterMethod != null) { + var match = FilterMethod.Match (method.ToString ()); + + if (!match.Success) + continue; + } + + methods.Add (method); + types.Add (type); + modules.Add (module); + } + } + + if (FilterMethod == null && FilterType != null) { + foreach (var type in pd.Types) { + if (types.Contains (type)) + continue; + + var match = FilterType.Match (type.ToString ()); + + if (!match.Success) + continue; + + types.Add (type); + } + } + + if (Modules) { + ColorWriteLine ($"Modules:", ConsoleColor.Green); + + foreach (var module in modules) + WriteLine ($"\t{module.Mvid} {module.ToString ()}"); + } + + if (Types) { + ColorWriteLine ($"Types:", ConsoleColor.Green); + + foreach (var type in types) + WriteLine ($"\t{type}"); + } + + if (Methods) { + ColorWriteLine ($"Methods:", ConsoleColor.Green); + + foreach (var method in methods) + WriteLine ($"\t{method}"); + } + + if (Summary) { + ColorWriteLine ($"Summary:", ConsoleColor.Green); + WriteLine ($"\tModules: {modules.Count.ToString ("N0"),10}{(modules.Count != pd.Modules.Length ? $" (of {pd.Modules.Length})" : "" )}"); + WriteLine ($"\tTypes: {types.Count.ToString ("N0"),10}{(types.Count != pd.Types.Length ? $" (of {pd.Types.Length})" : "")}"); + WriteLine ($"\tMethods: {methods.Count.ToString ("N0"),10}{(methods.Count != pd.Methods.Length ? $" (of {pd.Methods.Length})" : "")}"); + } + + if (!string.IsNullOrEmpty (Output)) { + if (Verbose) + ColorWriteLine ($"Going to write the profile to '{Output}'", ConsoleColor.Yellow); + var modulesArray = new ModuleRecord [modules.Count]; + modules.CopyTo (modulesArray, 0); + var typesArray = new TypeRecord [types.Count]; + types.CopyTo (typesArray, 0); + var updatedPD = new ProfileData (modulesArray, typesArray, methods.ToArray ()); + + using (var stream = new FileStream (Output, FileMode.Create)) { + var writer = new ProfileWriter (); + writer.WriteAllData (stream, updatedPD); + } + } + } + + static void ColorMessage (string message, ConsoleColor color, TextWriter writer, bool writeLine = true) + { + ForegroundColor = color; + + if (writeLine) + writer.WriteLine (message); + else + writer.Write (message); + + ResetColor (); + } + + public static void ColorWriteLine (string message, ConsoleColor color) => ColorMessage (message, color, Out); + + public static void ColorWrite (string message, ConsoleColor color) => ColorMessage (message, color, Out, false); + + public static void Error (string message) => ColorMessage ($"Error: {Name}: {message}", ConsoleColor.Red, Console.Error); + + public static void Warning (string message) => ColorMessage ($"Warning: {Name}: {message}", ConsoleColor.Yellow, Console.Error); + } +} diff --git a/mcs/tools/aprofutil/README.md b/mcs/tools/aprofutil/README.md new file mode 100644 index 00000000000..22e749e20c9 --- /dev/null +++ b/mcs/tools/aprofutil/README.md @@ -0,0 +1,70 @@ +**aprofutil** is a tool to inspect AOT profiler files + +``` +Usage: aprofutil.exe OPTIONS* <aotprofile-file> + +Processes AOTPROFILE files created by Mono's AOT Profiler + +Copyright 2019 Microsoft Corporation + +Options: + -h, --help, -? Show this message and exit + -a, --all Show modules, types and methods in the profile + -d, --modules Show modules in the profile + --filter-method=VALUE Filter by method with regex VALUE + --filter-module=VALUE Filter by module with regex VALUE + --filter-type=VALUE Filter by type with regex VALUE + -m, --methods Show methods in the profile + -s, --summary Show summary of the profile + -t, --types Show types in the profile + -v, --verbose Output information about progress during the run + of the tool + +If no other option than -v is used then --all is used by default +``` + +It can be use to show and filter the profiler file content in readable text form. + +### Example usage + +Display modules and summary of XA startup profile +``` +mono aprofutil.exe -sd startup.aotprofile +Modules: + 41C38B0A-2032-45CE-8638-0299CED65330 mscorlib + 0326DF03-2158-4F7A-9A2B-B7A9419F021D Mono.Android + 8FB63BB4-1195-4173-A9ED-0EC341B07C32 System + 74C06E06-C1C7-4A4C-B64E-EAC7DBB08BBC Java.Interop + 11E2319F-6A26-461C-9C46-C972248BEE4B System.Core + 7999CC4B-D566-4ECA-8A72-469344172CA3 Xamarin.Forms.Platform.Android + C5089213-328B-451D-BA87-D6585C120780 Xamarin.Forms.Performance.Integration.Droid + D754F8AE-503C-41C8-B16F-647FC662507A Xamarin.Android.Support.v7.AppCompat + 929ECB6D-1171-4C66-8470-DD32AC608969 Xamarin.Android.Support.Fragment + F841E23B-59A8-4AE2-9A84-D2FC1D891B4A Xamarin.Forms.Core + 945CCBF8-C2DB-468B-B3BD-D7ACA37B69AD Xamarin.Forms.Performance.Integration + AF20FA19-F07E-4BD4-B5ED-104706EA660E Xamarin.Forms.Xaml + 629C84F8-0988-42EF-8BC5-872173A0A71F FormsViewGroup + 60398815-8E62-487E-A553-781F56A0849D Xamarin.Android.Support.Design + F0C550D7-665A-40B5-A307-8E9B49976D87 Xamarin.Android.Support.Core.UI + 23A34485-DE75-440E-BA9D-E235F664E990 Xamarin.Android.Support.Compat +Summary: + Modules: 16 + Types: 907 + Methods: 4,230 +``` + +Filter Java.Interop.Runtime type in XA startup profile: +``` +mono aprofutil.exe --filter-type Java.Interop.Runtime -sa startup.aotprofile +Modules: + 0326DF03-2158-4F7A-9A2B-B7A9419F021D Mono.Android +Types: + Java.Interop.Runtime +Methods: + bool Java.Interop.Runtime:IsGCUserPeer (Android.Runtime.IJavaObject) + bool Java.Interop.Runtime:IsGCUserPeer (intptr) +Summary: + Modules: 1 (of 16) + Types: 1 (of 907) + Methods: 2 (of 4230) +``` diff --git a/mcs/tools/aprofutil/aprofutil.csproj b/mcs/tools/aprofutil/aprofutil.csproj new file mode 100644 index 00000000000..faa957543d6 --- /dev/null +++ b/mcs/tools/aprofutil/aprofutil.csproj @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- WARNING: this file is autogenerated, don't modify it. Edit the .sources file of the corresponding assembly instead if you want to add/remove C# source files. --> +<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">net_4_x</Platform> + <ProjectGuid>{658B566B-CED1-4C42-9926-C1AA930BA368}</ProjectGuid> + <OutputType>Exe</OutputType> + <NoWarn>1699</NoWarn> + <LangVersion>latest</LangVersion> + <HostPlatform Condition=" '$(HostPlatform)' == '' and '$(OS)' == 'Windows_NT'">win32</HostPlatform> + <HostPlatform Condition=" '$(HostPlatform)' == '' and '$(OS)' == 'Unix' and $([System.IO.File]::Exists('/usr/lib/libc.dylib'))">macos</HostPlatform> + <HostPlatform Condition=" '$(HostPlatform)' == '' and '$(OS)' == 'Unix'">linux</HostPlatform> + <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute> + <NoStdLib>False</NoStdLib> + <NoConfig>True</NoConfig> + <AssemblyName>aprofutil</AssemblyName> + <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion> + </PropertyGroup> + <PropertyGroup> + <!-- Set AddAdditionalExplicitAssemblyReferences to false, otherwise if targetting .NET4.0, + Microsoft.NETFramework.props will force a dependency on the assembly System.Core. This + is a problem to compile the Mono mscorlib.dll --> + <AddAdditionalExplicitAssemblyReferences>false</AddAdditionalExplicitAssemblyReferences> + </PropertyGroup> + <PropertyGroup Condition=" '$(Platform)' == 'net_4_x' "> + <OutputPath>./../../class/lib/net_4_x-$(HostPlatform)</OutputPath> + <IntermediateOutputPath>./../../class/obj/$(AssemblyName)-net_4_x-$(HostPlatform)</IntermediateOutputPath> + <DefineConstants>NET_4_0;NET_4_5;NET_4_6;MONO;WIN_PLATFORM</DefineConstants> + </PropertyGroup> + <!-- @ALL_PROFILE_PROPERTIES@ --> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <!-- TRACE is set only for Debug configuration, so inherit from platform-specific value --> + <DefineConstants>TRACE;$(DefineConstants)</DefineConstants> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Release' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + </PropertyGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- @BUILT_SOURCES@ --> + <!--Common files--> + <ItemGroup> + <Compile Include="Program.cs" /> + </ItemGroup> + <!--End of common files--> + <!-- @ALL_SOURCES@ --> + <!-- @COMMON_PROJECT_REFERENCES@ --> + <ItemGroup Condition=" '$(Platform)' == 'net_4_x' "> + <ProjectReference Include="../../class/System/System.csproj" /> + <ProjectReference Include="../../class/System.Core/System.Core.csproj" /> + <ProjectReference Include="../../class/Mono.Options/Mono.Options.csproj" /> + <ProjectReference Include="../../class/Mono.Profiler.Log/Mono.Profiler.Log.csproj" /> + </ItemGroup> + <!-- @ALL_REFERENCES@ --> + <!-- @ALL_RESOURCES@ --> + <PropertyGroup> + <!-- Force the pre-build event to run after references have been resolved. The default + behavior is to run them before resolving references, which can cause things like + culevel.exe to be used before they have been built. --> + <PreBuildEventDependsOn>ResolveReferences</PreBuildEventDependsOn> + </PropertyGroup> +</Project>
\ No newline at end of file diff --git a/mcs/tools/aprofutil/aprofutil.exe.sources b/mcs/tools/aprofutil/aprofutil.exe.sources new file mode 100644 index 00000000000..48de7b53bdd --- /dev/null +++ b/mcs/tools/aprofutil/aprofutil.exe.sources @@ -0,0 +1 @@ +Program.cs |