20

私のシリアライザー/デシリアライザーには、次のスニペットがあります。

    if (element_type.IsValueType && collection_type.IsArray)
    {
        try
        {
            GCHandle h = GCHandle.Alloc(array_object, GCHandleType.Pinned);
            int arrayDataSize = Marshal.SizeOf(element_type) * c.Count;
            var array_data = new byte[arrayDataSize];
            Marshal.Copy(h.AddrOfPinnedObject(), array_data, 0, arrayDataSize);
            h.Free();
            WriteByteArray(array_data);

            return;
        }
        catch (ArgumentException)
        {
            //if the value type is not blittable, then we need to serialise each array item one at a time
        }
    }

その目的は、値型の配列を可能な限り最も効率的な方法で (つまり、コンテンツをバイトの集まりとして) ストリームに書き込もうとすることです。

問題は、型が値型であるが blittable ではなく、Alloc() が失敗した場合に発生します。現時点では、例外がキャッチされ、参照型で構成されているかのように配列を処理するコードに制御が渡されます。

ただし、このチェックは (例外のスローとキャッチが非常に遅いため)、アプリケーションで遭遇する値の型の数が原因で深刻なボトルネックであることが証明されています。型がblittableかどうかを確認する最速の方法は何ですか?

4

9 に答える 9

7

結果をキャッシュするために汎用クラスを使用しています。テストは同じ方法で行われます (固定されたハンドルを割り当てようとしています)。

public static class BlittableHelper<T>
{
    public static readonly bool IsBlittable;

    static BlittableHelper()
    {
        try
        {
            // Class test
            if (default(T) != null)
            {
                // Non-blittable types cannot allocate pinned handle
                GCHandle.Alloc(default(T), GCHandleType.Pinned).Free();
                IsBlittable = true;
            }
        }
        catch { }
    }
}
于 2015-02-15T22:22:06.970 に答える
0

http://msdn.microsoft.com/en-us/library/system.type.islayoutsequential.aspxおよびhttp://msdn.microsoft.com/en-us/library/system.type.isexplicitlayout.aspxを使用します。

element_type.IsValueType && collection_type.IsArray && (element_type.IsLayoutSequential || element_type.IsExplicitLayout)
于 2012-05-13T22:34:02.033 に答える