How to make the Fastest C# Serializer, In the case of ZeroFormatter

18

Transcript of How to make the Fastest C# Serializer, In the case of ZeroFormatter

Page 1: How to make the Fastest C# Serializer, In the case of ZeroFormatter
Page 2: 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

Page 3: How to make the Fastest C# Serializer, In the case of ZeroFormatter

ZeroFormatter

Page 4: How to make the Fastest C# Serializer, In the case of ZeroFormatter
Page 5: How to make the Fastest C# Serializer, In the case of ZeroFormatter

Why...?

Page 6: How to make the Fastest C# Serializer, In the case of ZeroFormatter
Page 7: How to make the Fastest C# Serializer, In the case of ZeroFormatter

Lazy/Delayed

Page 8: How to make the Fastest C# Serializer, In the case of ZeroFormatter

Infinitely Fast Serializer

https://github.com/neuecc/ZeroFormatter/

Fast Serialize as well

Page 9: How to make the Fastest C# Serializer, In the case of ZeroFormatter

Benchmark

Page 10: How to make the Fastest C# Serializer, In the case of ZeroFormatter
Page 11: How to make the Fastest C# Serializer, In the case of ZeroFormatter

Benchmarks written by others

Page 12: How to make the Fastest C# Serializer, In the case of ZeroFormatter

Serialization Process

Page 13: How to make the Fastest C# Serializer, In the case of ZeroFormatter

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;}

}

Page 14: How to make the Fastest C# Serializer, In the case of ZeroFormatter

// 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();

}

Page 15: How to make the Fastest C# Serializer, In the case of ZeroFormatter

// 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!

Page 16: How to make the Fastest C# Serializer, In the case of ZeroFormatter

// 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;

}

Page 17: How to make the Fastest C# Serializer, In the case of ZeroFormatter

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);

}

Page 18: How to make the Fastest C# Serializer, In the case of ZeroFormatter

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]));}