LoginSignup
0
0

More than 5 years have passed since last update.

小ネタ:箱詰めの値型を外側から偏執的にいじる

Posted at

どーいうこと?

昨日、dynamic 経由の値型の取り回しと言うエントリをアップしたのですが、その後気になるというかまぁ調べてみっか程度に、色々と調べてみたら、どうやらコールサイトの構築時に内部でボックス化を含む処理を生成しているらしく高頻度に動かしたときGarbageCollectionが発生していた。

本質的に、値型をボックス化した挙げ句、ボックス化した状態で結構な回数書き換え、読み込みを行うことなんて本来的には問題が多く、改善をすべき状態ではあるけど、ここは一つ偏執狂的に何とか出来ないか追い求めてみたので、おつきあい頂ければ幸い。

尚、今回はパラノイア回なのでほとんど自己満足として、出来ましたと言う事実の提示であって、積極的にお勧めなんてとても出来る代物では無いのでその点十分ご留意の程。

前説

さて、今回使う箱詰めにする構造体は以下の通り

public struct SomeStruct
{
    public int Value { get; set; }

    public override string ToString() => Value.ToString();
}

で、コレを、以下のように操作したとき、


static void Main()
{
    dynamic d = new SomeStruct { Value = 42 };

    for (int i = 0; i < 1000000; i++)
    {
        d.Value += i;
    }

    Console.WriteLine(d.Value);
}

自分の環境では、

  • Generation0:17回
  • Generation1:1回
  • Generation2:0回

という感じでGarbageCollectionが発生していた。
で、ここのカウントを0にしていきましょうというのが今回のお題です。

dynamic無しでとりあえずどうかしてみる

dynamicの使用せず、ボックス化したままValueプロパティをGet/Setするにはリフレクションを使えばまぁ何とかなる。


static void Main()
{
    object obj = new SomeStruct {Value = 42};

    var propInfo = typeof (SomeStruct).GetProperty("Value");


    for (int i = 0; i < 1000000; i++)
    {
        var tmp = i + (int) propInfo.GetValue(obj);
        propInfo.SetValue(obj, tmp, null);
    }

    Console.WriteLine(obj);
}

ただ、propInfo.GetValueメソッドの戻りはobjectからintへのUnboxingが発生しているし、propInfo.SetValueメソッドの第2引数もintからobjectへのBoxingが発生している。
だもんで、自分の環境ではGeneraton0が26回発生していた。

どーせ行くならパラノイア♪

ということで、基本はリフレクション経由で行くとして、解決すべきはBoxingUnboxingが発生させなきゃ良いので、それは何とかしたい。
で何とかしたのが以下1


static void Main()
{
    object obj = new SomeStruct {Value = 42};

    var propInfo = typeof (SomeStruct).GetProperty("Value");

    var setter = (Action<int>) propInfo.SetMethod.CreateDelegate(typeof (Action<int>), obj);
    var getter = (Func<int>) propInfo.GetMethod.CreateDelegate(typeof (Func<int>), obj);

    for (int i = 0; i < 1000000; i++)
    {
        var tmp = i + getter();
        setter(tmp);
    }

    Console.WriteLine(obj);
}

見事、GarbageColletionを発生させないまま完了したけど、一般的なシナリオ2では多分、setter,getterの構築コストをペイできないし、そもそも、何れのデリゲートもobj変数専用となっており、ほぼ使い道は無い。

とはいえ、多分実用的な場面でコンなこと必要なシナリオは多分ないかな~とは思う。でも良いじゃ無いパラノイアなんだから♪


  1. ごめん。飽きたw 

  2. 含む、ちょっと逸般的なシナリオ。余程な逸般的なシナリオは除く。 

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0