How to make the Fastest C# Serializer, In the case of ZeroFormatter
-
Upload
yoshifumi-kawai -
Category
Technology
-
view
472 -
download
4
Transcript of How to make the Fastest C# Serializer, In the case of ZeroFormatter
Work
http://grani.jp/
Unity
Private
http://neue.cc/
@neuecc
https://github.com/neuecc/UniRx
ZeroFormatter
Why...?
Lazy/Delayed
Infinitely Fast Serializer
https://github.com/neuecc/ZeroFormatter/
Fast Serialize as well
Benchmark
Benchmarks written by others
Serialization Process
For example, convert int(999) to byte[]
var bytes = BitConverter.GetBytes(999);
unsafe{
var bytes = new byte[4];fixed (byte* ptr = bytes){
*((int*)ptr) = 999;}
}
// Example of standard serializer APIbyte[] Serialize<T>(T obj){
// 1. new MemoryStream for write to binaryusing(var stream = new MemoryStream())
// 2. new Writer for keep internal statevar writer = new XxxWriter(stream);
// 3. get inner serializer or switch(when primitive)var serializer = serializerCacheDictionary[typeof(T)];
// 4. boxing!serializer.WriteObject(writer, (object)obj);
// 5. encode for variable-length integerif(x <10) write... else if(x < 150) write...
// 6. Many WriteByte(if, increment, etc...)stream.WriteByte(byte >> 0); stream.WriteByte(byte >> 8) ...
// 7. ToArray is byte[] copymemoryStream.ToArray();
}
// Example of standard serializer APIbyte[] Serialize<T>(T obj){
// 1. new MemoryStream for write to binaryusing(var stream = new MemoryStream())
// 2. new Writer for keep internal statevar writer = new XxxWriter(stream);
// 3. get inner serializer or switch(when primitive)var serializer = serializerCacheDictionary[typeof(T)];
// 4. boxing!serializer.WriteObject(writer, (object)obj);
// 5. encode for variable-length integerif(x <10) write... else if(x < 150) write...
// 6. Many WriteByte(if, increment, etc...)stream.WriteByte(byte >> 0); stream.WriteByte(byte >> 8) ...
// 7. ToArray is byte[] copymemoryStream.ToArray();
}
It’s too slow!!!and many garbage!
// Case of ZeroFormatterbyte[] Serialize<T>(T obj){
// 1. Get child serializer form static variablevar formatter = Formatter<DefaultResolver, T>.Default;
// 2. no boxing, all internal structures are genericsformatter.Serialize(T value);
// 3. create static length byte[] when length is knownvar bytes = new byte[formatter.GetLength()];
// 4. Write byte[] directry(WriteInt32 is *((int*)b) = value; )BinaryUtil.WriteInt32(ref bytes, value);
// 5. only returns byte[]return bytes;
}
Minimal Abstraction
public abstract class Formatter<TTypeResolver, T>where TTypeResolver : ITypeResolver, new()
{public abstract int? GetLength();public abstract int Serialize(ref byte[] bytes, int offset, T value);public abstract T Deserialize(ref byte[] bytes, int offset, out int byteSize);
}
internal class Int32ArrayFormatter : Formatter<Int32[]>{
public override int Serialize(ref byte[] bytes, int offset, Int32[] value){
var writeSize = value.Length * 4;BinaryUtil.EnsureCapacity(ref bytes, offset, writeSize + 4);BinaryUtil.WriteInt32Unsafe(ref bytes, offset, value.Length);Buffer.BlockCopy(value, 0, bytes, offset + 4, writeSize);
return writeSize + 4;}
}
// For example, in the case of int []// it usually becomes a code that processes each element of intfor (int i = 0; i < values.Length; i++){
stream.Write(serialize(values[i]));}