6

TCP ソケットから受信したメッセージを取得し、それらをエンコード/デコードし、暗号化/復号化する一連のメソッドをサーバー アプリケーションに記述しようとしています。

メッセージは、それぞれ独自のプロパティ セットと合計長を持つ特別な型として定義されていることを考慮すると、次の解決策のいずれかを選択する必要がありますEncode<T>(...) where T : IMessage。などの をResolveEncoder<T>実装している限り、任意のタイプのメッセージを使用するメソッドを作成し、System.Reflectionを使用して、それについて知る必要があるすべてを決定します。IMessageEncode(IMessage message)

コードが 30 分の 1 になるので、解決策 2 に興味があります。ただ、プロパティの常時反映が性能に影響しないか心配です。プロジェクトを完了するための時間が限られているため、実際に「実験」することはできません。

いずれかのソリューションでパフォーマンスがどのように低下​​するかについての個人的な経験やベンチマークとのリンクに感謝します.

4

6 に答える 6

6

プロジェクトを完了するための時間が限られているため、実際に「実験」することはできません。

次に、実際の制約はパフォーマンスではなく、指定された時間制約内でコーディング、テスト、およびデバッグできることです。反射バージョンが 30 倍小さいというあなたの主張を仮定すると、それはあなたが傾くべきもののように聞こえます。

ただし、5つのポイント:

  1. 30x が正しい推定値であるかどうかは疑問です。おそらくはるかに小さいでしょう。
  2. リフレクションは、ジェネリックを使用するよりもパフォーマンスが低下します。それについては疑問の余地はありません。
  3. 「しかし、常にプロパティを反映することがパフォーマンスに影響するか心配です。」PropertyInfoリフレクションによってロードするものとそうでないものを積極的にキャッシュすることで、これの一部を軽減できます。
  4. 式ツリーを使用すると、リフレクションに似た処理を実行できます。これにより、パフォーマンスが大幅に向上します。これは、この問題について正しい方向に導くブログ投稿です。ただし、式ツリーの操作に慣れていない場合は、時間の制約があるため、慣れていない概念を使用してコーディング、テスト、およびデバッグを行うのは危険です。
  5. これがパフォーマンスのボトルネックでさえあると確信していますか? ここでネットワーク遅延が支配的であり、時期尚早に最適化していても、私はショックを受けません.
于 2012-04-18T03:38:14.840 に答える
4

リフレクションは十分に高速です。しかし、正しく実装する必要があります。

反射性能 -

速くて軽い機能

typeof
Object.GetType
typeof == Object.GetType
Type equivalence APIs (including typehandle operator overloads)
get_Module
get_MemberType
Some of the IsXX predicate APIs
New token/handle resolution APIs in the .NET Framework 2.0

コストのかかる機能

GetXX  APIs (MethodInfo, PropertyInfo, FieldInfo, and so on)
GetCustomAttributes
Type.InvokeMember
Invoke APIs (MethodInfo.Invoke, FieldInfo.GetValue, and so on)
get_Name (Name property)
Activator.CreateInstance

ソース - 高速なアプリケーションを作成するための一般的なパフォーマンスの落とし穴を回避する

MethodInfo は高速化できます -パフォーマンスの反映の改善、どの代替案を検討する必要がありますか

良いリンク:
.NET リフレクションのコストはどれくらいですか?
http://www.codeproject.com/Articles/18450/HyperDescriptor-Accelerated-dynamic-property-acces

于 2012-04-18T03:55:15.703 に答える
0

多くの場合役立つアプローチの1つは、静的ジェネリッククラスでReflectionを使用することです。これは、のようなものによって取られるアプローチEqualityComparer<T>.Defaultです。基本的に、特定のタイプTの場合、最初の参照EqualityComparer<T>.DefaultはReflectionを使用して、タイプが制約なしで動作して使用する実装か、制約TIComparable<T>て使用する実装かを判断する必要があります。その目的でリフレクションを使用するのはやや遅いですが、特定のタイプに対して1回だけ実行する必要があります。実装が構築されると、静的フィールドに格納されます。IEqualityComparer<T>TObject.EqualsTIEqualityComparer<T>IEqualityComparer<T>.EqualsTEqualityComparer<T>したがって、そのタイプのデフォルトの比較子を取得するための将来の要求は、以前に構築IEqualityComparer<T>された実装を単純に使用できるようになります。

このアプローチは、ジェネリックスの速度と、ジェネリックスだけでは十分ではないことを実行する柔軟性を兼ね備えています。

于 2012-04-18T17:36:46.157 に答える
0

ジェネリックはコンパイル時にバインドされ、通常の型と同じようにパフォーマンスが向上します。反省には莫大なコストがかかります。

于 2012-04-18T03:35:06.170 に答える
0

パフォーマンスが重要な場合は、メッセージの種類ごとにDynamicMethodを生成することを検討してください。動的メソッドを生成するコードは、(リフレクションの場合と同様に) すべてのメッセージ タイプで同じになりますが、動的メソッドが生成されると、リフレクションのパフォーマンス ヒットはありません。欠点は、コードを書くのが難しく、デバッグがより難しいことです。そのため、時間に追われている場合、これは最良の選択肢ではない可能性があります。

于 2012-04-18T04:19:53.247 に答える
0

現在のコードはこれを行います:

protected void Decode<T>(Action<BinaryReader> action, byte[] buffer) {...}

MemoryStream ストリームを作成します。ストリームに BinaryReader リーダーを作成します。そして、アクション(リーダー)を実行します。

ここで、バイト Id と int 記述子の 2 つのプロパティのみを持つ HelloMessage.cs があるとします。デコーダ クラス HelloMessageCodec.cs の Decode メソッドは次のようになります。

public HelloMessage Decode(byte[] buffer)
{
    var message = new HelloMessage();
    Decode<HelloMessage>(reader => 
        { message.Id = reader.ReadByte();
          message.Descriptor = reader.ReadInt32();
        }, buffer);
    return message;
}

これは非常にうまく行われていますが、約 15 種類のメッセージがあり、各種類には独自の xxxMessageCodec.cs があり、Decode と Encode の実装があり、それぞれに Action デリゲート内で手動で渡されたプロパティがあります。

ここで、暗号化を行う必要があります。つまり、このパターンに従うとしたら、15 の異なるメッセージ暗号化プログラムを作成する必要があります。

私はすでにすべてのコーデック コードをソリューション #2 (リフレクションあり) に作り直しました。15 x 2 関数の代わりに、2 つの関数しかありません + 基礎となるレベルはなく、プロパティによってメッセージを処理し、ReadByte、ReadInt32 を呼び出す 2 つの関数だけです。 ...プロパティのタイプに応じて。

それで、作業は完了しましたが、暗号化の作業に移らなければならないため、パフォーマンスをテストするのに十分な時間がありません. 続行するには、2 つの解決策のいずれかを選択する必要があります。小さい方の解決策 (反射の解決策) が後で顔を蹴り返すかどうか、睡眠の問題があります :)

于 2012-04-19T05:15:59.027 に答える