2013-05-24 2 views
1

안전하지 않은/안전하지 않은/dll 호출 속도 비교가있는 실험으로 1 meg 길이의 char 배열의 모든 위치에서 200 바이트 배열의 문자 일치 계산에 안전하지 않은 포인터를 사용하여 테스트하고 있습니다. .포인터가있는 안전하지 않은 블록이 일반 버전보다 느린 이유

코드는 최적화 모드로 실행되고, 안전하지 않고 범위 검사는 허용되지 않습니다. 긴 문자 배열은 호출 오버 헤드 영향을 최소화하기 위해 의도적으로 사용됩니다. 제가

얻을

시간은 830 밀리

DLL 205 MS

이유 불안전 느린

안전

일반 560 밀리 초이다 ??

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

나는 당신이 더 많은 공간을 사용해야한다고 생각합니다, 그것은 당신의 코드를 더 읽기 쉽게 만들 것입니다. 이것은 코드 골프가 아닙니다. – svick

+0

디버거를 연결하지 않고 실행 했습니까? – svick

+0

svick, 예 디버거없이 실행되었습니다. –

답변

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 MS 안전하지 않은 : 284 MS

이것은 프로젝트에서 마우스 오른쪽 버튼을 클릭하고 디버거없이 새 인스턴스를 시작하여 릴리스에서 실행되었습니다. 나는 또한 내 코드를 검사했고 두 방법 모두에서 같은 결과를 얻었다.

+0

포인터 역 참조가 닷넷의 추가 단계 인 것처럼 보입니까? –

+0

@KelseyBowman 원한다면 포인터 산술로 바꿀 수 있지만, 그들은 같은 것이라고 생각합니다. 즉 ptr [5]는 * (ptr + 5)와 동일합니다. 나는 그것을 시도해 볼 것이다 – Alan

+0

if (* bufhldptr ++ == * chckhldptr ++) match ++; 과거의 원시 코드 생성에서는 변수가 이미 프로세서 레지스터에 있었기 때문에 이러한 유형의 작업이 빨라졌습니다. 그러나 이것은 관리되는 코드에 적용되지 않는 것처럼 보입니까 ?? –

관련 문제