Giter Club home page Giter Club logo

netserializer's Introduction

NetSerializer - A fast, simple serializer for .Net

NetSerializer is a simple and very fast serializer for .Net languages. It is
the fastest serializer I have found for my use cases.

The main pros of NetSerializer are:

- Excellent for network serialization
- Supports classes, structs, enums, interfaces, abstract classes
- No versioning or other extra information is serialized, only pure data
- No type IDs for primitive types, structs or sealed classes, so less data to
  be sent
- No dynamic type lookup for primitive types, structs or sealed classes, so
  deserialization is faster
- No extra attributes needed (like DataContract/Member), just add the standard
  [Serializable]
- Thread safe without locks
- The data is written to the stream and read from the stream directly, without
  the need for temporary buffers or large buffers

The simpleness of NetSerializer has a drawback which must be considered by the
user: no versioning or other meta information is sent, which means that the
sender and the receiver have to have the same versions of the types being
serialized.  This means that it's a bad idea to save the serialized data for
longer periods of time, as a version upgrade could make the data
non-deserializable.  For this reason I think the best (and perhaps only) use
for NetSerializer is for sending data over network, between a client and a
server which have verified version compatibility when the connection is made.

Supported Types

NetSerializer supports serializing the following types:

- All primitive types (Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32,
  Int64, UInt64, IntPtr, UIntPtr, Char, Double, and Single)
- Strings
- Enums
- Single dimensional arrays
- Structs and classes marked as [Serializable]. Note that NetSerializer does
  _not_ support ISerializable, so not all classes marked with [Serializable]
  are supported.  However, NetSerializer has special support for the following
  ISerializable classes:
- Dictionary<K,V>
- DateTime

NetSerializer also supports creating custom serializers. Custom serializers can
be used to serialize types not directly supported by NetSerializer.

Usage

Usage is simple. The types to be serialized need to be marked with the standard
[Serializable].  You can also use [NonSerialized] for fields you don't want to
serialize. Nothing else needs to be done for the types to be serialized.

Then you need to initialize NetSerializer by giving it a list of types you will
be serializing. NetSerializer will scan through the given types, and
recursively add all the types used by the given types, and create
(de)serialization code.

Initialization:

	var ser = new Serializer(types);

Serializing:

	ser.Serialize(stream, ob);

Deserializing:

	(YourType)ser.Deserialize(stream);


Performance

Below is a performance comparison between NetSerializer and protobuf-net.
Protobuf-net is a fast Protocol Buffers compatible serializer, which was the
best serializer I could find out there when I considered the serializer for
my use case.

The table lists the time it takes run the test, the number of GC collections
(per generation) that happened during the test, and the size of the
outputted serialized data (when available).

There are three tests:

- MemStream Serialize - serializes an array of objects to a memory stream.

- MemStream Deserialize - deserializes the stream created with MemStream
  Serialize test.

- NetTest - uses two threads, of which the first one serializes objects and
  sends them over a local socket, and the second one receive the data and
  deserialize the objects. Note that the size is not available for NetTest, as
  tracking the sent data is not trivial. However, the dataset is the same as
  with MemStream, an so is the size of the data.

The tests are ran for different kinds of datasets. These datasets are composed
of objects of the same type. However, each object is initialized with random
data. The types used in the datasets are:

- U8Message - contains a single byte field
- S16Message - contains a single short field
- S32Message - contains a single int field
- S64Message - contains a single long field
- PrimitivesMessage - contains multiple fields of primitive types
- DictionaryMessage - contains a few Dictionaries
- ComplexMessage - contains fields with interface and abstract references
- StringMessage - contains random length string
- StructMessage - contains a few structs
- ByteArrayMessage - contains random length byte array
- IntArrayMessage - contains random length int array

The details of the tests can be found from the source code. The tests were run
on a 64bit Windows 10 laptop.


                                      |  time (ms) |    GC coll. |   size (B) |
== 6000000 U8Message ==
NetSerializer | MemStream Serialize   |        369 |   0   0   0 |   12000000 |
NetSerializer | MemStream Deserialize |        987 |  24  12   1 |            |
NetSerializer | NetTest               |       1253 |  24  12   1 |            |
protobuf-net  | MemStream Serialize   |       1692 | 289   0   0 |   31084229 |
protobuf-net  | MemStream Deserialize |       3645 |  24  12   1 |            |
protobuf-net  | NetTest               |       4506 | 170  43   1 |            |

== 6000000 S16Message ==
NetSerializer | MemStream Serialize   |        468 |   0   0   0 |   20427894 |
NetSerializer | MemStream Deserialize |       1203 |  24  12   1 |            |
NetSerializer | NetTest               |       1341 |  24  12   1 |            |
protobuf-net  | MemStream Serialize   |       1734 | 289   0   0 |   52482244 |
protobuf-net  | MemStream Deserialize |       3651 |  24  12   1 |            |
protobuf-net  | NetTest               |       4416 | 169  43   1 |            |

