3

Castle Windsor とインターセプターを使用すると、プログラムがメモリ不足になるという問題が発生しました。次のコードを使用して再現可能です。

public interface ITest{}
public class Test : ITest {}
class TestInterceptor:IInterceptor {
    public void Intercept(IInvocation invocation) {}
}
class Program {
    static void Main(string[] args) {
        while(true) {
            using(var container = new WindsorContainer()) {
                container.Register(Component.For<TestInterceptor>());
                container.Register(Component.
                    For<ITest>().
                    ImplementedBy<Test>().
                    Interceptors(
                        InterceptorReference.ForType<TestInterceptor>()
                    ).Anywhere);

                var tst = container.Resolve<ITest>();
            }
        }
    }
}

これは、メモリ使用量がどのように発展するかです。

メモリ使用量

だから私を失望させたのは、非マネージ コードのメモリ リークがあると思っていたということでしたが、多くのデバッグの後、問題はインターセプター prxoy の生成にあることがわかりました: プロキシ タイプの新しい (動的) アセンブリは解決されるたびにランタイムに導入されます。

インターセプタ プロキシが挿入されました

さて、私はあなたがこれを解決できると思います

  1. アプリ全体にグローバル(静的)コンテナを使用していますが、現時点ではこれは私のアプリでは実行できません(これはこれを行うための推奨される方法であり、理由は完全には明らかではありません)
  2. ProxyGenerator静的を使用して自分でプロキシUsingFactoryMethodを生成し、インスタンスを生成する方法を使用します(これは現在行っています)

これにより、3つの質問が残ります。

  1. Castle Windsor を正しく使用していますか (ドキュメントは完全に明確ではありません)、Castle Windsor がプロキシ タイプをキャッシュする方法はありますか?
  2. Castle Windsor はプロキシ タイプを自動的にキャッシュする必要がありますか (または、現在の動作はバグですか)?
  3. 動的に生成されたアセンブリがすべてのメモリを消費していることを (たとえば、perfmon を使用して) どのようにデバッグしますか?

ありがとうございました。

4

3 に答える 3

3

これがこれを行うための推奨される方法であると読みましたが、その理由は完全には明らかではありません

次の理由により、アプリケーションの存続期間中は 1 つのコンテナーを使用することをお勧めします。

  • コンテナーは、このシナリオ向けに高度に最適化されています。多くの場合、Reflection.Emit を使用したデリゲートの生成と情報がキ​​ャッシュされます。これにより、(コンテナー インスタンスごとに) 1 回限りのパフォーマンス ヒットが発生し、後続のすべての要求が高速化されます。リクエストごとに新しいインスタンスを作成すると、アプリケーションのパフォーマンスが低下する可能性があります。これは、このすべてのリフレクションとコードの発行が何度も発生するためです。
  • しかし、この最適化に加えて、登録プロセス自体にも時間がかかります。これは 1 回限りのコストかもしれませんが、何度も繰り返しています。
  • コンテナーの構成は、はるかに難しくなる可能性があります。リクエストよりも長く存続する必要があるインスタンスの登録は、はるかに困難です。これを回避する方法はありますが、多くの場合、把握しにくく、保守しにくく、バグのあるコンテナー構成になってしまいます。Castle Windsor には、コンテナーを検証できるコンテナー診断機能が含まれていますが、コンテナー間の検証は実行できません。
于 2013-02-06T14:41:30.057 に答える
1

今日、この同じ問題に遭遇しました。元の投稿の #3 に答えると、パフォーマンス カウンター [.NET Clr Loading -> Current Assemblies] は、動的プロキシ タイプが読み込まれているためにコード スニペットを実行すると、直線的に増加するアセンブリ数を示します。

于 2015-08-19T19:10:31.290 に答える
0

ドキュメントをよく読んでください。インターセプターを常に一時的にします。

正しいコードは次のとおりです。

public interface ITest{}
public class Test : ITest {}
class TestInterceptor:IInterceptor {
     public void Intercept(IInvocation invocation) {}
}
class Program {
static void Main(string[] args) {
    while(true) {
        using(var container = new WindsorContainer()) {
            container.Register(Component.For<TestInterceptor>().LifestyleTransient());
            container.Register(Component.
                For<ITest>().
                ImplementedBy<Test>().
                Interceptors(
                    InterceptorReference.ForType<TestInterceptor>()
                ).Anywhere);

            var tst = container.Resolve<ITest>();
        }
    }
}
}
于 2013-02-07T11:34:01.627 に答える