ものがたり(旧)

atsushieno.hatenablog.com に続く

from array to fixed pointer, and ABCREM

例のEncoding実装の話の続き。

現在、とりあえずI18Nライブラリに含まれるカスタムエンコーディングのGetBytes()*1を例のポインタベースで書き換えようとしているのだけど、ひとつ問題があることに気付いた。ABCREM(配列境界チェック)はmanaged arrayには有効だけど、fixed pointerには効かない:


using System;

public class Test
{
public unsafe static void Main (string [] args)
{
int count = 10000;
if (args.Length > 0)
count = int.Parse (args [0]);

char [] arr = new char [100];
int len = arr.Length;
char c;
fixed (char* cptr = arr) {
//char [] cptr = arr;
DateTime start = DateTime.Now;
for (int i = 0; i < count; i++)
for (int x = 0; x < len; x++)
c = cptr [x];
Console.WriteLine (
DateTime.Now.Ticks - start.Ticks);
}
}
}

ということは、単純にGetBytes(char,int,int,byte,int)をGetBytes(char*,int,byte*,int)に置き換えると、(ABCREMが有効に機能するという前提で)パフォーマンスがABCREMの分だけ損なわれるということにもなりうる。

Massiに聞いてみたら、fixed pointerについては、(境界が無いので)ABCはあり得ないけど、null checkについては可能だろう、という話で、いずれHSSAが実装された暁には、この最適化もサポートしてもらえそうだ。ちなみに、MS.NETで↑のコードを動かしてみたら、1.xではfixed pointerの方が遅かったが、2.0では逆の結果が出た。

たぶん、null checkが有効になるようなコードは、現在のI18Nライブラリみたいな実装になっていると不可能だろうから、この辺をいじるのは後にした方が良いかもしれないが、どっちにしろ現在のI18NコードではABCREMも効いていないはずなので、とりあえずこのまま進めてしまおう。

*1:こっちだけ。GetChars()は先日書いた事情でポインタに出来ない