Proposal to Expand the TemplateEngine / CLI Interface
See original GitHub issueMotivation
The primary motivation for this proposal is to eliminate unnecessary process creation overhead when communicating from the template engine back to the SDK. Not only does this allow for reduction in additional “chaining” processes when performing actions in the SDK, but this also allows us to remove the managed overhead (JIT, R2R initialization, etc.) associated with these additional processes.
The most immediate use of this proposal would be to eliminate extra processes required to restore new templates during DotNetRestorePostActionProcessor.Process
.
Current State
As it stands today, there is communication between the template engine and the CLI in both directions.
SDK --> Template Engine: This works by allowing the SDK to pass arguments to the template engine as part of the template engine entrypoint - New3Command.Run
.
public static int Run(string commandName, ITemplateEngineHost host, ITelemetryLogger telemetryLogger, Action<IEngineEnvironmentSettings, IInstaller> onFirstRun, string[] args, string hivePath)
Template Engine --> SDK: The template engine can communicate with the SDK in two ways today. The first is by invoking delegate arguments that were passed to the template engine from the SDK when calling New3Command.Run
. A good example here is the onFirstRun
delegate which implements what the SDK would like done when the template engine determines that it is being run for the first time. The second mechanism is by allowing the template engine to invoke dotnet.exe directly which spawns a new SDK process and allows the template engine to ask the SDK to perform operations on behalf of the template engine. An example of where this is used is in DotNetRestorePostActionProcessor.Process
, which invokes dotnet.exe directly to call dotnet restore
on the newly instantiated template.
Proposal
I would like to propose that we expand on the mechanisms that the template engine has to communicate with the SDK by allowing for more delegates to be implemented by the SDK, such that the template engine no longer has to call dotnet.exe in order to ask the SDK to perform actions on its behalf. For the most part, the extra process creation should be unnecessary, and materially increases the time required to complete the action. This comes from both the cost of spawning the new process, as well as new managed process overhead, such as JIT and R2R initialization time.
Strawman Code Pattern
Rather than passing individual delegates, I propose replacing the onFirstRun
argument with a callbacks argument of type DotNetNew3Callbacks
that lives in the template engine codebase (today the SDK depends on the template engine, not the other way around):
public sealed class DotNetNew3Callbacks
{
public Action<IEngineEnvironmentSettings, IInstaller> OnFirstRun { get; set; }
}
From here, we can add a new callback whenever one is needed. The workflow for adding a new callback is the following:
- Add the new callback to
DotNetNew3Callbacks
, and optionally allow its use in the template engine, as long as the template engine can handle if the callback isnull
(it will be null until step 3). - Merge the new callback and wait for the change to propagate to the SDK repo.
- Implement the callback in the SDK.
- If necessary, change the usage of the delegate in the template engine now that the SDK implements the delegate unconditionally (step 3).
First Proposed Usage
The first proposed usage of this mechanism is to replace the call to dotnet restore
that is made in DotNetRestorePostActionProcessor.Process
to avoid the extra process overhead.
public sealed class DotNetNew3Callbacks
{
public Action<IEngineEnvironmentSettings, IInstaller> OnFirstRun { get; set; }
// string argument: Path to restore
public Action<string> RestoreProject { get; set; }
}
RestoreProject
will be called by DotNetRestorePostActionProcessor.Process
instead of calling Dotnet.Restore(pathToRestore)
at https://github.com/dotnet/templating/blob/master/src/Microsoft.TemplateEngine.Cli/PostActionProcessors/DotnetRestorePostActionProcessor.cs#L78.
Issue Analytics
- State:
- Created 3 years ago
- Comments:12 (11 by maintainers)
Top GitHub Comments
We want to be very careful about changing the onFirstRun mechanism. The template engine interfaces are used by more than just dotnet new. Visual Studio and and Visual Studio for Mac both use these interfaces, from multiple entry points, by multiple teams.
The new mechanism should be implemented on a separate or updated interface which could be opted into by the new command so that we could maintain compatibility across the other consumers of the API, especially considering that the IDEs would get very little benefit from this update since they don’t invoke restore at project creation, but instead via solution build.
Edit: I just realized as long as we only update the signature in the New3Command and not in the. Microsoft.TemplateEngine.IDE we should be fine here, so the above does not really apply in this case. We should keep the other consumers in mind though for any other proposed API signature changes.
@donJoseLuis, @dsplaisted I’d like to get your feedback on this. cc: @DamianEdwards, @davidfowl, @KathleenDollard
Note: Right now, in order to restore a newly instantiated template, there are 3 processes involved:
dotnet new <template>
: The user typed this.dotnet restore new-project.csproj
: Started by process 1 because there isn’t currently a clean way to call back into the SDK to do the restore. This proposal would allow for elimination of this process.dotnet exec MSBuild.dll
: This is invoked by process 2. A separate effort is required to eliminate this process.