安全/安全でない/dll の呼び出し速度を比較する実験として、1 メガバイトの長さの char 配列のすべての位置に沿って 200 バイト配列をカウントする文字一致の unsafe とポインターを使用してテストしています。
コードの最適化をオンにしてリリース モードで実行し、安全でないことを許可し、境界チェックを行いません。long char 配列は、呼び出しのオーバーヘッドへの影響を最小限に抑えるために意図的に使用されます。
私が得る時間は
通常 560 ミリ秒
安全でない 830 ミリ秒
dll 205 ミリ秒
unsafe が遅いのはなぜですか??
byte[] buffer = new Byte[1000000];
byte[] check = new Byte[1000];
[DllImport("sortitdev.dll", CallingConvention=CallingConvention.StdCall)]
//[DllImport("sortitfast.dll", CallingConvention=CallingConvention.StdCall)]
//[DllImport("sortitpellas.dll", CallingConvention=CallingConvention.StdCall)]
public unsafe static extern void sortitt([MarshalAs(UnmanagedType.LPArray)] byte[] buffer);
public MainForm()
{
InitializeComponent();
}
void Button1Click(object sender, EventArgs e) // do char array matching
{
byte match;
Random rnd = new Random();
for(int i=0;i<1000000;i++)
buffer[i]=(byte)rnd.Next(0,256);
for(int i=0;i<200;i++)
check[i]=(byte)rnd.Next(0,256);
Stopwatch sw = Stopwatch.StartNew();
int kk=0;
int jq=0;
while(kk<999000)
{
kk++;
match=0;
for(jq=0;jq<199;jq++)
if(buffer[kk+jq]==check[jq])match++;
buffer[kk]=match;
}
sw.Stop();
textBox1.Text= sw.Elapsed.TotalMilliseconds.ToString();
sw.Reset();
sw.Start();
unsafe
{
fixed (byte* bufptr=&buffer[0] , chckptr=&check[0])
{
byte* bufptrC=bufptr; // modifiable pointer
byte* chckptrC=chckptr;
byte* bufhldptr;
byte* chckhldptr;
int k=999000;
int jw=0;
while(k>0)
{
bufhldptr=bufptrC;
match=0;
chckhldptr=chckptrC;
for(jw=0;jw<199;jw++)
if(*bufhldptr++==*chckhldptr++)match++;
*bufptrC++=match;
k--;
}
}
sw.Stop();
textBox2.Text= sw.Elapsed.TotalMilliseconds.ToString();
}
sw.Reset();
for(int tt=0;tt<200;tt++) buffer[tt]=(byte)tt;
sw.Start();
unsafe
{
fixed(byte* dadata=&buffer[0])
{
sortitt(buffer);
}
}
sw.Stop();
textBox3.Text= sw.Elapsed.TotalMilliseconds.ToString();
int kll=(int)buffer[1];
textBox4.Text= kll.ToString();
}
}