为什么带指针的不安全块比普通版慢

时间:2013-05-24 18:16:49

标签: c#

我正在测试使用不安全和字符匹配指针计算1兆字节char数组中每个位置的200字节数组作为安全/不安全/ dll调用速度比较的实验。

它们在发布模式下运行,优化代码打开,允许不安全,无边界检查。 Long char数组用于最大限度地减少呼叫开销影响。

我得到的时间是

  

常规560毫秒

     

不安全830毫秒

     

dll 205 ms

为什么不安全的慢?

    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();
    }
}

1 个答案:

答案 0 :(得分:0)

我检查了你的代码,我没有得到你的不安全代码更慢。但是,我重写了你的不安全代码(相当快 - 双重检查),但我相信这对你来说应该更简单:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    byte[] buffer = new byte[1000000];
    byte[] check = new byte[200];

    private unsafe void button1_Click(object sender, EventArgs e)  // do char array matching
    {
        Random rnd = new Random();
        rnd.NextBytes(buffer);
        rnd.NextBytes(check);
        Stopwatch sw = Stopwatch.StartNew();

        byte match = 0;
        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();

        fixed (byte* pCheck = check, pBuffer = buffer)
        {
            match = 0;
            kk = 0;
            jq = 0;

            while (kk < 999000)
            {
                kk++;
                match = 0;
                for (jq = 0; jq < 199; jq++)
                    if (pBuffer[kk + jq] == pCheck[jq])
                        match++;
                pBuffer[kk] = match;
            }
        }
        sw.Stop();
        textBox2.Text = sw.Elapsed.TotalMilliseconds.ToString();
    }
}

结果:

管理:404毫秒 不安全:284毫秒

这是在发布时通过右键单击项目并在没有调试器的情况下启动新实例来执行的。我还检查了我的代码,它给出了两种方法相同的结果。