-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Collectible Assemblies and the CLR #4075
Comments
Thank you for starting the conversation. We have been mulling over this feature request for a while.System.Runtime.Loader.AssemblyLoadContext - .NET Core replacement for AppDomain.AssemblyResolve event - was designed with collectability in mind. Our tentative plan has been to expose it by adding a new constructor to this type that takes an extra flag to mark the context as collectible. That is the easy part. The hard part is the runtime implementation of the collectability. It should build upon the existing Reflection.Emit collectability infrastructure (look for FEATURE_COLLECTIBLE_TYPES). The implementation needs to include targeted tests for corner cases as well as stress testing the unloading (e.g. run all existing corefx tests as unloadable in a loop for a long time, etc.) In case somebody would like to start the implementation before the core team gets to it, it should be done in series of smaller commits under FEATURE_XXX define (e.g. FEATURE_COLLECTIBLE) that will be turned off by default until the implementation is completed. The first baby steps may be to add the extra argument to the AssemblyLoadContext constructor under this define. |
+1! 😄 Would love this for razor compilation and other things |
I'd love to work on this! |
Start with the "easy" constructor changes and feel free to ask questions about the rest. :-) |
Would this behave like AppDomains where all loaded assemblies are collected with the context or does the context just mark assemblies loaded through it as collectible? After looking through the code it looks like it would be per assembly since the CLR already supports that. So AssemblyLoadContext would need a new constructor that lets you specify whether it loads assemblies as collectible. It looks like that flag would need to make it down to Assembly::Create which has a parameter to mark assemblies as collectible. A LoaderAllocater is required for collectible assemblies as well. Assembly::CreateDynamic uses AssemblyLoaderAllocator which is probably what should be used, assuming per assembly collection I guess. Is this correct? I'm not really sure how I would get that information from AssemblyLoadContext all the way to Assembly::Create, or if I even need to. |
All assemblies loaded into given collectible AssemblyLoadContext should be unloaded as a unit.
The owning AssemblyLoadContext can be retrieved in Assembly::Create from PEAssembly argument using |
Also how would I safely cast the |
Yes, creating interface would be a clean way to do this. |
So I made an interface and changed
Here's what I have for my interface right now: class DECLSPEC_UUID("68220E65-3D3F-42E2-BAD6-2D07419DAB5E") IAssemblyLoadContext : public IUnknown
{
public:
STDMETHOD(GetIsCollectible)(
/* [retval][out] */ BOOL *pIsCollectible) = 0;
}; Also is there any reason why |
How many places have this problem? You should be able to fix them by casting to the specific interface.
I do not see a particularly strong reason. It should be ok to change it to public. |
It's just one place but there is no interface for that method, even though it looks like there should be one. I changed it to a reinterpret_cast to get it to build but I doubt that would work properly at runtime. |
OK so I have it using the IsCollectible flag and LoaderAllocator I added to CLRPrivBinderAssemblyLoadContext in I'm basing this off of what |
Is this going to make RC2? |
No, which is why we moved it into the Future milestone. |
So if it's in the Future milestone is it effectively dead? A 'Future' sprint is usually where most tasks go to die and be forgotten |
@runxc1 That's not the intent. 'Future' is the equivalent of our backlog. The other milestones are tracking the upcoming RC and RTM versions early this year. Impactful features like this don't make the bar for V1. |
@terrajobst any info on this since fabruary and a successful release of 1.0.0? ;-) |
Will collectible assemblies be part of the 1.2... or it is more reasonable it will not? |
That would be very nice if this made it into 2.0 |
For folks following this feature, I have been working to bring back this feature with the PR dotnet/coreclr#8677 on coreclr and the PR 14763 on corefx. The current status is that it seems that the implementation is working well so far but requires a bit more stress tests to verify that we have something rock solid. |
As I have understood, this feature allows, selectively, unload an assembly within a context, leaving the rest of the assemblies loaded. This is very powerful, but would it be possible to also implement the option to unload the full context, just like it can be done with the AppDomain?. This might accelerate the delivery of this feature. |
What is the status of this feature? Is it yet available? Will it be available only for dynamic assemblies or also for static assemblies? |
Any further update on this - or is the only work around to terminate the process and wait for daemon / service / iis to restart in order to clear the context? |
@dandcg As jkotas stated here the functionality of unload assemblies will not be done with 2.1! But they will talk again about this topic when they make a new roadmap for 2.2 e.g. |
Seems the roadmap for 2.2 stands and 3.0 was announced as well some time ago, was there a discussion about this topic and can you share your plans? Could it be part of 3.0? |
Yes, this is planned to be in 3.0. |
@jkotas Awesome! So... when's that coming out? 😛 |
(...which is terrifyingly soon, I just realized...) |
The remaining work is tracked by https://github.com/dotnet/coreclr/projects/9 |
@joktas Can't get keep this issue open until the feature is completed? It's much easier to be subscribed to one "overall" issue than several small individual issues in a project board. |
It is in the nightly builds and it should be generally working. The remaining work is a lot of extra testing and bug fixes. If you were waiting for this feature, it is time to start giving us feedback - please give it a try and open issues on any problems you are running into. |
I read the whole post and I'm wondering how I could use this feature (and if I understood it correctly). From what I understood, this issue concerns the unloading of assemblies. For example, I load an assembly (that I generated on-the-fly using Roslyn) like this:
How could I unload only this assembly from the context? From what I saw, the "Unload" method on "AssemblyLoadContext.Default" can be used to unload the whole context, but not a particular assembly, so how could this be used? |
@ssougnez You can create additional |
@Rohansi Is there a performance penalty when making calls that are in different contexts? The option that you propose seems viable if the option does not have performance penalties. |
@Suriman Compared to using AppDomains like you would in .NET Framework, no, I wouldn't say there's a performance penalty. There's no There should be a few small differences for collectible assemblies though. Inlining code between two contexts should not be possible but you would probably be using an interface or reflection to call these methods. Those can't be inlined anyway so it's not a new problem. I believe thread locals might be a bit slower in collectible assemblies but I can't find a source for this. I remember seeing something about that in a thread here. |
Do you have an idea on how to write
I wrote something for this but I load all assemblies in memory as LoadEngine but I want to use this new feature for this. |
@HamedFathi the unloadability should work for your case. You can take a look at the sample at https://github.com/dotnet/samples/tree/master/core/tutorials/Unloading and howto document on unloadability at https://docs.microsoft.com/en-us/dotnet/standard/assembly/unloadability-howto. |
Hi there,
I would like to start the conversation about collectible assemblies and the CLR. For reference the user voice for this issue is available here. My understanding is that this is currently possible with Mono, but not the CLR.
With the new Roslyn compiler and projects like ScriptCS, I think we're going to see an increase in the number of users who are dynamically compiling and running code. Today there is no way to unload an assembly (without burning down the entire AppDomain 😄).
I'd love to get a feel for what limitations exist that would prevent this feature, how much work it might take and whether or not the team felt it was feasible (or necessary).
The text was updated successfully, but these errors were encountered: