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()は先日書いた事情でポインタに出来ない