Yes, the massive difference in timing is due to a number of different things, and we’re working on them at the moment. We’ll do a post about the timings we were able to achieve this week. Here are some of the things to keep in mind:
- JsonUtility operates on the native side and has direct access to Mono types, so it will be very hard to beat, but we’re confident we can get it down to something in the 2x-3x range for the same use-cases.
- Because we support streaming data in, we were using safe views over the data pretty much everywhere. In the cases where we deserialize from a complete Json string, we can use unsafe views over the data. This shaved off quite a lot of time.
- Reading/loading in memory and tokenizing is very fast and is on par with what JsonUtility can do. This is because we are using Burst to do this part.
- Having the Jobs debugger, the safety checks and leak detection on will chip at our results in the editor. Same goes for the profiler, of course.
- Creating new instances and transferring the data in those take the bulk of the time, because we cannot use Burst here, since we are dealing with arbitrary types. This is where JsonUtility will outperform us. We’ll optimize this part as much as possible, but as this is a C# only library, we’ll be bound by its limitations as well. Deserializing into an existing instance will most likely help a lot.
- This last step is done using another library, which is being re-written and should be more performant as well.
On top of all of the above, there are some design decisions that we took that we believe will add more flexibility and more features, at the cost of some overhead.
Polymorphic serialization
We decided to include this from the start. The overhead here is evident, as we need to ensure that we create new instances of the correct type. JsonUtility only supports this for UnityEngine.Object types.
Enhanced collection support
We decided to support more collection types and with the next version, we’ll be able to support lists, arrays, dictionaries and hash sets. This also includes nesting collection types.
Support for generic types
Since we are not tied to current Unity serialization, we can more easily dig in generic types.
Separation between serialization and UI
JsonUtility is tied to the way Unity is serializing the data, which means it is also tied to what would be shown in the default inspector. With this library, we’ll be able to separate the two cleanly, even though the default behavior will resemble what Unity does today. For example, you could mark a field to be serialized and use a property for UI, so that you can validate the data in a more natural way.
Migration support
Migration is currently possible in Unity at the engine level and through a limited number of attributes (i.e.: FormerlySerializedAs), but general migration is somewhat lacking for users.
We aim to allow users to control how their data change across time. We’ll support name changes, moving types to a different assembly/namespace, type changes and type conversions and manual migration. Not all of these will be supported at first, but this is the direction we are going.
Validation
When parsing the Json file, we can run different levels of validation to ensure that it is, in fact, a valid Json string or file. In the case of an error, we can output where the errors were found (line and character) as expected.
During deserialization, we can also inform the users about different problems that may have occurred, such as an instance could not be created because no default or implicit constructor was found, as well as give an indication as to how users can fix this problem.
Streaming
The low level parser is designed as a hybrid between SAX (forward-only read) and DOM (document-object-model). This gives us the ability to stream in large amounts of data while still working with discrete chunks.
Low-Level support
While we provide some high-level APIs to make it very easy to use, users are able to use the SerializedObjectReader to do custom deserialization by walking the tokens manually.
The in memory views returned from the reader can be consumed in bursted jobs for more specialized code paths.
Most of the above will add overhead compared to JsonUtility, but we believe these features are worth it.
As mentioned above, we are rewriting one of the packages that this one depends on, so the next update will probably take some time.
Let us know what you think. 