== 6000000 S32Message ==
NetSerializer | MemStream Serialize   |        498 |   0   0   0 |   27982635 |
NetSerializer | MemStream Deserialize |       1223 |  24  12   1 |            |
NetSerializer | NetTest               |       1421 |  24  12   1 |            |
protobuf-net  | MemStream Serialize   |       1750 | 289   0   0 |   51654177 |
protobuf-net  | MemStream Deserialize |       3699 |  24  12   1 |            |
protobuf-net  | NetTest               |       4494 | 170  43   1 |            |

== 5000000 S64Message ==
NetSerializer | MemStream Serialize   |        454 |   0   0   0 |   27502929 |
NetSerializer | MemStream Deserialize |       1015 |  19   9   0 |            |
NetSerializer | NetTest               |       1226 |  20  10   1 |            |
protobuf-net  | MemStream Serialize   |       1497 | 241   0   0 |   40624074 |
protobuf-net  | MemStream Deserialize |       3068 |  19   9   0 |            |
protobuf-net  | NetTest               |       3769 | 142  36   1 |            |

== 1000000 PrimitivesMessage ==
NetSerializer | MemStream Serialize   |        830 |  14   2   2 |   52288890 |
NetSerializer | MemStream Deserialize |        944 |  19   6   0 |            |
NetSerializer | NetTest               |       1231 |  26   7   1 |            |
protobuf-net  | MemStream Serialize   |        800 |  50   2   2 |   72591287 |
protobuf-net  | MemStream Deserialize |       1131 |  13   6   0 |            |
protobuf-net  | NetTest               |       1392 |  38  10   1 |            |

== 5000 DictionaryMessage ==
NetSerializer | MemStream Serialize   |        704 |  18   0   0 |   42731220 |
NetSerializer | MemStream Deserialize |       1231 |  53  19   1 |            |
NetSerializer | NetTest               |       1727 |  65  22   1 |            |
protobuf-net  | MemStream Serialize   |       1024 | 105   0   0 |   71101535 |
protobuf-net  | MemStream Deserialize |       3086 | 115  31   1 |            |
protobuf-net  | NetTest               |       2761 | 217  39   0 |            |

== 1000000 ComplexMessage ==
NetSerializer | MemStream Serialize   |        775 |   0   0   0 |   27997927 |
NetSerializer | MemStream Deserialize |       1011 |  26  13   1 |            |
NetSerializer | NetTest               |       1220 |  26  12   1 |            |
protobuf-net  | MemStream Serialize   |        913 |  48   0   0 |   50853349 |
protobuf-net  | MemStream Deserialize |       2142 |  26  12   1 |            |
protobuf-net  | NetTest               |       2374 |  51  18   1 |            |

== 600000 StringMessage ==
NetSerializer | MemStream Serialize   |        163 |   0   0   0 |   30905071 |
NetSerializer | MemStream Deserialize |        331 |  14   6   0 |            |
NetSerializer | NetTest               |        441 |  15   8   1 |            |
protobuf-net  | MemStream Serialize   |        308 |  30   1   1 |   32105223 |
protobuf-net  | MemStream Deserialize |       1321 |  14   6   0 |            |
protobuf-net  | NetTest               |        798 |  30   9   1 |            |

== 2000000 StructMessage ==
NetSerializer | MemStream Serialize   |        598 |   0   0   0 |   50560829 |
NetSerializer | MemStream Deserialize |       1153 |  31  15   1 |            |
NetSerializer | NetTest               |       1387 |  32  16   1 |            |
protobuf-net  | MemStream Serialize   |       1448 | 138   1   1 |   74056319 |
protobuf-net  | MemStream Deserialize |       5379 |  72  19   1 |            |
protobuf-net  | NetTest               |       3106 | 142  46   0 |            |

== 5000 ByteArrayMessage ==
NetSerializer | MemStream Serialize   |        294 |   1   1   1 |  249332892 |
NetSerializer | MemStream Deserialize |        141 |  29  15   1 |            |
NetSerializer | NetTest               |        430 |  30  14   1 |            |
protobuf-net  | MemStream Serialize   |        654 |  88   6   3 |  249366259 |
protobuf-net  | MemStream Deserialize |        160 |  29  15   1 |            |
protobuf-net  | NetTest               |        735 |  90  21   2 |            |

== 800 IntArrayMessage ==
NetSerializer | MemStream Serialize   |       1153 |   0   0   0 |  147703547 |
NetSerializer | MemStream Deserialize |        863 |   1   0   0 |            |
NetSerializer | NetTest               |       1540 |   1   0   0 |            |
protobuf-net  | MemStream Serialize   |       1431 |  33   3   2 |  236205801 |
protobuf-net  | MemStream Deserialize |       1334 |  21   2   0 |            |
protobuf-net  | NetTest               |       2001 |  52   3   2 |            |

As can be seen from the tests, NetSerializer is clearly faster and has smaller
memory footprint in about all of the cases. For example, the tests with
ComplexMessages show NetSerializer's MemStream Serialize cause zero garbage
collections, even though more than 20MB of data is being serialized.

netserializer's People

Contributors

pchalamet avatar tomba avatar visubesy avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.