Very fast JSON serializer for .NET
Writing directly to byte sequences (byte*
or Stream
) rather than TextWriter
allows this JSON serializer to achieve the speed of binary serializers.
// Easiest serialization method
void Serializer.Serialize<T>(T item, Stream destination, byte[] buffer)
// Fastest serialization method
int Serializer.Serialize<T>(T item, byte* destination, int available)
Deserialization is not currently supported, I recommend Jil for your deserialization needs.
Array with integers 0 through 1024, 1024 times
Serializer | Average Milliseconds |
---|---|
Cameronism.Json | 9 |
Jil | 41 |
ProtoBuf | 170 |
Newtonsoft | 179 |
Array with integers 0 through 1024 as strings, 1024 times
Serializer | Average Milliseconds |
---|---|
Cameronism.Json | 24 |
Jil | 85 |
ProtoBuf | 107 |
Newtonsoft | 134 |
Dictionary with 1 million small objects
Serializer | Average Milliseconds |
---|---|
Cameronism.Json | 415 |
ProtoBuf | 889 |
Jil | 1230 |
Newtonsoft | 3195 |
Small object:
new
{
SessionId = Guid.NewGuid(),
Timestamp = DateTime.UtcNow,
UserAgent = i + "/" + i,
PageId = (uint)i,
Options = new Dictionary<string,string>(),
Groups = new List<GroupInfo>(),
}
Stream Usage:
var stuffToSerialize = GetSomeStuff();
Stream destination = GetDestinationStream();
byte[] buffer = GetReusedBuffer();
Serializer.Serialize(stuffToSerialize, destination, buffer);
// destination now has the JSON
Pointer Usage:
var stuffToSerialize = GetSomeStuff();
byte[] buffer = GetReusedBuffer();
int position;
unsafe
{
fixed (byte* ptr = buffer)
{
position = Serializer.Serialize(stuffToSerialize, ptr, buffer.Length);
}
}
if (position < 0) return; // buffer was too small
/* buffer now has the JSON */
// copy it elsewhere
otherStream.Write(buffer, 0, position);
// or create a stream of your own
var myStream = new MemoryStream(buffer, 0, position);
// or get the string version of the JSON
string debug = Encoding.UTF8.GetString(buffer, 0, position);
// if you need a string for more than debugging, use a TextWriter based serializer like Jil
BufferManager is an option for reusing buffers.
Serialize may be also be called with an UnmanagedMemoryStream. MemoryMappedFile can be used to get an unmanaged stream for a file on disk (or not on disk at all).
PM> Install-Package Cameronism.Json
TODO Show the logger
TODO Show logger benchmarks
No deserialization (use Jil or Newtonsoft)
- string
- from
System.String
writer done - from
System.Char
writer done - from
System.Guid
writer done, only the "D" format - from
System.DateTime
writer done, only ISO8601 - from
System.DateTimeOffset
TODO - from
System.Net.IPAddress
handled by delegate generator, very Windows specific - from
byte[]
done, base64 - from enum
- FlagAttribute
TODO - non flag
TODO
- FlagAttribute
- from
- number
- from
System.Int32
writer done - from
System.UInt32
writer done - from
System.Int16
cast toInt32
, probably not worth special case - from
System.UInt16
cast toUInt32
, probably not worth special case - from
System.Byte
cast toUInt32
, probably not worth special case - from
System.SByte
cast toInt32
, probably not worth special case - from
System.Int64
writer done - from
System.UInt64
writer done - from
System.Double
writer done, wastefully uses ToString - from
System.Single
writer done, wastefully uses ToString - from
System.Decimal
writer done, wastefully uses ToString - from
System.DateTime
TODO - from enum
handled by delegate generator
- from
- object
- from type composed of other supported types
handled by delegate generator - from
IDictionary<TKey, TValue>
- string TKey
handled by delegate generator - enum TKey
TODO
- string TKey
- from type composed of other supported types
- array
- from array
handled by delegate generator - from
IEnumerable<>
handled by delegate generator
- from array
- true
- from
System.Boolean
writer done
- from
- false
- from
System.Boolean
writer done
- from
- null
- from
System.String
writer done - from
System.Nullable<>
handled by delegate generator for primitives and non-dictionary objects
- from
- Not TextWriter based,
byte*
based - Member order
TODO - Whitespace for 8 byte alignment
TODO - Inline constant properties Properties that return a constant will not be called, the serialized value will be calculated when generating serialization method
- Test for inlined constant properties around stream boundaries
- Better return value when insufficient space
- object serializer
- currently just doubles original avail param
member result - minLength
might be sufficient- should decrease available before serializing member, save some room for following members
- object serializer
- Minimum length (and maybe reserved length) per schema
DateTime and Guid are JSON type string but we know a lot more about their length than the general string case - Call Dispose on enumerators
- Performance test array with unrolled first iteration