Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

4,128 views

Published on

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

Published in: Technology
  • Be the first to comment

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

  1. 1. Work http://grani.jp/ Unity Private http://neue.cc/ @neuecc https://github.com/neuecc/UniRx
  2. 2. ZeroFormatter
  3. 3. Why...?
  4. 4. Lazy/Delayed
  5. 5. Infinitely Fast Serializer https://github.com/neuecc/ZeroFormatter/ Fast Serialize as well
  6. 6. Benchmark
  7. 7. Benchmarks written by others
  8. 8. Serialization Process
  9. 9. 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; } }
  10. 10. // Example of standard serializer API byte[] Serialize<T>(T obj) { // 1. new MemoryStream for write to binary using(var stream = new MemoryStream()) // 2. new Writer for keep internal state var 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 integer if(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[] copy memoryStream.ToArray(); }
  11. 11. // Example of standard serializer API byte[] Serialize<T>(T obj) { // 1. new MemoryStream for write to binary using(var stream = new MemoryStream()) // 2. new Writer for keep internal state var 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 integer if(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[] copy memoryStream.ToArray(); } It’s too slow!!! and many garbage!
  12. 12. // Case of ZeroFormatter byte[] Serialize<T>(T obj) { // 1. Get child serializer form static variable var formatter = Formatter<DefaultResolver, T>.Default; // 2. no boxing, all internal structures are generics formatter.Serialize(T value); // 3. create static length byte[] when length is known var 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; }
  13. 13. 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); }
  14. 14. 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 int for (int i = 0; i < values.Length; i++) { stream.Write(serialize(values[i])); }

×