簡體   English   中英

C#改善二進制序列化

[英]c# improve binary serialization

我目前正在從事一個基於其他代碼生成代碼的項目。 本質上是將編程語言本身用作DSL。

生成器目標之一是二進制DataContract序列化程序,以及為以下類生成的ToBytes

[DataContract]
public partial class Root
{
    [DataMember]
    public int Number { get; set; }

    [DataMember]
    public Partial[] Partials { get; set; }

    [DataMember]
    public IList<ulong> Numbers { get; set; }
}

變成這個:

public int Size
{
    get 
    { 
        var size = 8;
        // Add size for collections and strings
        size += Partials.Sum(entry => entry.Size);
        size += Numbers.Count * 8;

        return size;              
    }
}
public byte[] ToBytes()
{
    var index = 0;
    var bytes = new byte[Size];

    return ToBytes(bytes, ref index);
}
public byte[] ToBytes(byte[] bytes, ref int index)
{
    // Convert Number
    Buffer.BlockCopy(BitConverter.GetBytes(Number), 0, bytes, index, 4);;
    index += 4;
    // Convert Partials
    // Two bytes length information for each dimension
    Buffer.BlockCopy(BitConverter.GetBytes((ushort)(Partials == null ? 0 : Partials.Length)), 0, bytes, index, 2);
    index += 2;
    foreach(var value in Partials ?? Enumerable.Empty<Partial>())
    {
        value.ToBytes(bytes, ref index);
    }
    // Convert Numbers
    // Two bytes length information for each dimension
    Buffer.BlockCopy(BitConverter.GetBytes((ushort)(Numbers == null ? 0 : Numbers.Count)), 0, bytes, index, 2);
    index += 2;
    foreach(var value in Numbers ?? Enumerable.Empty<ulong>())
    {
        Buffer.BlockCopy(BitConverter.GetBytes(value), 0, bytes, index, 8);;
        index += 8;
    }
    return bytes;
}

現在,即使這變得非常困難,我也正在尋找一種方法來加速Buffer.BlockCopy(BitConverter.GetBytes所有使用。為每次轉換創建一個新的小byte[]然后復制它似乎仍然浪費資源。當我都准備好了byte[]和位置的時候。

有什么想法可以最好地改進代碼嗎?

更新:基於@adrianm注釋,我將用數組的for循環替換foreach並將可空類型包裝在if語句中。 不需要在另一個線程中使用結構。 我寧願使用類和[DataContract]屬性。 另外,為了符合Linux,我不能使用WinApi。

Update2:添加了其余的生成代碼。 感謝您的評論,將來的版本將包括

if (index + Size > bytes.Length)
    // Some error handling

因此,我看到了BitConverter的實現以及它們對unsafe和指針的使用,以創建byte[] 我想在生成的代碼中使用它,例如:

*byte pointer = bytes;
*((int*)pointer + pos) = Number;
pos += 4;

但是在那種情況下,這將是一種不安全的方法,並且我不確定這將對那里的更多托管代碼產生什么影響。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM