dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.47k stars 4.76k forks source link

Mono AOT image size profiling #82101

Open kotlarmilos opened 1 year ago

kotlarmilos commented 1 year ago

Description

Size investigation of Mono AOT binaries relies on profiling tools like bloaty and otool which provide good insight about content of a binary. However, even with such tools, it is not straightforward to identify if data are redundant between different AOT images linked into a single binary.

For example, it might be beneficial to find methods that are duplicated in different AOT images. Also, it might be beneficial to preview methods info table, methods to llvm table, PLT and GOT entries, number of patches per method, etc.

The idea is to extend https://github.com/dotnet/runtime/issues/79551 to output method code size and number of patches in addition to method name. It could output such data per AOT image and aggregated data with redundancies for a binary. It should help us identify redundant data in AOT images and allow us to be more data-driven.

This PR should collect all relevant data needed for Mono AOT size profiling and check if such mechanism has been already implemented or drafted. Ideas on what could be included into the Mono AOT size profiling are more than welcome.

/cc: @lambdageek @vargaz @fanyang-mono @ivanpovazan @jandupej @LeVladIonescu @SamMonoRT

ivanpovazan commented 1 year ago

/cc: @lateralusX

lateralusX commented 1 year ago

size of per method unwind data is also interesting to include. Mono uses its own unwind format and I know that we get duplication in that space since the target platform also include platform specific unwind data per method. When running in llvmonly mode (like WASM), we fallback to platform specific unwind data since we utilize C++ unwinder, so that shouldn't carry the additional Mono unwind data since we use stock LLVM tooling not capable of emitting Mono specific unwind data.

kotlarmilos commented 1 year ago

size of per method unwind data is also interesting to include. Mono uses its own unwind format and I know that we get duplication in that space since the target platform also include platform specific unwind data per method. When running in llvmonly mode (like WASM), we fallback to platform specific unwind data since we utilize C++ unwinder, so that shouldn't carry the additional Mono unwind data since we use stock LLVM tooling not capable of emitting Mono specific unwind data.

Thanks for the suggestion! Trying to understand a use case where Mono specific unwind data are redundant. When running in llvmonly mode, Mono specific unwind data are not necessary as platform specific unwind data are used due to utilization of C++ unwinder, right?

lateralusX commented 1 year ago

Yes llvmonly relies on C++ unwinder so shouldn't add additional unwind data to image. AFAIK llvmonly uses a shadow stack on platforms where it can't take context meaning that prolog/epilog push/pop information about current frame in order to do a stackwalk when needed, but all unwinding is done using C++ exception handling.

When using Mono's LLVM backend we have customization that will emit generated unwind info into Mono specific format for Mono unwinder, but I believe we would also get OS specific unwind info in that case since OS needs to unwind each compiled method as well using the unwind info format used by OS when building through LLVM. When using our JIT AOT compiler we generate dwarf unwind info and setup the needed OS unwind info as part of generating the image, but on platform that doesn't use dwarf (windows) we would end up with both Mono unwind info as well as OS specific unwind info per function.

kotlarmilos commented 1 year ago

The profiler could output the following in a file:

There are two options -- profiling during the compilation and profiling a binary. Profiling during the compilation would require changes across AOT compiler to collect all necessary data. Profiling a binary would rely on Mono API and could be a separate source file.

kotlarmilos commented 1 year ago

Also, it would be good to revise available options. @mdh1418 is there a similar tool that we can use for size profiling?

mdh1418 commented 1 year ago

Also, it would be good to revise available options. @mdh1418 is there a similar tool that we can use for size profiling?

Not sure if these can be used for profiling the size of mono aot images, but I had previously used dotnet trace to profile what methods were hit when an app ran in conjunction with coreclr's dotnet-pgo tool to specifically AOT hot methods. https://github.com/dotnet/runtime/pull/70851 and https://github.com/dotnet/runtime/pull/70194 descriptions exemplify how the two tools can be used.

kotlarmilos commented 1 year ago

Thanks, we will check it out. Also, there is aot_dump that outputs emitted methods, PLT and GOT entries. https://github.com/dotnet/runtime/blob/db084d9ea1287a5f90b93071512a9559a0d33c0d/src/mono/mono/mini/aot-compiler.c#L15232-L15233

It could be enriched with the above-mentioned properties.

  • methods/extra methods/trampolines - assembly_name method_token method_name method_signature flags code_size number_of_patches unwind_info_size
  • types - class_token class_name vtable_size
  • got and plt entries - entries size
  • methods to llvm table - entries size
kotlarmilos commented 1 year ago

Size profiling tool for Native AOT binaries - https://github.com/MichalStrehovsky/sizoscope