0

そのため、アプリケーションの期間中、コンテナがDerivedTypeConstructorSelectorPolicyのインスタンスを保持しているという問題が発生しています。TypeInterceptionStrategyの次の2行のコードが古いポリシーを新しいポリシーにラップし、それが2つのインスタンス(またはそれ以上、インターセプトされたクラスのResolveへのすべての呼び出し)を保持するという事実がなければ、これはそれほど悪くはありません。問題を悪化させます)。これは、.NETメモリプロファイラーを実行しているときに確認できます。

IConstructorSelectorPolicy originalConstructorSelectorPolicy = PolicyListExtensions.Get<IConstructorSelectorPolicy>(context.Policies, (object) context.BuildKey, out containingPolicyList);
PolicyListExtensions.Set<IConstructorSelectorPolicy>(containingPolicyList, (IConstructorSelectorPolicy) new TypeInterceptionStrategy.DerivedTypeConstructorSelectorPolicy(proxyType, originalConstructorSelectorPolicy), (object) context.BuildKey);

これにより、多くのクラスがインターセプトされ、GCが再利用できないメモリの穴が発生した場合、特にスレッドセーフを確保するためにポリシーがコピーされると、Gen2コレクションのスラッシングが発生します。ポリシーリストに十分な数のアイテムが含まれると、LOHに移動され、スラッシングがさらに悪化します。

アプリケーションが統合パイプラインではなくIISクラシックで実行されており、32ビットモードで実行されているという事実に注意する必要があります。64ビットモードでアドレス指定可能なスペースが増えれば、これはそれほど悪くはありません。しかし、それでも、IISから提供された仮想メモリにとらわれており、GCがVMマップで追加のメモリを割り当てるのに十分なスペースを見つけることができず、要求が停止し始めるため、これはすぐに進行します。

ファイルには3つのリビジョンしかなく、元のリビジョンにはこの問題がなかったように見えます。他の誰かがこの問題に遭遇したことがありますか、または私はおそらくこの動作を説明する何かを見逃していますか?

これを説明する非常に単純なプログラムへのリンクは、pastebinに投稿されています:http://pastebin.com/DYG3GXNm

.NETメモリプロファイラー(または選択したプロファイラー)を使用してDerivedTypeConstructorSelectorPolicyを監視すると、反復ごとに成長するのを監視でき、成長するにつれて、originalConstructorSelectorPolicyが長いチェーンで古いインスタンスを参照し続けることを確認できます。

インターセプトするクラスの数の例として、登録数は約1300程度です。

4

1 に答える 1

1

その間に解決策を見つけました。これは簡単な修正ですが、InterceptionとTypeInterceptionStrategyをオーバーライドする必要があります。修正は、ポリシーリストから出てくるタイプを確認するだけのワンライナーでした。

これはTypeInterceptionStrategyからのコードです:

if (originalConstructorSelectorPolicy is DefaultUnityConstructorSelectorPolicy)
{
    containingPolicyList.Set<IConstructorSelectorPolicy>(new CustomDerivedTypeConstructorSelectorPolicy(proxyType, originalConstructorSelectorPolicy), context.BuildKey);
}

もちろん、これを変更するには、TypeInterceptionStrategyをコピーして、その修正だけで同じことを行う必要があります。PreBuildUpメソッドをオーバーライドするだけで修正することはできません。

他の人が問題に遭遇した場合に備えて、修正全体をここに貼り付けています。

