-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Mono]: Add "driver" support to Mono AOT cross compiler. #97226
[Mono]: Add "driver" support to Mono AOT cross compiler. #97226
Conversation
src/mono/mono/mini/aot-compiler.c
Outdated
@@ -9067,6 +9109,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) | |||
printf (" direct-pinvokes=<string> - Specific direct pinvokes to generate direct calls for an entire 'module' or specific 'module!entrypoint' separated by semi-colons. Incompatible with 'direct-pinvoke' option.\n"); | |||
printf (" direct-pinvoke-lists=<string> - Files containing specific direct pinvokes to generate direct calls for an entire 'module' or specific 'module!entrypoint' on separate lines. Incompatible with 'direct-pinvoke' option.\n"); | |||
printf (" direct-pinvoke - Generate direct calls for all direct pinvokes encountered in the managed assembly.\n"); | |||
printf (" driver - Run AOT compiler in driver mode. Runs cross compiler and tools as child processes.\n"); | |||
printf (" driver-logfile - Pass by driver parent process when executin AOT cross compiler as a child process. Executed commands will be logged into file instead of executed by child process. Path to file or 'stdout'.\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo 'executin'.
static int driver_log_file_fd = -1; | ||
|
||
typedef enum { | ||
CROSS_COMPILER_COMMAND, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be possible to just replace this with a generic 'exec_command' facility ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wanted to have a more structural way to describe supported commands making it simpler for clients to quickly identify/validate the commands that are requested to be executed. Also, since several tools have different names on different platforms, having a way to type it also makes it simpler for the clients to identify what things its supposed to be executed and take decisions based on that. The pace of adding new commands to AOT compiler is also very slow, so don't anticipate to much change here either.
Wouldn't it be better to have this as a python/c#/msbuild script/task ? |
You mean the driver portion of the PR, running the second instance of AOT compiler + executing the commands returned over stdout? With the current implementation it is possible to implement a driver in any language as a complement to the driver, just run AOT compiler with driver-logfile=stdout from a different driver implementation and then take care of the commands returned in the stream. I also added the driver capabilities to AOT compiler since it will make it simple to use the feature for existing build system by just adding aot=driver to the command line. That made the integration into an existing downstream build infrastructure very very simple, so I think the solution in this PR as well as the potential to do custom drivers together with changes in this PR adds a powerful mechanism to the overall AOT compiler chain and in the LLVM case, saves a lot of memory. |
c9b7006
to
2a2bff9
Compare
Draft Pull Request was automatically closed for 30 days of inactivity. Please let us know if you'd like to reopen it. |
@vargaz what do you think on getting this in? I've been running it downstream for quite some time and it has big impact on the parallelization on the machines since we consume half RAM per compiled assembly when running LLVM. Its also disabled by default and needs to be explicitly enabled and it opens up for alternative driver implementations in other front ends as well. |
I'm trying to make a version which doesn't use pipes, but executes the 'compile code' phase in a child. |
That implementation can use a file instead of pipes as well, just pass in a path to a file and that will be used for the commands. That was the original implementation, I then extended with possibility to use stdout as an alternative. |
Draft Pull Request was automatically closed for 30 days of inactivity. Please let us know if you'd like to reopen it. |
Running Mono AOT cross compiler will keep the process alive while running external tools like opt and llc. When building a large assembly using LLVM the memory footprint of Mono AOT cross compiler can fall in the gigabytes and then running LLVM tools like opt and llc as child processes tends to take up additional memory in the gigabyte space for large assemblies meaning that the total memory needed to compile one large assembly will be max Mono AOT cross compiler memory usage + (opt|llc) memory usage, meaning that it can consume gigabytes of memory. Adding parallel compiles into the mix means machine memory will drain pretty fast.
This PR adds a "driver" mode to AOT compiler. Its integrated into the execute system command infrastructure of the Mono AOT cross compiler, meaning that a Mono AOT compiler process doing the compile work will write the exact commands (opt, llc, clang, ld etc) that it would have executed into a file or stdout and the AOT compiler instance acting as the driver will record them and execute them once the original child process exited (and released all its memory). Doing it like this won't keep memory around and the Mono AOT cross compiler instance acting as the "driver" will only consume a couple of MB's of memory. The benefit of recording the commands into a file/stdout will make sure we are always up to date with the correct set of arguments for each command and it is even possible to write a custom driver and it will be able to run the exact same commands as the AOT cross compiler would have done when not executed as a driver child process.
By default, driver mode in Mono AOT cross compiler is disabled. To enable it add aot=driver argument to the list of all arguments passed to Mono AOT cross compiler. That will run a different instance of the Mono AOT cross compiler with the same set of arguments, but adding aot=driver-logfile=stdout that makes sure child process runs the compile of the assembly, but record selected executed commands into the supplied file, by default that is stdout to only communicate between the pipe setup between parent and child process. Once all commands have been recorded and the child process terminates, the driver instance will execute each command in sequence (after doing validation of the binary used in each command).
Here is an example of how the child process of a driver instance logs into stdout:
so each of the [XX_COMMAND] are just logged into stdout by child process as it would have been executed, driver parent process reads stdout and extract commands into a command log, the rest is written to its stdout making sure all the output (except the commands) are still visible to the user. It will then execute the list of commands in sequence as recorded by the child process after the child process has terminated and the system has been able to reclaim its memory.
Since the driver currently don't support the unlink, rename and rm commands used by AOT compiler in some scenarios, it currently only works with the outfile || llvm_outfile and temp_path aot options. It is simple to add them in the driver, but in the use case where the complete driver option was implemented didn't have the need since things where always executed with outfile and temp_path. The same applies to assemblies compiled through the MonoAOTCompiler msbuild task.