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

Fix #948 make component registry immutable #981

Conversation

weelink
Copy link
Contributor

@weelink weelink commented Apr 11, 2019

Make IComponentRegsitry immutable by moving all mutable actions to IComponentRegistryBuilder.

@weelink
Copy link
Contributor Author

weelink commented Apr 11, 2019

If this PR is going to be approved, I'll update the documentation as well.

Notes

I have assumed that this PR will be merged into a version where IContainerBuilder.Update will no longer be needed (#811)

  • Moved all mutable methods to IComponentRegistryBuilder.
  • CopyOnWriterRegistry is not necessary anymore. It only did something when the IComponentRegistry of a lifetime scope is modified. Since this PR disallows it, it has been removed.
  • IComponentRegistry.RegistrationsFor is quering the registration sourced, that may add new registrations to the existing component registry, making this not a pure immutable registry. That is why I added a IRegisteredServicesTracker to share the registrations in the builder and the registrations from registration sources.

@tillig
Copy link
Member

tillig commented Apr 11, 2019

Thanks for this! It will take a while to get through since a lot has changed, and it'll also require some time to think through all the use cases. I'm excited to dive in and see how you solved one of the larger challenges on the backlog. I'd like to make sure @alexmg has a chance to check it out, too, before any final decision gets made.

Just to set up expectations that it probably won't happen, like, tomorrow or something. Appreciated, not forgotten, just not immediate. Yay for "real life" work taking over, right? ;)

@tillig
Copy link
Member

tillig commented May 16, 2019

I haven't forgotten! I've pulled the PR down to my local machine and I'm looking at it now. For the most part, I dig it. I'm trying to mess around with the changes from a consumer perspective and see what's different, running the benchmarks to see how perf is affected, if at all.

That's actually where I've gotten stuck. The ConcurrencyBenchmark effectively never finishes for me. That's not a problem in this branch, the same thing happens on the develop branch for me. I think it's hammering through the "1,000 tasks each trying to concurrently resolve 10,000 object graphs" that it's going. There's not any visual feedback on the execution progress so it's hard to say, but I do see my RAM get pegged and I see the Autofac.Benchmarks.ConcurrencyBenchmark log gets created and sits at 0 bytes.

I'll have to work through that so I can see what the changes mean as far as performance. It may require some additional benchmarks to exercise areas like lifetime scope creation and resolution from scopes. Most of the benchmarks currently resolve directly from a container, which is good to exercise certain subsystems (like decorators) but it doesn't give us insight into more hierarchical systems that are more real-world.

Not to say that's a task for this PR, just keeping things up to date. If I update the benchmarks in the develop branch, I may do a pull from that branch into this PR to keep things apples-to-apples. That'd also resolve some of the recent merge conflicts due to me moving things around in the unit tests. :)

@weelink
Copy link
Contributor Author

weelink commented May 22, 2019

Sure, no problem. I'll just check in once in a while.

@tillig
Copy link
Member

tillig commented May 24, 2019

OK, here's what I did:

  • Pulled this PR into a pr-immutable-container branch.
  • Merged the latest develop changes into that branch.
  • Pushed that branch to the main repo.

What this effectively does is "take the PR" but allow us to test some things like adding more benchmarks without holding this up or leaving it open forever. It also lets us target it for a 5.0 release and plan around when it should be brought into develop without holding up any minor changes that need to happen first. Likely this will end up being the "breaking changes for 5.0" branch. ;)

This is definitely one of the largest and most sweeping changes I've seen come in a PR, and I can't overstate how much I appreciate the work that happened here. I like what I see and I think if anything needs to change we can do whatever minor massaging needs to happen right in the branch.

So... thanks! 🎉

@tillig tillig closed this May 24, 2019
/// <summary>
/// Protects instance variables from concurrent access.
/// </summary>
private readonly object _synchRoot = new object();
Copy link
Member

Choose a reason for hiding this comment

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

Really amazing, first-class PR :-) !!! 👏 🎉

Just one (late) question - does this class need synchronization now? The only times registry builders are mutated are during initial container build-up (required to be single-threaded) and during scope creation (also single-threaded).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you :-).
Now that I look at this again, I think you are right and this can be removed. I don't remember why I left it in, or if I actually had a reason to leave it in.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for the reply! @alexmg @tillig I'll PR some changes through around this and Properties if it sounds sane to you both :-)

Copy link
Member

Choose a reason for hiding this comment

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

Sounds great! This is all in the pr-immutable-container branch. I still haven't had a chance to really dig in due to some personal stuff coming up unexpectedly.

/// An <see cref="IDictionary{TKey, TValue}"/> that can be used to share
/// context across registrations.
/// </value>
public IDictionary<string, object> Properties { get; }
Copy link
Member

Choose a reason for hiding this comment

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

For example, regarding synchronization, Properties here will allow the underlying Dictionary<,> to be accessed outside the _syncRoot lock, which is potentially non-threadsafe.

(I'm happy to attempt a PR for these things but just thought I should confirm my understanding first.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is true. I kept this as it is now. This is something that could be improved.

@alexmg
Copy link
Member

alexmg commented May 29, 2019

Great PR @weelink. Thanks for taking the time to put this together.

I have a branch with changes to get the Service being resolved into the resolution pipeline. This is also a breaking change so I have put it off for a while. I'm wondering if we should create a v5.0 branch and start merging breaking changes into that from various feature branches such as this.

@nblumhardt
Copy link
Member

Would be a nice target for the Properties changes I am mulling over 👍

Is there a plan to introduce new optimisations now that component registries are immutable? (Intrigued where all this is going to land - lots of possibilities :-))

@weelink weelink deleted the feature/948_MakeComponentRegistryImmutable branch November 12, 2019 08:57
@alexmg
Copy link
Member

alexmg commented Dec 21, 2019

@weelink I just wanted to let you know this has now been incorporated into the develop branch. Thanks again for the awesome PR. We really appreciate the effort you put into this.

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.

4 participants