web-dev-qa-db-ja.com

リフレクションはどのくらい遅い

DataAccessProviderをビジネスロジックレイヤーと区別するために、最近インターフェイスレイヤーを作成しました。このアプローチでは、Web/App.Configの値を変更することにより、必要に応じていつでもDataAccessProviderの選択を変更できます。 (必要に応じて詳細を指定できます)。

とにかく、これを行うには、リフレクションを使用して、作業できるDataProviderクラスを完成させます。

/// <summary>
/// The constructor will create a new provider with the use of reflection.
/// If the Assembly could not be loaded an AssemblyNotFoundException will be thrown.
/// </summary>
public DataAccessProviderFactory()
{
    string providerName = ConfigurationManager.AppSettings["DataProvider"];
    string providerFactoryName = ConfigurationManager.AppSettings["DataProviderFactory"];
    try
    {
        activeProvider = Assembly.Load(providerName);
        activeDataProviderFactory = (IDataProviderFactory)activeProvider.CreateInstance(providerFactoryName);
    }
    catch
    {
        throw new AssemblyNotFoundException();
    }
}

しかし、今私は反射がどれほど遅いのか疑問に思っていますか?

63
user29964

非反射コードと比較して遅いです。重要なことは、遅いかどうかではなく、遅い場合カウントされる場所です。たとえば、予想される同時実行性が10Kまで上昇する可能性があるWeb環境でリフレクションを使用してオブジェクトをインスタンス化する場合、速度は遅くなります。

とにかく、事前にパフォーマンスを気にする必要がないのは良いことです。物事が遅いことがわかった場合、物事を正しく設計していれば、いつでもスピードアップして、将来最適化が必要になると予想される部分をローカライズすることができます。

スピードアップが必要な場合は、この有名な記事を確認できます。

Dynamic ... But Fast:The Tale of Three Monkeys、A Wolf and the DynamicMethod and ILGenerator Class

17
majkinetor
9
Ruben Steins

反射はそれほど遅くありません。リフレクションによるメソッドの呼び出しは、通常の方法より約3倍遅くなります。これを1回だけ行う場合、または重大でない状況で行う場合は、問題ありません。タイムクリティカルな方法で10000回使用する場合は、実装を変更することを検討します。

5
Enyra

反射が遅い場合と反射がない場合とを比較するために簡単なテストを行うと思いました。

反射あり

  • 58個のオブジェクトを、それぞれの属性を反復して照合することによりインスタンス化します。
  • 合計時間:52254ナノ秒

    while (reader.Read()) {
        string[] columns = reader.CurrentRecord;
        CdsRawPayfileEntry toAdd = new CdsRawPayfileEntry();
        IEnumerable<PropertyInfo> rawPayFileAttributes = typeof(CdsRawPayfileEntry).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(CustomIndexAttribute)));
        foreach (var property in rawPayFileAttributes) {
            int propertyIndex = ((CustomIndexAttribute)property.GetCustomAttribute(typeof(CustomIndexAttribute))).Index;
            if (propertyIndex < columns.Length)
                property.SetValue(toReturn, columns[propertyIndex]);
            else
                break;
        }
    }
    

リフレクションなし

  • 新しいオブジェクトを作成して58個のオブジェクトをインスタンス化する
  • 合計時間:868ナノ秒

        while (reader2.Read()) {
            string[] columns = reader2.CurrentRecord;
            CdsRawPayfileEntry toAdd = new CdsRawPayfileEntry() {
                ColumnZero = columns[0],
                ColumnOne = columns[1],
                ColumnTwo = columns[2],
                ColumnThree = columns[3],
                ColumnFour = columns[4],
                ColumnFive = columns[5],
                ColumnSix = columns[6],
                ColumnSeven = columns[7],
                ColumnEight = columns[8],
                ColumnNine = columns[9],
                ColumnTen = columns[10],
                ColumnEleven = columns[11],
                ColumnTwelve = columns[12],
                ColumnThirteen = columns[13],
                ColumnFourteen = columns[14],
                ColumnFifteen = columns[15],
                ColumnSixteen = columns[16],
                ColumnSeventeen = columns[17]
            };
        }
    

とはいえ、リフレクションはすべてのプロパティの特定の属性を58 * 18回リフレクション経由で新しいオブジェクトを作成する上で取得する必要があるため、完全に公平ではありませんが、少なくともある程度の観点は提供されます。

5
Levi Fuller

他の回答に記載されているリンクをたどり、「病理学的に悪い」コードを記述していないことを確認する以外は、私にとってこれに対する最良の答えは自分でテストすることです。

ボトルネックがどこにあるか、リフレクションコードがユーザーになる回数、リフレクションコードがタイトループになるかどうかなど、あなただけが知っています。ビジネスケース、サイトにアクセスするユーザー数、パフォーマンス要件は何ですか。

ただし、ここで示したコードスニペットを考えると、リフレクションのオーバーヘッドが大きな問題になることはないと思います。

VS.NET Webテストおよびパフォーマンステスト機能により、このコードのパフォーマンスの測定が非常に簡単になります。

リフレクションを使用しない場合、コードはどのようになりますか?どのような制限がありますか?リフレクションコードを削除すると、限界に耐えられなくなる可能性があります。このコードをリフレクションなしで設計して、それが可能かどうか、または代替手段が望ましいかどうかを確認することは価値があるかもしれません。

3
Martin Peck

IoCを使い始めるまで、私は同じようなことをしていました。 Springオブジェクト定義を使用して、データプロバイダー(SQL、XML、またはMocks)を指定します。

0
n8wrl