-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Refactor Props #5416
Refactor Props #5416
Conversation
@@ -38,7 +38,7 @@ public void Initialize(IDependencyResolver dependencyResolver) | |||
/// <returns>A <see cref="Akka.Actor.Props"/> configuration object for the given actor type.</returns> | |||
public Props Props(Type actorType) | |||
{ | |||
return new Props(typeof(DIActorProducer), new object[] { dependencyResolver, actorType }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this was the only place where the old DIActorProducer got with new object[] { dependencyResolver, actorType }
created, then we could remove the obsolete Props.CreateProducer
method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true. Can mark that API for deletion in 1.5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how do we mark deletion in version?
simply put some text in the obsolete attribute message?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct - just mention that in the ObsoleteAttribute
's text
if (producer is IIndirectActorProducerWithActorType p) | ||
return (producer, p.ActorType, NoArgs); | ||
|
||
//maybe throw new ArgumentException($"Unsupported legacy actor producer [{type.FullName}]", nameof(type)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here I am not sure, maybe to throw is better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's actually unsupported now, we should throw here.
@@ -689,92 +669,20 @@ public FactoryConsumer(Func<TActor> factory) | |||
_factory = factory; | |||
} | |||
|
|||
public ActorBase Produce() | |||
public ActorBase Produce(Props props) | |||
{ | |||
return _factory.Invoke(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe insert here a safety type check with props.Type
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To do what with it exactly? I don't recall what the FactoryConsumer
does anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FactoryConsumer
was not used, I reactivated it for the Producer by Custom-Functon
return CompareDeploy(other) && CompareSupervisorStrategy(other) && CompareArguments(other) && | ||
CompareInputType(other); | ||
return Type == other.Type | ||
&& _producer.GetType() == other._producer.GetType() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added here a simple producer type compare, there was no comparison on the producer before
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One other idea would be to let test if the producer implements IEqualityComparer<Akka.Props>
or maybe add a field for it into the producer interface.
All tests running successfully on my local machine. Is the build server just over committed or throttled and just slow? |
@Aaronontheweb Do we have any unit tests for the TestKit methods itself, that are checking the thread-id? I do not have currently an other idea. |
@Zetanova the test suite has become much more flakey since the .NET 6 upgrade due to the new "deadlock detection" algos that the managed thread pool uses. We're going to need to refactor all of it to be |
What exactly happens with the new "deadlock detection" ? The message is not pushed into the Queue of TestProp.
|
I'm not entirely sure, but the behavior of the |
Don't think that's, even with a new thread the message should be in the BlockingCollection in under 300ms. Would be most likely better to find and fix first the issue in the TestKit and then update the test methods to For |
Some tests failed only in "debug" test run, but not with a simple "run" test I found In the But the underlining problem is most likely that scheduled task just do not activated in time, |
@Aaronontheweb two failing tests are left, most likely it's just the racy akka-system startup or? |
@Aaronontheweb I added now a hack into the TestPrope.Create method This produces now errors local and a lot on the build-server, strange only in |
You have a lot of test failures now (77) - looks like one of your changes broke something in the logging system that the TestKit uses. |
I put a hack inside the commit to instantly await a log message and it is failing now Need to analyze why it is not support one some tests |
I removed now the testprope startup await hack, @Aaronontheweb if its ok for can be merged |
Finally looking at this now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly looks good, but have some changes that either need to be explained in more detail or removed
@@ -38,7 +38,7 @@ public void Initialize(IDependencyResolver dependencyResolver) | |||
/// <returns>A <see cref="Akka.Actor.Props"/> configuration object for the given actor type.</returns> | |||
public Props Props(Type actorType) | |||
{ | |||
return new Props(typeof(DIActorProducer), new object[] { dependencyResolver, actorType }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true. Can mark that API for deletion in 1.5
src/contrib/dependencyinjection/Akka.DependencyInjection/ServiceProvider.cs
Show resolved
Hide resolved
@@ -1072,10 +1072,14 @@ namespace Akka.Actor | |||
} | |||
public interface IIndirectActorProducer | |||
{ | |||
System.Type ActorType { get; } | |||
Akka.Actor.ActorBase Produce(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to check to see if there are any instances of plugins that call this - I don't think so but I want to double check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're good
@@ -689,92 +669,20 @@ public FactoryConsumer(Func<TActor> factory) | |||
_factory = factory; | |||
} | |||
|
|||
public ActorBase Produce() | |||
public ActorBase Produce(Props props) | |||
{ | |||
return _factory.Invoke(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To do what with it exactly? I don't recall what the FactoryConsumer
does anymore
@@ -32,12 +30,12 @@ namespace Akka.Actor | |||
/// </code> | |||
/// </example> | |||
/// </summary> | |||
public class Props : IEquatable<Props>, ISurrogated | |||
public sealed class Props : IEquatable<Props>, ISurrogated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how I feel about this, in terms of keeping this class open for extension. I checked the Phobos source to see if we subclass Props
anywhere there and we do not (we do subclass Deploy
, one of the sub-components of Props
) so if that doesn't need to extend Props
I can't imagine many other plugins that do...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that it has subclasses anywhere.
It's a miss design to use subclasses as decorators and/or to change the behavior.
Props
is a data/payload structure and the IIndirectActorProducer
should contain the behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - we're doing the 1.4.29 release today and I don't want to incorporate this change right away without having some further testing on subsequent PRs (I did the same thing with my PipeTo
changes between 1.4.28 and 1.4.29), but this will make it into 1.4.30
{ | ||
return actorFactory(); | ||
if (props.Type != _actorType) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to be more careful about inheritance checks here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is part of the deprecated DI library so I'm not as worried about it - but did we end up changing something here that we shouldn't have?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I insert here only a safty check the props.Type
and _actorType
should have the same type,
because it's only copy
{ | ||
var t = ((SendOrPostCallback, object, ActorCellKeepingSynchronizationContext, ActorCell))s; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm torn on this. I feel like once we multitarget netcore, this can be made better (because then, I think the boxing/unboxing can be elided here). But for now we are paying box/unbox penalty.
But as it stands, is it worth deconstructing the tuple immediately to help with reads?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only affects the TestKit
so I think we should be ok
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know what's faster here ValueTuple
or System.Tuple
, wanted only remove the scope.
It does not matter here, but when a scope is used with ThreadPool,
the context will not be GC until the action runs, it can lead to a self-reference in some scenarios.
var args = newExpression.GetArguments(); | ||
args = args.Length > 0 ? args : NoArgs; | ||
|
||
return new Props(new ActivatorProducer(typeof(TActor), args), DefaultDeploy, args){ SupervisorStrategy = supervisorStrategy }; | ||
return new Props(ActivatorProducer.Instance, DefaultDeploy, typeof(TActor), args) { SupervisorStrategy = supervisorStrategy }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're already getting the args, would there be any benefit in also sniffing out the Ctor in .GetArguments()
? (Can we even do that in a way that works OK with expectations of Props?)
That method was originally CopyPasta'd from OddJob, where we weren't newing up objects but rather were getting arguments for method calls. If you can actually hang on to what constructor is called (would be easy) there are opportunities to elide penalties involved with Activator.CreateInstance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you file an issue for this so we remember to do this as part of 1.5?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@to11mtm We could move the logic into a custom-actor-producer and use the instance for mass creation of the same actor type with the same or different props-instances,
everything else will always require runtime binding or dynamic-compile and use it only once
var args = newExpression.GetArguments(); | ||
args = args.Length > 0 ? args : NoArgs; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider, if you don't do the deed commented below about pulling ConstructorInfo:
var args = newExpression.Arguments > 0 ? newExpression.GetArguments() : NoArgs;
In the call chain for .GetArguments()
it looks like we might allocate an empty array if a 0-arg ctor is passed in. The suggestion will elide that allocation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good idea
{ | ||
|
||
Deploy = deploy; | ||
// have to preserve the "CreateProducer" call here to preserve backwards compat with Akka.DI.Core |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you. :)
) * remove the forced waiting on the underlying transport to start up * racy spec fix: `BackoffOnRestartSupervisor_must_respect_maxNrOfRetries_property_of_OneForOneStrategy` (#5442) issue was that using `AutoReset` could cause a race where if the scheduler could reset the count in-flight and throw off the estimates used by the tests. Using a `ManualReset` avoids this issue. * deleted commented out code * Make updates to `FishUntil` (#5433) * Make updates to `FishUntil` Implement nitpicks from #5430 * Nitpick * cleaned up `FishUntilMessage` * removed `FluentAssertions` reference * fixed bad `TestKit.ReceiveTests` * Custom frame size computation support in Framing (#5444) * Custom frame size computation support in Framing * Speed up of framing spec * optimize `Props` `NewExpression` allocations (#5428) per #5416 (comment) Co-authored-by: Ismael Hamed <1279846+ismaelhamed@users.noreply.github.com>
refactor of class Props to reduce view allocations, seal the class,
and adding the possibility to use the same
IIndirectActorProducer
for multiple Props instances.There is new an new obsolete
IIndirectActorProducerWithActorType
for legacy Akka.DI.Core,but I don't know the legacy DI well to know if there will be some binary combability issues.
Improvements for each props instance:
1x less object instance with min. 1 reference field (the producer instance)
1x less reference field (outtype field)
View less vcalls