0

我目前正在开发一个基于其他代码生成代码的项目。本质上将编程语言本身用作 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。

更新 2:添加了生成的代码的其余部分。感谢评论未来的版本将包括

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

1 回答 1

0

所以我看到了BitConverter的实现以及他们使用 unsafe 和指针来创建byte[]. 我想在生成的代码中使用它,例如:

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

但在那种情况下,这将是一个不安全的方法,我不确定这会对那里的更多托管代码产生什么影响。

于 2016-04-07T07:40:27.840 回答