2012-07-16 8 views
5

コードの下に反映されているフォームの.NET Framework:私の意見ではMarshal.WriteInt64メソッドのコードが複雑なのはなぜですか?

[SecurityCritical] 
public static unsafe void WriteInt64(IntPtr ptr, int ofs, long val){ 
    try{ 
     byte* numPtr = (byte*) (((void*) ptr) + ofs); 
     if ((((int) numPtr) & 7) == 0){ 
      *((long*) numPtr) = val; 
     } 
     else{ 
      byte* numPtr2 = (byte*) &val; 
      numPtr[0] = numPtr2[0]; 
      numPtr[1] = numPtr2[1]; 
      numPtr[2] = numPtr2[2]; 
      numPtr[3] = numPtr2[3]; 
      numPtr[4] = numPtr2[4]; 
      numPtr[6] = numPtr2[6]; 
      numPtr[7] = numPtr2[7]; 
     } 
    } 
    catch (NullReferenceException){ 
     throw new AccessViolationException(); 
    } 
} 

*((long*) numPtr) = valは十分に、かつ非常に効率的です。

なぜ複雑なのですか?

+0

(これは「ループ展開」と呼ばれる)いくつかの時間を節約するためにループをスキップし、一度にendiensとは何かを1つのバイトを書き込みますか? 。 – KingCronus

+5

それは私とのメモリアラインメントと関係があるように見えます。 –

+0

これはmemcpy()です。手動で展開します。 ARMコアには必要です。 –

答えて

6

最適化されていますが、やや単純です。

外側のif - itは、Int64を1回の操作で書くことができるかどうかをチェックします(メソッドを渡すポインタが適切な位置にある場合に起こります - メモリ内のInt64の開始点を指します)。 8の倍数)。

使用すると、1回の操作で書き込みができない場合は、コードがちょうど多分

+0

彼らは4バイト境界のためにそれを最適化できたと推測します。 – leppie

+0

おそらく、小切手自体が高価すぎて平均的に実際の差を出すことはできませんでした。 – zmbq

+0

'varデータ=新しいバイト[128]; long num = 0x1234567890ABCDEF; 固定(バイト* p =データ) { *(long *)(p + 1)= num; *(ロング*)(p + 10)= num; } 'ポインタを揃えないと、このコードはうまく動作します。 – ldp

関連する問題