Skip to content
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

DYN-7691: Add assembly load contexts to packages #15424

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open

Conversation

pinzart90
Copy link
Contributor

@pinzart90 pinzart90 commented Aug 12, 2024

Purpose

https://jira.autodesk.com/browse/DYN-7691

Add assemblyLoadCOntexts for all packages loaded in Dynamo
Use feature flags
Did not do dynamic unload - still not clear how to make it work for packages

Declarations

Check these if you believe they are true

  • The codebase is in a better state after this PR
  • Is documented according to the standards
  • The level of testing this PR includes is appropriate
  • User facing strings, if any, are extracted into *.resx files
  • All tests pass using the self-service CI.
  • Snapshot of UI changes, if any.
  • Changes to the API follow Semantic Versioning and are documented in the API Changes document.
  • This PR modifies some build requirements and the readme is updated
  • This PR contains no files larger than 50 MB

Release Notes

Enable assembly isolation for packages.

Reviewers

(FILL ME IN) Reviewer 1 (If possible, assign the Reviewer for the PR)

(FILL ME IN, optional) Any additional notes to reviewers or testers.

FYIs

(FILL ME IN, Optional) Names of anyone else you wish to be notified of

@pinzart90 pinzart90 changed the title add assembly load contexts to packages [WIP] add assembly load contexts to packages Aug 12, 2024
@pinzart90
Copy link
Contributor Author

Unload is still not working as expected (after the unloading event kicks in, the package assemblies still cannot be deleted...)
Still looking into a couple of things

@pinzart90
Copy link
Contributor Author

Will probably need to filter out packages that implemented isolation on their own

AssemblyLoadContext pkgLoadContext = AssemblyLoadContext.Default;

bool isolateAnyPackage = DynamoModel.FeatureFlags?.CheckFeatureFlag("IsolateAnyPackage", false) ?? false;
bool isolateThisPackage = DynamoModel.FeatureFlags?.CheckFeatureFlag("IsolatePackage_" + package.Name, false) ?? false;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should check per version ?
probably would be helpful for IronPython which already has isolation. The current version should not be isolated by Dynamo probably...but all other could be...

Copy link

github-actions bot commented Aug 12, 2024

UI Smoke Tests

Test: success. 11 passed, 0 failed.
TestComplete Test Result
Workflow Run: UI Smoke Tests
Check: UI Smoke Tests

}
else if (package.Header.node_libraries.Any())
{
string entryPoint = new AssemblyName(package.Header.node_libraries.First()).Name + ".dll";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there could be more than one node_library right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try the root package location first...then I'll circle back to this if needed

@mjkkirschner
Copy link
Member

I think if we were going to just turn this using feature flags, there would be value in somehow collecting some analytics though I'm not sure how we can prove a package "works" after being loaded this way without asking people since our testing system for package is non existent.

@pinzart90
Copy link
Contributor Author

I think if we were going to just turn this using feature flags, there would be value in somehow collecting some analytics though I'm not sure how we can prove a package "works" after being loaded this way without asking people since our testing system for package is non existent.

I could write a test, that downloads each package at a time and loads it in isolation. It would take a long time...so should be a nightly thing...
I thing I have some of that code already from the email notification work

@pinzart90 pinzart90 changed the title [WIP] add assembly load contexts to packages Add assembly load contexts to packages Oct 25, 2024
@@ -2218,7 +2219,7 @@ private void AddDllFile(string filename)
{
// we're not sure if this is a managed assembly or not
// we try to load it, if it fails - we add it as an additional file
var result = PackageLoader.TryLoadFrom(filename, out Assembly assem);
var result = PackageLoader.TryLoadFrom(AssemblyLoadContext.Default, filename, out Assembly assem);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this needs to be isolated or not.

Copy link
Member

@mjkkirschner mjkkirschner Oct 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

umm, certainly seems so? I guess this should use an MLC to determine what type of binary it is before loading it into the real ALC for this package?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh - this is just for publishing, I mean, I still think what I stated is the way to go, but maybe less important.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might add a new task for this

@github-actions github-actions bot changed the title Add assembly load contexts to packages DYN-7691: Add assembly load contexts to packages Oct 30, 2024
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the ticket for this pull request: https://jira.autodesk.com/browse/DYN-7691

Comment on lines 49 to 59
string pkgs = DynamoModel.FeatureFlags?.CheckFeatureFlag("IsolatePackages", string.Empty);
if (!string.IsNullOrEmpty(pkgs))
{
foreach (var x in pkgs.Split(","))
{
packagesToIsolate.Add(x);
}
}


pkgs = DynamoModel.FeatureFlags?.CheckFeatureFlag("DoNotIsolatePackages", string.Empty);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Who specifies which packages should be isolated and which shouldn't? If we do, how do we decide that? Is this meant for only the packages that are owned by us? If not, how would this be scalable? Am I right in assuming that in the long run, we'll be getting rid of these feature flags to load all packages in isolation by default (except for the ones that already use ALCs, i.e. if there is a way for us to know that ahead of time)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I foresee that some packages might have issues with being loaded in isolation (maybe the interaction between the isolated types vs the ones in the main load context).
So the main reason for adding feature flags is to slowly roll it out for all packages and have the option to disable it for a select few(like the ones that are already isolated on the package side )

As for “how do we decide which ones to isolate”:
I was thinking to take a couple at a time from the list I used to notify package maintainers about the dotnet8 migration.

}

// Useful for mocking in tests
internal IFFlags flags { get; set; } = new FFlags();
Copy link
Contributor Author

@pinzart90 pinzart90 Nov 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may have tunnel vision, but I could not think of anything else to easily enable mocking.
I seem to need mocking because I am using the CheckFeatureFlag function in the PackageLoader

I tried to avoid refactoring the entire DynamoFeatureFlagsManager to be mockable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mjkkirschner any other options that you see?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The feature flags cli already returns a set of static test flags in test mode - is that sufficient?

{
// with testmode = true, the call goes through an interface so that we can intercept it with Mock
// with testmode = false, the call simply goes to the CheckFeatureFlagInternal
return testmode ? flags.CheckFeatureFlag(this, featureFlagKey, defaultval) : CheckFeatureFlagInternal(featureFlagKey, defaultval);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a performance thing I guess

@mjkkirschner
Copy link
Member

mjkkirschner commented Nov 7, 2024

I still think that control should be in the hands of users for opting out of isolated loading to avoid issues when something breaks for their local setup.

Feature flags do not seem sufficient for this purpose.

A simple config flag in prefs or config file could work.

@pinzart90
Copy link
Contributor Author

I still think that control should be in the hands of users for opting out of isolated loading to avoid issues when something breaks for their local setup.

Feature flags do not seem sufficient for this purpose.

A simple config flag in prefs or config file could work.

Preferences might be better know to dynamo users..

@@ -652,13 +652,21 @@ public void PlacingCustomNodeInstanceFromPackageRetainsCorrectPackageInfoState()
[Test]
public void LoadPackagesInAssemblyIsolation()
{
var ff = new Mock<DynamoUtilities.IFFlags>();
DynamoModel.FeatureFlags.flags = ff.Object;
Copy link
Contributor

@aparajit-pratap aparajit-pratap Nov 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make flags uppercase as per coding standards?

return null;
}

protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the fact that you can override this function mean that you can also load unmanaged assemblies in isolation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly no, you can only override the search algorithm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants