4

再初期化せずに、複数の同時 ASP.NET 要求で非スレッド セーフ エンコーダー インスタンスのプールを使用したいと考えています。初期化コストを気にしない場合は、次のようにします。

public class ResultController {
    public JsonResult GetResults() {
        List<MyViewModel> items = new List<MyViewModel>();
        // It obviously does more than this in real life
        for(id = 0; id < 1000; id++) {
            items.Add(new MyViewModel(id));
        }
        return Json(items);
    }
}

public class MyViewModel() {
    public string CodedId { get; set; }
    public MyViewModel(int id) {
        // This "new" is the concern
        CodedId = new ExpensiveToInitializeCodec().InexpensiveEncode(id);
    }
}

正常に動作します。すべての地元の人、スレッド化について心配する必要はありません。私のモデルの外にいる人は、値がエンコードされて表示されていることを理解する必要はありません。ただし、簡単なパフォーマンス テストでは、各初期化に約 0.129 ミリ秒かかりますが、エンコード自体には 0.006 ミリ秒未満かかります。(参考までに、コーデックは TripleDESCryptoServiceProvider です)。

事前に初期化されたオブジェクトを渡すことなく、その初期化コストを制限したいと考えています (パフォーマンスを向上させるためにコンストラクターなどに渡しますが、関心の分離を壊します)。これが私が現在行っていることであり、この単純な例の外では明らかに面倒です:

public class ResultController {
    public JsonResult GetResults() {
        List<MyViewModel> items = new List<MyViewModel>();
        ExpensiveToInitializeCodec codec = new ExpensiveToInitializeCodec();
        for(id = 0; id < 1000; id++) {
            items.Add(new MyViewModel(id, codec));
        }
        return Json(items);
    }
}

public class MyViewModel() {
    public string CodedId { get; set; }
    public MyViewModel(int id, ExpensiveToInitializeCodec codec) {
        CodedId = codec.InexpensiveEncode(id);
    }
}

よく知られている ASP.NET の要求ごとのキャッシュ パターンを活用できます。

public class MyViewModel() {
    public string CodedId { get; set; }
    public MyViewModel(int id) {
        CodedId = ExpensiveToInitializeCodec.Get().InexpensiveEncode(id);
    }
}

public class ExpensiveToInitializeCodec {
    public static ExpensiveToInitializeCodec Get() {
        ExpensiveToInitializeCodec codec = HttpContext.Current.Items["codec"];
        if (codec == null) {
            codec = new ExpensiveToInitializeCodec();
            HttpContext.Current.Items["codec"] = codec;
        }
        return codec;
    }
}

しかし、タイトなループで実行するのはまだ無駄です: HttpContext.Current 呼び出しの背後にある計算はどれくらいですか?

また、スレッドごとのソリューションは、リクエストごとのソリューションよりも正確であるように思われました。ASP.NET 要求と互換性のある提案はありますか?

ASP の外ではあるが .NET 空間では、ある人の答えは ThreadStatic でした。ThreadStaticを使用して高価なローカル変数を置き換えます -- 良いアイデアですか? . ただし、http://blog.idm.fr/2010/03/aspnet-thread-agility-or-why-threadstatic-should-not-be-used.htmlは、ASP.NET でのそのソリューションを明らかに排除しています。私の同様の質問HttpContext.Current.Items で使用するために ThreadStatic を模倣する方法はありますか? 無回答になりました。

編集: コーデックの使用が I/O 操作とインターリーブされていないことを確認すれば、ThreadStatic を使用できるように見えますが、それがどれほど安全かはわかりません。

私は今到達していますが、私が考えた他のいくつかのアプローチには、1) EncodedAttribute を持つアイテムのカスタムシリアライゼーション/デシリアライゼーションを提供する、2) インスタンス初期化オーバーヘッドなしで独自の静的 TripleDES シングルブロック暗号化を実装する、3) に対して私の設定、外部で初期化された暗号化子を各アイテムのコンストラクターに渡す、4) IEncryptable インターフェイスを実装し、結果が入力された後にアイテムを再列挙する、5) ビューモデルの外部ですべての暗号化を実行し、ビューモデルが使用されるすべての場所に実装する.

4

1 に答える 1