The main extension point for MSBuild is through the use of a Task.
A common problem with using a Task is that after the first use the assembly containing the task is locked. This locking also applies to all assemblies the Task references. The lock is not released until Visual Studio closes.
Luckily there is an alternative to Task that does not lock files: AppDomainIsolatedTask.
With AppDomainIsolatedTask every time the task is run it executes within a new AppDomain. When the task finishes that AppDomain is released and all file locks are also released.
AppDomainIsolatedTask is frequently recommended as a solution to the file locking nature of Task. For example:
However the performance implications of using AppDomainIsolatedTask are rarely included in these recommendations.
When using a new AppDomain for every task execution .net is not able to make use of loaded assemblies. This results in assemblies needing to be re-loaded at each task execution.
To put the performance impact into perspective I ran up a little test. I built a custom task which did the following things
- JSON manipulation using Json.net
- Constructed a MEF CompositionContainer
- Constructed a NLog Logger
- Inspected the assembly using Mono Cecil
I then built up a solution with 10 projects. Each one called the custom task in the AfterCompile node.
For a full re-build the results were as follows
- Approximately 1 second when inheriting from Task
- Approximately 5 seconds when inheriting from AppDomainIsolatedTask
(Note: this is on a Quad Core 2.67GHz i7, 6GB Ram, SSD HD)
This performance impact of AppDomainIsolatedTask will increase with two factors
- The more projects using the task
- The more (size of) assemblies that are used by that task
Now I am not saying "Dont use AppDomainIsolatedTask" but rather "Consider the performance implication of AppDomainIsolatedTask".
There may be many sceneries where the benefits of AppDomainIsolatedTask overrule the performance impact.
No new comments are allowed on this post.