I am currently working on a project that generates code based on other code. Essentially using the programming language itself as a DSL.
One of the generator targets is a binary DataContract serializer and the generated ToBytes for the following class
[DataContract]
public partial class Root
{
[DataMember]
public int Number { get; set; }
[DataMember]
public Partial[] Partials { get; set; }
[DataMember]
public IList<ulong> Numbers { get; set; }
}
becomes this:
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;
}
Now even tough this is really fast I am looking for a way to speed up all the uses of Buffer.BlockCopy(BitConverter.GetBytes
. It still seems to be waste of resources to create a new small byte[]
for every conversion and then copy that when I allready have the byte[]
and the position.
Any ideas how to best improve the code?
Update: Based on @adrianm comment I will replace foreach with for-loops for arrays and wrap nullable type in if statements. Using structs as in another thread is not wanted. I would rather use classes and [DataContract] attributes. Also for Linux compliance I can't use WinApi.
Update2: Added the rest of the generated code. Thanks to a comment future version will include
if (index + Size > bytes.Length)
// Some error handling