私は、ユーザーが特定のデータソース (興味のある方のために、Football Manager 2010 のゲーム内データベース) に対してクエリを実行できるようにするフレームワークを用意しています。
このフレームワークには、フレームワークを実行できる 2 つの異なるモード (リアルタイム モードとキャッシュ モード) があります。このフレームワークを使用しているユーザーが、別のコンストラクターを呼び出すだけで切り替えられるようにしてほしい (例: new Context(Mode.Cached)
)。これは、ユーザーが行う必要がある唯一の切り替えである必要があるため、ユーザーは引き続きすべて同じ Linq 呼び出しを行うことができますが、アプリケーションがより適している場合はキャッシュ モードを使用するだけです。クリア。
次の理由から、PostSharp を使用することが最善の選択であると判断しました。
- すべてのプロパティにアスペクトを作成します (属性によって既に装飾されています)。
- その面では、私たちがモードにいる
Cached
かどうかを確認してくださいRealtime
- メモリまたはキャッシュから値を返す
それはうまくいきます。しかし!速度が十分ではありません。90.000 個のオブジェクトに対して次の操作を行う場合:
foreach (Player p in fm.Players)
{
int ca = (short)ProcessManager.ReadFromBuffer(p.OriginalBytes, PlayerOffsets.Ca, typeof(Int16));
}
わずか 63 ミリ秒かかります。(ReadFromBuffer は高度に最適化された関数で、 を受け取ってbyte[], int, Type
返しますobject
)、大量のオブジェクトを考慮すると、63 ミリ秒は非常に妥当です。
しかし!PostSharp では、これを使用してまったく同じものを実装しました。
public override void OnInvocation(MethodInvocationEventArgs eventArgs)
{
if (eventArgs.Method.Name.StartsWith("~get_"))
{
if (Global.DatabaseMode == DatabaseModeEnum.Cached)
{
byte[] buffer = ((BaseObject)eventArgs.Instance).OriginalBytes;
eventArgs.ReturnValue =
ProcessManager.ReadFromBuffer(buffer, this.Offset, eventArgs.Method.ReturnType);
}
今、私はこれを使用して呼び出します
foreach (Player p in fm.Players)
{
int ca = p.CA;
}
そして、10 倍以上の782 msかかります。
アスペクトを次のように作成しました。
[Serializable]
[MulticastAttributeUsage(MulticastTargets.Method, PersistMetaData = true)]
internal class FMEntityAttribute : OnMethodInvocationAspect
{
public FMEntityAttribute(int offset, int additionalStringOffset)
{
this.Offset = offset;
this.AdditionalStringOffset = additionalStringOffset;
}
//blah blah AOP code
}
そして、プロパティは次のように装飾されています
[FMEntityAttribute(PlayerOffsets.Ca)]
public Int16 CA { get; set; }
どうすればこれをうまく機能させることができますか?!