public class CustomTypeInterceptionStrategy : BuilderStrategy
{
    public override void PreBuildUp(IBuilderContext context)
    {
        Guard.ArgumentNotNull(context, "context");

        if (context.Existing != null)
        {
            return;
        }

        Type type = context.BuildKey.Type;
        ITypeInterceptionPolicy typePolicy = FindInterceptionPolicy<ITypeInterceptionPolicy>(context);

        if (typePolicy == null)
        {
            return;
        }

        ITypeInterceptor interceptor = typePolicy.GetInterceptor(context);

        if (!interceptor.CanIntercept(type))
        {
            return;
        }

        IInterceptionBehaviorsPolicy behaviorPolicy = FindInterceptionPolicy<IInterceptionBehaviorsPolicy>(context);

        IEnumerable<IInterceptionBehavior> interceptionBehaviors = behaviorPolicy == null
                                                                       ? Enumerable.Empty<IInterceptionBehavior>()
                                                                       : behaviorPolicy.GetEffectiveBehaviors(context, interceptor, type, type).Where(ib => ib.WillExecute);

        IAdditionalInterfacesPolicy interceptionPolicy3 = FindInterceptionPolicy<IAdditionalInterfacesPolicy>(context);
        IEnumerable<Type> additionalInterfaces1 = interceptionPolicy3 != null ? interceptionPolicy3.AdditionalInterfaces : Type.EmptyTypes;
        context.Policies.Set(new CustomEffectiveInterceptionBehaviorsPolicy() { Behaviors = interceptionBehaviors }, context.BuildKey);

        Type[] additionalInterfaces2 = Intercept.GetAllAdditionalInterfaces(interceptionBehaviors, additionalInterfaces1);
        Type proxyType = interceptor.CreateProxyType(type, additionalInterfaces2);

        IPolicyList containingPolicyList;
        IConstructorSelectorPolicy originalConstructorSelectorPolicy = context.Policies.Get<IConstructorSelectorPolicy>(context.BuildKey, out containingPolicyList);

        if (originalConstructorSelectorPolicy is DefaultUnityConstructorSelectorPolicy)
        {
            containingPolicyList.Set<IConstructorSelectorPolicy>(new CustomDerivedTypeConstructorSelectorPolicy(proxyType, originalConstructorSelectorPolicy), context.BuildKey);
        }
    }

    public override void PostBuildUp(IBuilderContext context)
    {
        Guard.ArgumentNotNull(context, "context");

        IInterceptingProxy interceptingProxy = context.Existing as IInterceptingProxy;

        if (interceptingProxy == null)
        {
            return;
        }

        CustomEffectiveInterceptionBehaviorsPolicy interceptionBehaviorsPolicy = context.Policies.Get<CustomEffectiveInterceptionBehaviorsPolicy>(context.BuildKey, true);

        if (interceptionBehaviorsPolicy == null)
        {
            return;
        }

        foreach (IInterceptionBehavior interceptor in interceptionBehaviorsPolicy.Behaviors)
        {
            interceptingProxy.AddInterceptionBehavior(interceptor);
        }
    }

    private static TPolicy FindInterceptionPolicy<TPolicy>(IBuilderContext context) where TPolicy : class, IBuilderPolicy
    {
        TPolicy policy = context.Policies.Get<TPolicy>(context.BuildKey, false);

        if (policy != null)
        {
            return policy;
        }

        return context.Policies.Get<TPolicy>(context.BuildKey.Type, false);
    }

    private class CustomEffectiveInterceptionBehaviorsPolicy : IBuilderPolicy
    {
        public CustomEffectiveInterceptionBehaviorsPolicy()
        {
            this.Behaviors = new List<IInterceptionBehavior>();
        }

        public IEnumerable<IInterceptionBehavior> Behaviors { get; set; }
    }

    private class CustomDerivedTypeConstructorSelectorPolicy : IConstructorSelectorPolicy
    {
        private readonly Type interceptingType;
        private readonly IConstructorSelectorPolicy originalConstructorSelectorPolicy;

        public CustomDerivedTypeConstructorSelectorPolicy(Type interceptingType, IConstructorSelectorPolicy originalConstructorSelectorPolicy)
        {
            this.interceptingType = interceptingType;
            this.originalConstructorSelectorPolicy = originalConstructorSelectorPolicy;
        }

        public SelectedConstructor SelectConstructor(IBuilderContext context, IPolicyList resolverPolicyDestination)
        {
            return FindNewConstructor(this.originalConstructorSelectorPolicy.SelectConstructor(context, resolverPolicyDestination), this.interceptingType);
        }

        private static SelectedConstructor FindNewConstructor(SelectedConstructor originalConstructor, Type interceptingType)
        {
            ParameterInfo[] parameters = originalConstructor.Constructor.GetParameters();
            SelectedConstructor selectedConstructor = new SelectedConstructor(interceptingType.GetConstructor(parameters.Select(pi => pi.ParameterType).ToArray()));

            foreach (string newKey in originalConstructor.GetParameterKeys())
            {
                selectedConstructor.AddParameterKey(newKey);
            }

            return selectedConstructor;
        }
    }
}

public class CustomInterception : Interception
{
    protected override void Initialize()
    {
        this.Context.Strategies.AddNew<InstanceInterceptionStrategy>(UnityBuildStage.Setup);
        this.Context.Strategies.AddNew<CustomTypeInterceptionStrategy>(UnityBuildStage.PreCreation);
        this.Context.Container.RegisterInstance(typeof(AttributeDrivenPolicy).AssemblyQualifiedName, (InjectionPolicy)new AttributeDrivenPolicy());
    }
}
于 2012-12-05T20:16:55.603 に答える