New features in Ceras 3.0.2

Ceras 3.0.2 got released on NuGet, and there are a lot of new features.
A few things from the previous post didn’t make it, but the most important stuff (the things you’re probably most excited about) did 😀

Word of warning though: This is release is a “breaking change“. Which means if you saved any data serialized using Ceras into a file, this new version won’t be able to load it. Yeah, I know, breaking changes suck a bit, but they’re worth the performance improvements! 🙂 Also, upgrading your data is easy, just load the data using the old version, then save it using the new version, that’s it. This will most likely be the last breaking change though!

Changelog

  • Massive performance improvements
    After implementing all the most wanted features I started a big optimization run, and the results are pretty intense.
    Earlier benchmarks with other serializers (for example ‘MessagePack-CSharp’) had Ceras at ~3.9x the time taken compared to the fastest.
    That was obviously pretty slow. But then again, Ceras also does one hell of a lot more than other serializers.
    Anyway, after all the optimizations in the last days and weeks we’re now the fastest; improving our old time-factor to roughly ~0.9x compared to MessagePack-CSharp!
    That’s a huge improvement.
    I encourage you to run the benchmarks yourself though. Every situation is different, and your own data, settings, CPU, and requirements might change things a lot.

  • Unity Formatters
    Yes, full support for every commonly used type in UnityEngine. In order to use it, just copy the whole Extension.cs into your Unity project.
    If you’re a complete beginner then you probably want to read the few sentence I wrote into the readme file here as well.

  • Improved dependency injection for custom IFormatters
    In the previous version – if you wanted to reference other formatters – you always had to have field types like IFormatter<...> which made it impossible to get a specific type of formatter and thus also had a (small) impact on performance (since the runtime needed to do an interface dispatch).
    Now you can explicitly request a formatter type like public Int32Formatter IntFormatter;.
    This is especially useful if you have multiple custom formatters that you provide to Ceras and you want them to be able to reference each other directly.

  • Formatter constructed types
    Continuing on with custom IFormatter<> implementations. In the past there was no way to let Ceras deserialize types that have no public parameterless constructor because it always wants to give you an instance. Now you can explicitly mark types as constructed by the formatter by calling:
    CerasSerializer.AddFormatterConstructedType(type);
    That will make it so Ceras will no longer construct this type, so you can do it yourself in your custom IFormatter.
    Very useful when dealing with immuable types!

  • Capacity constructors
    As you know List<>, Dictionary<>, and some more collections have a constructor that takes a “capacity” argument, which makes populating the collection much more efficient if you know how many entries it will get beforehand.
    Ceras will now take advantage of those constructors and use them whenever possible; resulting in another performance improvement!

  • Advanced Settings
    In order to keep the already pretty large SerializerConfig from completely overwhelming beginners, many settings have been moved into the .Advanced sub-group.
    That’s really all there is to it. If you’re missing anything now, it has been moved there.

  • Support for Tuple<...> and ValueTuple<...>
    Previously Ceras’ powerful DynamicObjectFormatter handled those two types, but that could cause problems in some rare scenarios (where you’d set an incompatible DefaultTargets), which you could only resolve by manually specifying the rules for those types. None of those workarounds are needed anymore!

  • Size limits
    To protect against corrupted/malicious data, Ceras now has settings to limit how large content can be.
    Take a look at config.Advanced.SizeLimits, there you can limit how large strings, arrays, collections and byte-arrays (as a special case) are allowed to be.
    Any inputs that exceed those limits will trigger an exception.

  • Preserve References
    As you know Ceras perfectly handles full object-graphs, meaning automatically does things like maintaining object identity/references, resolving and handling circular references, …
    However getting some feedback I realized that many people actually don’t really need that much functionality, and would like to be able to trade those features for more performance. So now you can!
    By setting config.PreserveReferences = false; Ceras will become like most other serializers (becoming a “tree-serializer”).
    This skips over some code related to reference handling and give you a small performance boost.
    But it obviously comes with the downsides of such an approach as well (which is simply crashing with a StackOverflowException should the object you’re serializing have any “reference loops”).

  • NonSerializedAttribute
    Ceras now respects the [NonSerialized] attribute.
    In order to restore the old funcionality (where Ceras simply ignores the attribute) you can simply set config.RespectNonSerializedAttribute = false;.

  • Improved readonly field handling
    Those improvements are mostly internal, but I thought I’d just include them as well.
    Most of you have been using the Members mode of the readonly field handling feature (which just overwrites the content of a class, where just the reference to the class itself is readonly). For this scenario I’ve managed to improve the performance a bit and got rid of all allocations.
    The ForcedOverwrite (where readonly fields are serialized and deserialized as if they were not readonly at all) nothing has changed.

  • Delegate Serialization
    Ceras can now serialize delegates.
    There are some reasonable limitations to it, so if you actually have a more advance use-case, then let me know!
    This new feature also comes with a setting to turn the functionality on or off (off being the default for security reasons).

There are some features that didn’t make it. Luckily those were just minor ones:

  • Static object pooling surprisingly turned out to (mostly) not be worth the effort. Maybe I’ll revisit that idea later.
  • For the so called “Merge batching” it turns out that this idea would break custom formatters, so no luck there. Maybe I’ll find a way to make it work later.
New features in Ceras 3.0.2

Leave a Reply

Your email address will not be published.